egison 4.0.3 → 4.1.0
raw patch · 105 files changed
+6541/−5810 lines, 105 filesdep +exceptionsdep +sweet-egisondep +unicode-showdep −deepseqdep −mini-egisondep ~mtl
Dependencies added: exceptions, sweet-egison, unicode-show
Dependencies removed: deepseq, mini-egison
Dependency ranges changed: mtl
Files
- benchmark/Benchmark.hs +7/−8
- egison.cabal +23/−8
- hs-src/Interpreter/egison.hs +103/−108
- hs-src/Language/Egison.hs +32/−97
- hs-src/Language/Egison/AST.hs +189/−247
- hs-src/Language/Egison/CmdOptions.hs +25/−16
- hs-src/Language/Egison/Completion.hs +23/−41
- hs-src/Language/Egison/Core.hs +1084/−1363
- hs-src/Language/Egison/Data.hs +112/−275
- hs-src/Language/Egison/Data/Collection.hs +117/−0
- hs-src/Language/Egison/Data/Utils.hs +78/−0
- hs-src/Language/Egison/Desugar.hs +380/−285
- hs-src/Language/Egison/Eval.hs +169/−0
- hs-src/Language/Egison/EvalState.hs +59/−0
- hs-src/Language/Egison/IExpr.hs +165/−0
- hs-src/Language/Egison/IState.hs +0/−66
- hs-src/Language/Egison/Match.hs +67/−0
- hs-src/Language/Egison/Math.hs +33/−0
- hs-src/Language/Egison/Math/Arith.hs +51/−0
- hs-src/Language/Egison/Math/Expr.hs +281/−0
- hs-src/Language/Egison/Math/Normalize.hs +128/−0
- hs-src/Language/Egison/Math/Rewrite.hs +208/−0
- hs-src/Language/Egison/MathExpr.hs +0/−351
- hs-src/Language/Egison/MathOutput.hs +7/−10
- hs-src/Language/Egison/Parser.hs +49/−40
- hs-src/Language/Egison/Parser/NonS.hs +232/−276
- hs-src/Language/Egison/Parser/SExpr.hs +173/−189
- hs-src/Language/Egison/Pretty.hs +105/−188
- hs-src/Language/Egison/PrettyMath/AST.hs +80/−9
- hs-src/Language/Egison/PrettyMath/AsciiMath.hs +5/−5
- hs-src/Language/Egison/PrettyMath/Latex.hs +2/−2
- hs-src/Language/Egison/PrettyMath/Mathematica.hs +5/−5
- hs-src/Language/Egison/PrettyMath/Maxima.hs +5/−5
- hs-src/Language/Egison/Primitives.hs +69/−587
- hs-src/Language/Egison/Primitives/Arith.hs +167/−0
- hs-src/Language/Egison/Primitives/IO.hs +199/−0
- hs-src/Language/Egison/Primitives/String.hs +112/−0
- hs-src/Language/Egison/Primitives/Types.hs +126/−0
- hs-src/Language/Egison/Primitives/Utils.hs +102/−0
- hs-src/Language/Egison/RState.hs +61/−0
- hs-src/Language/Egison/Tensor.hs +198/−249
- hs-src/Language/Egison/Types.hs +0/−115
- hs-src/Tool/translator.hs +76/−85
- lib/core/assoc.egi +6/−6
- lib/core/base.egi +23/−19
- lib/core/collection.egi +83/−103
- lib/core/io.egi +15/−15
- lib/core/maybe.egi +1/−1
- lib/core/number.egi +36/−40
- lib/core/order.egi +18/−21
- lib/core/random.egi +12/−12
- lib/core/shell.egi +54/−49
- lib/core/sort.egi +44/−0
- lib/core/string.egi +20/−22
- lib/math/algebra/equations.egi +20/−20
- lib/math/algebra/inverse.egi +1/−1
- lib/math/algebra/matrix.egi +28/−33
- lib/math/algebra/root.egi +33/−37
- lib/math/algebra/tensor.egi +9/−6
- lib/math/algebra/vector.egi +6/−6
- lib/math/analysis/derivative.egi +11/−15
- lib/math/analysis/integral.egi +4/−4
- lib/math/common/arithmetic.egi +30/−26
- lib/math/common/constants.egi +1/−1
- lib/math/common/functions.egi +22/−22
- lib/math/expression.egi +112/−194
- lib/math/geometry/3d-euclidean-space.egi +2/−2
- lib/math/geometry/4d-euclidean-space.egi +2/−2
- lib/math/geometry/differential-form.egi +6/−6
- lib/math/geometry/minkowski-space.egi +2/−2
- lib/math/no-normalize.egi +7/−0
- lib/math/normalize.egi +13/−226
- sample/bellman-ford.egi +20/−0
- sample/chopsticks.egi +16/−16
- sample/chopsticks2.egi +3/−3
- sample/demo1-ja.egi +1/−1
- sample/demo1.egi +1/−1
- sample/generalized-sequential-pattern-mining.egi +18/−18
- sample/graph.egi +60/−0
- sample/ioRef.egi +2/−2
- sample/mahjong.egi +7/−7
- sample/math/geometry/curvature-form.egi +10/−10
- sample/math/geometry/hodge-laplacian-polar.egi +9/−9
- sample/math/geometry/riemann-curvature-tensor-of-S2.egi +13/−13
- sample/math/geometry/riemann-curvature-tensor-of-S5-non-sym.egi +54/−0
- sample/math/geometry/riemann-curvature-tensor-of-S5.egi +54/−0
- sample/math/geometry/riemann-curvature-tensor-of-T2-non-sym.egi +85/−0
- sample/math/geometry/riemann-curvature-tensor-of-T2.egi +29/−13
- sample/math/geometry/thurston-non-sym.egi +89/−0
- sample/math/geometry/thurston.egi +89/−0
- sample/math/number/17th-root-of-unity.egi +39/−39
- sample/math/number/tribonacci.egi +5/−7
- sample/n-queens.egi +23/−22
- sample/poker-hands-with-joker.egi +3/−3
- sample/poker-hands.egi +3/−3
- sample/primes.egi +2/−2
- sample/sat/cdcl.egi +27/−27
- sample/sat/dp.egi +5/−5
- sample/tree.egi +4/−4
- test/Test.hs +34/−31
- test/lib/core/collection.egi +12/−0
- test/lib/core/number.egi +4/−4
- test/lib/math/tensor.egi +8/−12
- test/primitive.egi +1/−3
- test/syntax.egi +83/−34
benchmark/Benchmark.hs view
@@ -1,20 +1,19 @@-{-# LANGUAGE FlexibleInstances #-} module Main where-import Control.Applicative ((<$>), (<*>))-import Control.Applicative-import Control.DeepSeq (NFData (rnf))-import Control.Monad.Except+ import Criterion import Criterion.Main import Language.Egison-import Language.Egison.CmdOptions runEgisonFile :: String -> IO ()-runEgisonFile path = initialEnv defaultOption >>= flip (loadEgisonFile defaultOption) path >> return ()+runEgisonFile path = evalRuntimeT defaultOption $ do+ env <- initialEnv+ _ <- loadEgisonFile env path+ return () main :: IO () main = defaultMainWith defaultConfig- [ bgroup "fact" [ bench "30000" $ nfIO $ runEgisonFile "benchmark/fact-30000.egi" ]+ [ bgroup "fact"+ [ bench "30000" $ nfIO $ runEgisonFile "benchmark/fact-30000.egi" ] , bgroup "collection" [ bench "cons-bench" $ nfIO $ runEgisonFile "benchmark/collection-bench-cons.egi" , bench "cons-bench-large" $ nfIO $ runEgisonFile "benchmark/collection-bench-cons-large.egi"
egison.cabal view
@@ -1,5 +1,5 @@ Name: egison-Version: 4.0.3+Version: 4.1.0 Synopsis: Programming language with non-linear pattern-matching against non-free data Description: An interpreter for Egison, a **pattern-matching-oriented**, purely functional programming language.@@ -95,7 +95,8 @@ , hashable , optparse-applicative , prettyprinter- , mini-egison >= 1.0.0+ , unicode-show+ , sweet-egison >= 0.1.0.2 if !impl(ghc > 8.0) Build-Depends: fail Hs-Source-Dirs: hs-src@@ -107,8 +108,17 @@ Language.Egison.Completion Language.Egison.Desugar Language.Egison.Data- Language.Egison.IState- Language.Egison.MathExpr+ Language.Egison.Data.Collection+ Language.Egison.Data.Utils+ Language.Egison.EvalState+ Language.Egison.Eval+ Language.Egison.IExpr+ Language.Egison.Match+ Language.Egison.Math.Arith+ Language.Egison.Math.Expr+ Language.Egison.Math.Normalize+ Language.Egison.Math.Rewrite+ Language.Egison.Math Language.Egison.MathOutput Language.Egison.MList Language.Egison.Parser@@ -121,8 +131,13 @@ Language.Egison.PrettyMath.Mathematica Language.Egison.PrettyMath.Maxima Language.Egison.Primitives+ Language.Egison.Primitives.Arith+ Language.Egison.Primitives.IO+ Language.Egison.Primitives.String+ Language.Egison.Primitives.Types+ Language.Egison.Primitives.Utils+ Language.Egison.RState Language.Egison.Tensor- Language.Egison.Types Other-modules: Paths_egison autogen-modules: Paths_egison ghc-options: -O3 -Wall -Wno-name-shadowing -Wno-incomplete-patterns@@ -144,6 +159,7 @@ , filepath Other-modules: Paths_egison autogen-modules: Paths_egison+ ghc-options: -Wall -Wno-name-shadowing Benchmark benchmark default-language: Haskell2010@@ -153,12 +169,10 @@ Build-Depends: egison , base >= 4.0 && < 5- , deepseq , criterion >= 0.5- , transformers- , mtl Other-modules: Paths_egison autogen-modules: Paths_egison+ ghc-options: -Wall -Wno-name-shadowing Executable egison default-language: Haskell2010@@ -168,6 +182,7 @@ , base >= 4.0 && < 5 , array , containers+ , exceptions , unordered-containers , haskeline , transformers
hs-src/Interpreter/egison.hs view
@@ -1,12 +1,11 @@ {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE TupleSections #-} module Main where -import Control.Exception (AsyncException (..), catch)+import Control.Exception (AsyncException (..))+import Control.Monad.Catch (catch) import Control.Monad.Except-import Control.Monad.Trans.State+import Control.Monad.Reader import Data.List (intercalate) import qualified Data.Text as T@@ -22,13 +21,9 @@ import Text.Regex.TDFA ((=~)) import Language.Egison-import Language.Egison.CmdOptions import Language.Egison.Completion-import Language.Egison.Core (evalTopExpr', recursiveBind)-import Language.Egison.Desugar-import Language.Egison.MathOutput-import qualified Language.Egison.Parser.SExpr as SExpr-import qualified Language.Egison.Parser.NonS as NonS+import Language.Egison.Eval+import Language.Egison.Parser (parseTopExpr) import Options.Applicative @@ -36,7 +31,7 @@ main = execParser cmdParser >>= runWithOptions isInValidMathOption :: EgisonOpts -> Bool-isInValidMathOption EgisonOpts{ optMathExpr = Just lang } = notElem lang ["asciimath", "latex", "mathematica", "maxima"]+isInValidMathOption EgisonOpts{ optMathExpr = Just lang } = lang `notElem` ["asciimath", "latex", "mathematica", "maxima", "haskell"] isInValidMathOption EgisonOpts{ optMathExpr = Nothing } = False runWithOptions :: EgisonOpts -> IO ()@@ -44,62 +39,77 @@ hPrint stderr (Default "this output lang is not supported") >> exitFailure runWithOptions EgisonOpts{ optShowVersion = True } = putStrLn (showVersion version) >> exitSuccess-runWithOptions opts = do- coreEnv <- initialEnv opts- mEnv <- evalEgisonTopExprs opts coreEnv $ map Load (optLoadLibs opts) ++ map LoadFile (optLoadFiles opts)+runWithOptions opts = evalRuntimeT opts run++run :: RuntimeM ()+run = do+ opts <- ask+ coreEnv <- initialEnv+ mEnv <- fromEvalT $ evalTopExprs coreEnv $ map Load (optLoadLibs opts) ++ map LoadFile (optLoadFiles opts) case mEnv of- Left err -> print err- Right env ->- case opts of- -- Evaluate the given string- EgisonOpts { optEvalString = Just expr }- | optTsvOutput opts ->- executeEgisonTopExpr opts env $ "execute (each (\\x -> print (showTsv x)) (" ++ expr ++ "))"- | otherwise -> do- executeEgisonTopExpr opts env $ "execute (print (show (" ++ expr ++ ")))"- -- Execute the given string- EgisonOpts { optExecuteString = Just cmd } ->- executeEgisonTopExpr opts env $ "execute (" ++ cmd ++ ")"- -- Operate input in tsv format as infinite stream- EgisonOpts { optSubstituteString = Just sub } ->- let (sopts, copts) = unzip (optFieldInfo opts)- sopts' = "[" ++ intercalate ", " sopts ++ "]"- copts' = "[" ++ intercalate ", " copts ++ "]"- expr = "load \"lib/core/shell.egi\"\n"- ++ "execute (let SH.input := SH.genInput " ++ sopts' ++ " " ++ copts' ++ "\n"- ++ " in each (\\x -> print (" ++ if optTsvOutput opts then "showTsv" else "show" ++ " x)) (" ++ sub ++ " SH.input))"- in executeEgisonTopExpr opts env expr- -- Execute a script (test only)- EgisonOpts { optTestOnly = True, optExecFile = Just (file, _) } -> do- result <- if optNoIO opts- -- TODO: Switch parsers by file extension- then do input <- readFile file- runEgisonTopExprs opts env input- else evalEgisonTopExprs opts env [LoadFile file]- either print (const $ return ()) result- -- Execute a script from the main function- EgisonOpts { optExecFile = Just (file, args) } -> do- result <- evalEgisonTopExprs opts env [LoadFile file, Execute (ApplyExpr (stringToVarExpr "main") (CollectionExpr (map ((ElementExpr . StringExpr) . T.pack) args)))]- either print (const $ return ()) result- -- Start the read-eval-print-loop- _ -> do- when (optShowBanner opts) showBanner- repl opts env- when (optShowBanner opts) showByebyeMessage- exitSuccess+ Left err -> liftIO $ print err+ Right env -> handleOption env opts -executeEgisonTopExpr :: EgisonOpts -> Env -> String -> IO ()-executeEgisonTopExpr opts env expr = do- cmdRet <- runEgisonTopExprs opts env expr+handleOption :: Env -> EgisonOpts -> RuntimeM ()+handleOption env opts =+ case opts of+ -- Evaluate the given string+ EgisonOpts { optEvalString = Just expr } ->+ runAndPrintExpr env expr+ -- Execute the given string+ EgisonOpts { optExecuteString = Just cmd } ->+ executeTopExpr env $ "execute (" ++ cmd ++ ")"+ -- Operate input in tsv format as infinite stream+ EgisonOpts { optSubstituteString = Just sub } ->+ let (sopts, copts) = unzip (optFieldInfo opts)+ sopts' = "[" ++ intercalate ", " sopts ++ "]"+ copts' = "[" ++ intercalate ", " copts ++ "]"+ expr = "load \"lib/core/shell.egi\"\n"+ ++ "execute (let SH.input := SH.genInput " ++ sopts' ++ " " ++ copts' ++ "\n"+ ++ if optTsvOutput opts then " in each (\\x -> print (showTsv x)) ((" ++ sub ++ ") SH.input))"+ else " in each (\\x -> print (show x)) ((" ++ sub ++ ") SH.input))"+ in executeTopExpr env expr+ -- Execute a script (test only)+ EgisonOpts { optTestOnly = True, optExecFile = Just (file, _) } -> do+ exprs <- liftIO $ readFile file+ result <- if optNoIO opts+ then fromEvalT (runTopExprs env exprs)+ else fromEvalT (evalTopExprs env [LoadFile file])+ liftIO $ either print (const $ return ()) result+ -- Execute a script from the main function+ EgisonOpts { optExecFile = Just (file, args) } -> do+ result <- fromEvalT $ evalTopExprs env [LoadFile file, Execute (makeApply "main" (map (ConstantExpr . StringExpr . T.pack) args))]+ liftIO $ either print (const $ return ()) result+ EgisonOpts { optMapTsvInput = Just expr } ->+ handleOption env (opts { optSubstituteString = Just $ "\\x -> map (" ++ expr ++ ") x" })+ EgisonOpts { optFilterTsvInput = Just expr } ->+ handleOption env (opts { optSubstituteString = Just $ "\\x -> filter (" ++ expr ++ ") x" })+ -- Start the read-eval-print-loop+ _ -> do+ when (optShowBanner opts) (liftIO showBanner)+ repl env+ when (optShowBanner opts) (liftIO showByebyeMessage)+ liftIO exitSuccess++runAndPrintExpr :: Env -> String -> RuntimeM ()+runAndPrintExpr env expr = do+ isTsvOutput <- asks optTsvOutput+ if isTsvOutput+ then executeTopExpr env $ "execute (each (\\x -> print (showTsv x)) (" ++ expr ++ "))"+ else executeTopExpr env $ "execute (print (show (" ++ expr ++ ")))"++executeTopExpr :: Env -> String -> RuntimeM ()+executeTopExpr env expr = do+ cmdRet <- fromEvalT (runTopExprs env expr) case cmdRet of- Left err -> hPrint stderr err >> exitFailure- _ -> exitSuccess+ Left err -> liftIO $ hPrint stderr err >> exitFailure+ _ -> liftIO exitSuccess showBanner :: IO () showBanner = do putStrLn $ "Egison Version " ++ showVersion version- putStrLn $ "https://www.egison.org"- putStrLn $ "Welcome to Egison Interpreter!"+ putStrLn "https://www.egison.org"+ putStrLn "Welcome to Egison Interpreter!" -- putStrLn $ "** Information **" -- putStrLn $ "We can use the tab key to complete keywords on the interpreter." -- putStrLn $ "If we press the tab key after a closed parenthesis, the next closed parenthesis will be completed."@@ -108,69 +118,54 @@ showByebyeMessage :: IO () showByebyeMessage = putStrLn "Leaving Egison Interpreter." -repl :: EgisonOpts -> Env -> IO ()-repl opts env =- loop $ StateT (\defines -> (, defines) <$> recursiveBind env defines)- where- settings :: MonadIO m => FilePath -> Settings m- settings home = setComplete completeEgison $ defaultSettings { historyFile = Just (home </> ".egison_history"), autoAddHistory = False }+settings :: MonadIO m => FilePath -> Env -> Settings m+settings home env = setComplete (completeEgison env) $ defaultSettings { historyFile = Just (home </> ".egison_history"), autoAddHistory = False } - loop :: StateT [(Var, EgisonExpr)] EvalM Env -> IO ()- loop st = (do- home <- getHomeDirectory- input <- liftIO $ runInputT (settings home) $ getEgisonExpr opts- case (optNoIO opts, input) of- (_, Nothing) -> return ()- (True, Just (LoadFile _)) -> do- putStrLn "error: No IO support"- loop st- (True, Just (Load _)) -> do- putStrLn "error: No IO support"- loop st- (_, Just topExpr) -> do- result <- liftIO $ fromEvalM (desugarTopExpr topExpr >>= evalTopExpr' opts st)- case result of- Left err -> liftIO (print err) >> loop st- Right (Nothing, st') -> loop st'- Right (Just output, st') ->- case optMathExpr opts of- Nothing -> putStrLn output >> loop st'- Just lang -> putStrLn (changeOutputInLang lang output) >> loop st'- )- `catch`- (\case- UserInterrupt -> putStrLn "" >> loop st- StackOverflow -> putStrLn "Stack over flow!" >> loop st- HeapOverflow -> putStrLn "Heap over flow!" >> loop st- _ -> putStrLn "error!" >> loop st- )+repl :: Env -> RuntimeM ()+repl env = (do+ home <- liftIO getHomeDirectory+ input <- runInputT (settings home env) getEgisonExpr+ case input of+ Nothing -> return ()+ Just topExpr -> do+ result <- fromEvalT (evalTopExprStr env topExpr)+ case result of+ Left err -> liftIO (print err) >> repl env+ Right (Just str, env') -> liftIO (putStrLn str) >> repl env'+ Right (Nothing, env') -> repl env'+ )+ `catch`+ (\case+ UserInterrupt -> liftIO (putStrLn "") >> repl env+ StackOverflow -> liftIO (putStrLn "Stack over flow!") >> repl env+ HeapOverflow -> liftIO (putStrLn "Heap over flow!") >> repl env+ _ -> liftIO (putStrLn "error!") >> repl env+ ) -- |Get Egison expression from the prompt. We can handle multiline input.-getEgisonExpr :: EgisonOpts -> InputT IO (Maybe EgisonTopExpr)-getEgisonExpr opts = getEgisonExpr' opts ""+getEgisonExpr :: InputT RuntimeM (Maybe TopExpr)+getEgisonExpr = getEgisonExpr' "" where- getEgisonExpr' opts prev = do+ getEgisonExpr' prev = do+ opts <- lift ask mLine <- case prev of "" -> getInputLine $ optPrompt opts _ -> getInputLine $ replicate (length $ optPrompt opts) ' ' case mLine of Nothing -> return Nothing- Just [] ->- if null prev- then getEgisonExpr opts- else getEgisonExpr' opts prev+ Just [] | null prev -> getEgisonExpr+ Just [] -> getEgisonExpr' prev Just line -> do history <- getHistory putHistory $ addHistoryUnlessConsecutiveDupe line history let input = prev ++ line- let parsedExpr = if optSExpr opts then SExpr.parseTopExpr input- else NonS.parseTopExpr input+ parsedExpr <- lift $ parseTopExpr input case parsedExpr of- Left err | show err =~ "unexpected end of input" ->- getEgisonExpr' opts $ input ++ "\n"+ Left err | err =~ "unexpected end of input" ->+ getEgisonExpr' (input ++ "\n") Left err -> do- liftIO $ print err- getEgisonExpr opts+ liftIO $ putStrLn ("Parse error at: " ++ err)+ getEgisonExpr Right topExpr -> do -- outputStr $ show topExpr return $ Just topExpr
hs-src/Language/Egison.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE TupleSections #-}- {- | Module : Language.Egison Licence : MIT@@ -11,117 +9,64 @@ ( module Language.Egison.AST , module Language.Egison.Data , module Language.Egison.Primitives- -- * Eval Egison expressions- , evalTopExprs- , evalTopExpr- , evalEgisonExpr- , evalEgisonTopExpr- , evalEgisonTopExprs- , runEgisonExpr- , runEgisonTopExpr- , runEgisonTopExpr'- , runEgisonTopExprs- -- * Load Egison files- , loadEgisonLibrary- , loadEgisonFile+ -- * Modules needed to execute Egison+ , module Language.Egison.CmdOptions+ , module Language.Egison.RState -- * Environment , initialEnv -- * Information , version ) where +import Control.Monad.Reader (asks, local)+import Control.Monad.State+ import Data.Version import qualified Paths_egison as P import Language.Egison.AST import Language.Egison.CmdOptions-import Language.Egison.Core import Language.Egison.Data-import Language.Egison.MathOutput (changeOutputInLang)-import Language.Egison.Parser+import Language.Egison.Eval import Language.Egison.Primitives--import Control.Monad.State+import Language.Egison.RState -- |Version number version :: Version version = P.version -evalTopExprs :: EgisonOpts -> Env -> [EgisonTopExpr] -> EvalM Env-evalTopExprs opts env exprs = do- (bindings, rest) <- collectDefs opts exprs [] []- env <- recursiveBind env bindings- forM_ rest $ evalTopExpr opts env- return env--evalTopExpr :: EgisonOpts -> Env -> EgisonTopExpr -> EvalM Env-evalTopExpr opts env topExpr = do- ret <- evalTopExpr' opts (StateT $ \defines -> (, defines) <$> recursiveBind env defines) topExpr- case fst ret of- Nothing -> return ()- Just output -> liftIO $- case optMathExpr opts of- Nothing -> putStrLn output- Just lang -> putStrLn $ changeOutputInLang lang output- evalStateT (snd ret) []---- |eval an Egison expression-evalEgisonExpr :: Env -> EgisonExpr -> IO (Either EgisonError EgisonValue)-evalEgisonExpr env expr = fromEvalM $ evalExprDeep env expr---- |eval an Egison top expression-evalEgisonTopExpr :: EgisonOpts -> Env -> EgisonTopExpr -> IO (Either EgisonError Env)-evalEgisonTopExpr opts env exprs = fromEvalM $ evalTopExpr opts env exprs---- |eval Egison top expressions-evalEgisonTopExprs :: EgisonOpts -> Env -> [EgisonTopExpr] -> IO (Either EgisonError Env)-evalEgisonTopExprs opts env exprs = fromEvalM $ evalTopExprs opts env exprs---- |eval an Egison expression. Input is a Haskell string.-runEgisonExpr :: EgisonOpts -> Env -> String -> IO (Either EgisonError EgisonValue)-runEgisonExpr opts env input =- fromEvalM $ readExpr (optSExpr opts) input >>= evalExprDeep env---- |eval an Egison top expression. Input is a Haskell string.-runEgisonTopExpr :: EgisonOpts -> Env -> String -> IO (Either EgisonError Env)-runEgisonTopExpr opts env input =- fromEvalM $ readTopExpr (optSExpr opts) input >>= evalTopExpr opts env---- |eval an Egison top expression. Input is a Haskell string.-runEgisonTopExpr' :: EgisonOpts -> StateT [(Var, EgisonExpr)] EvalM Env -> String -> IO (Either EgisonError (Maybe String, StateT [(Var, EgisonExpr)] EvalM Env))-runEgisonTopExpr' opts st input =- fromEvalM $ readTopExpr (optSExpr opts) input >>= evalTopExpr' opts st---- |eval Egison top expressions. Input is a Haskell string.-runEgisonTopExprs :: EgisonOpts -> Env -> String -> IO (Either EgisonError Env)-runEgisonTopExprs opts env input =- fromEvalM $ readTopExprs (optSExpr opts) input >>= evalTopExprs opts env---- |load an Egison file-loadEgisonFile :: EgisonOpts -> Env -> FilePath -> IO (Either EgisonError Env)-loadEgisonFile opts env path = evalEgisonTopExpr opts env (LoadFile path)---- |load an Egison library-loadEgisonLibrary :: EgisonOpts -> Env -> FilePath -> IO (Either EgisonError Env)-loadEgisonLibrary opts env path = evalEgisonTopExpr opts env (Load path)- -- |Environment that contains core libraries-initialEnv :: EgisonOpts -> IO Env-initialEnv opts = do- env <- if optNoIO opts then primitiveEnvNoIO- else primitiveEnv- ret <- evalEgisonTopExprs defaultOption env $ map Load coreLibraries+initialEnv :: RuntimeM Env+initialEnv = do+ isNoIO <- asks optNoIO+ useMathNormalize <- asks optMathNormalize+ env <- liftIO $ if isNoIO then primitiveEnvNoIO else primitiveEnv+ let normalizeLib = if useMathNormalize then "lib/math/normalize.egi" else "lib/math/no-normalize.egi"+ ret <- local (const defaultOption)+ (fromEvalT (evalTopExprs env $ map Load (coreLibraries ++ [normalizeLib]))) case ret of Left err -> do- print . show $ err+ liftIO $ print (show err) return env Right env' -> return env' coreLibraries :: [String] coreLibraries =- [ "lib/math/expression.egi"- , "lib/math/normalize.egi"- , "lib/math/common/arithmetic.egi"+ -- Libs that defines user-defined infixes comes first+ [ "lib/core/base.egi" -- Defines (&&) (||)+ , "lib/math/common/arithmetic.egi" -- Defines (+) (-) (*) (/) (+') (-') (*') (/')+ , "lib/math/algebra/tensor.egi" -- Defines (.) (.')+ , "lib/math/expression.egi" -- Defines (+) (*) (/) (^) for patterns++ , "lib/core/assoc.egi"+ , "lib/core/collection.egi"+ , "lib/core/io.egi"+ , "lib/core/maybe.egi"+ , "lib/core/number.egi"+ , "lib/core/order.egi"+ , "lib/core/random.egi"+ , "lib/core/string.egi"+ , "lib/core/sort.egi" , "lib/math/common/constants.egi" , "lib/math/common/functions.egi" , "lib/math/algebra/root.egi"@@ -131,15 +76,5 @@ , "lib/math/analysis/integral.egi" , "lib/math/algebra/vector.egi" , "lib/math/algebra/matrix.egi"- , "lib/math/algebra/tensor.egi" , "lib/math/geometry/differential-form.egi"- , "lib/core/assoc.egi"- , "lib/core/base.egi"- , "lib/core/collection.egi"- , "lib/core/io.egi"- , "lib/core/maybe.egi"- , "lib/core/number.egi"- , "lib/core/order.egi"- , "lib/core/random.egi"- , "lib/core/string.egi" ]
hs-src/Language/Egison/AST.hs view
@@ -1,7 +1,5 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-} {- | Module : Language.Egison.AST@@ -11,320 +9,264 @@ -} module Language.Egison.AST- ( EgisonTopExpr (..)- , EgisonExpr (..)- , EgisonPattern (..)- , Var (..)+ ( TopExpr (..)+ , ConstantExpr (..)+ , Expr (..)+ , Pattern (..) , VarWithIndices (..)- , varToVarWithIndices+ , makeApply , Arg (..)- , Index (..)- , extractIndex+ , ArgPattern (..)+ , IndexExpr (..)+ , VarIndex (..) , PMMode (..)- , InnerExpr (..)- , BindingExpr+ , BindingExpr (..) , MatchClause , PatternDef , LoopRange (..) , PrimitivePatPattern (..)- , PrimitiveDataPattern (..)- , Infix (..)- , BinOpAssoc (..)- , reservedExprInfix- , reservedPatternInfix+ , PDPatternBase (..)+ , PrimitiveDataPattern+ , Op (..)+ , Assoc (..)+ , reservedExprOp+ , reservedPatternOp , findOpFrom- , stringToVar- , stringToVarExpr+ , stringToVarWithIndices ) where -import Data.Hashable (Hashable)-import Data.List (find, intercalate)+import Data.List (find) import Data.Maybe (fromJust)-import Data.List.Split (splitOn) import Data.Text (Text)-import GHC.Generics (Generic) -data EgisonTopExpr =- Define Var EgisonExpr- | DefineWithIndices VarWithIndices EgisonExpr- | Redefine Var EgisonExpr- | Test EgisonExpr- | Execute EgisonExpr+data TopExpr+ = Define VarWithIndices Expr+ | Test Expr+ | Execute Expr -- temporary : we will replace load to import and export | LoadFile String | Load String- | InfixDecl Bool Infix -- True for pattern infix; False for expression infix- deriving (Show, Eq)+ | InfixDecl Bool Op -- True for pattern infix; False for expression infix+ deriving Show -data EgisonExpr =- CharExpr Char+data ConstantExpr+ = CharExpr Char | StringExpr Text | BoolExpr Bool | IntegerExpr Integer | FloatExpr Double- | VarExpr Var+ | SomethingExpr+ | UndefinedExpr+ deriving Show++data Expr+ = ConstantExpr ConstantExpr+ | VarExpr String | FreshVarExpr- | IndexedExpr Bool EgisonExpr [Index EgisonExpr] -- True -> delete old index and append new one- | SubrefsExpr Bool EgisonExpr EgisonExpr- | SuprefsExpr Bool EgisonExpr EgisonExpr- | UserrefsExpr Bool EgisonExpr EgisonExpr- | PowerExpr EgisonExpr EgisonExpr -- TODO: delete this in v4.0.0- | InductiveDataExpr String [EgisonExpr]- | TupleExpr [EgisonExpr]- | CollectionExpr [InnerExpr] -- TODO: InnerExpr should be EgisonExpr from v4.0.0- | HashExpr [(EgisonExpr, EgisonExpr)]- | VectorExpr [EgisonExpr]+ | IndexedExpr Bool Expr [IndexExpr Expr] -- True -> delete old index and append new one+ | SubrefsExpr Bool Expr Expr+ | SuprefsExpr Bool Expr Expr+ | UserrefsExpr Bool Expr Expr+ | TupleExpr [Expr]+ | CollectionExpr [Expr]+ | ConsExpr Expr Expr+ | JoinExpr Expr Expr+ | HashExpr [(Expr, Expr)]+ | VectorExpr [Expr] - | LambdaExpr [Arg] EgisonExpr- | MemoizedLambdaExpr [String] EgisonExpr- | CambdaExpr String EgisonExpr- | PatternFunctionExpr [String] EgisonPattern+ | LambdaExpr [Arg ArgPattern] Expr+ | LambdaExpr' [Arg String] Expr+ | MemoizedLambdaExpr [String] Expr+ | CambdaExpr String Expr+ | PatternFunctionExpr [String] Pattern - | IfExpr EgisonExpr EgisonExpr EgisonExpr- | LetRecExpr [BindingExpr] EgisonExpr- | LetExpr [BindingExpr] EgisonExpr- | LetStarExpr [BindingExpr] EgisonExpr- | WithSymbolsExpr [String] EgisonExpr+ | IfExpr Expr Expr Expr+ | LetExpr [BindingExpr] Expr+ | LetRecExpr [BindingExpr] Expr+ | WithSymbolsExpr [String] Expr - | MatchExpr PMMode EgisonExpr EgisonExpr [MatchClause]- | MatchAllExpr PMMode EgisonExpr EgisonExpr [MatchClause]- | MatchLambdaExpr EgisonExpr [MatchClause]- | MatchAllLambdaExpr EgisonExpr [MatchClause]+ | MatchExpr PMMode Expr Expr [MatchClause]+ | MatchAllExpr PMMode Expr Expr [MatchClause]+ | MatchLambdaExpr Expr [MatchClause]+ | MatchAllLambdaExpr Expr [MatchClause] | MatcherExpr [PatternDef]- | AlgebraicDataMatcherExpr [(String, [EgisonExpr])]+ | AlgebraicDataMatcherExpr [(String, [Expr])] - | QuoteExpr EgisonExpr- | QuoteSymbolExpr EgisonExpr- | WedgeApplyExpr EgisonExpr EgisonExpr+ | QuoteExpr Expr+ | QuoteSymbolExpr Expr+ | WedgeApplyExpr Expr [Expr] - | DoExpr [BindingExpr] EgisonExpr- | IoExpr EgisonExpr+ | DoExpr [BindingExpr] Expr - | PrefixExpr String EgisonExpr- | InfixExpr Infix EgisonExpr EgisonExpr- | SectionExpr Infix (Maybe EgisonExpr) (Maybe EgisonExpr) -- There cannot be 'SectionExpr op (Just _) (Just _)'+ | PrefixExpr String Expr+ | InfixExpr Op Expr Expr+ | SectionExpr Op (Maybe Expr) (Maybe Expr) -- There cannot be 'SectionExpr op (Just _) (Just _)' - | SeqExpr EgisonExpr EgisonExpr- | ApplyExpr EgisonExpr EgisonExpr- | CApplyExpr EgisonExpr EgisonExpr- | AnonParamFuncExpr Integer EgisonExpr+ | SeqExpr Expr Expr+ | ApplyExpr Expr [Expr]+ | CApplyExpr Expr Expr+ | AnonParamFuncExpr Integer Expr | AnonParamExpr Integer - | GenerateTensorExpr EgisonExpr EgisonExpr- | TensorExpr EgisonExpr EgisonExpr- | TensorContractExpr EgisonExpr- | TensorMapExpr EgisonExpr EgisonExpr- | TensorMap2Expr EgisonExpr EgisonExpr EgisonExpr- | TransposeExpr EgisonExpr EgisonExpr- | FlipIndicesExpr EgisonExpr -- Does not appear in user program+ | GenerateTensorExpr Expr Expr+ | TensorExpr Expr Expr+ | TensorContractExpr Expr+ | TensorMapExpr Expr Expr+ | TensorMap2Expr Expr Expr Expr+ | TransposeExpr Expr Expr+ | FlipIndicesExpr Expr -- Does not appear in user program - | FunctionExpr [EgisonExpr]+ | FunctionExpr [String]+ deriving Show - | SomethingExpr- | UndefinedExpr- deriving (Eq, Show)+data VarWithIndices = VarWithIndices String [VarIndex]+ deriving Show -data Var = Var [String] [Index ()]- deriving (Eq, Generic)+data Arg a+ = ScalarArg a+ | InvertedScalarArg a+ | TensorArg a+ deriving Show -data VarWithIndices = VarWithIndices [String] [Index String]- deriving (Eq)+data ArgPattern+ = APWildCard+ | APPatVar String+ | APInductivePat String [Arg ArgPattern]+ | APTuplePat [Arg ArgPattern]+ | APEmptyPat+ | APConsPat (Arg ArgPattern) (Arg ArgPattern)+ | APSnocPat (Arg ArgPattern) (Arg ArgPattern)+ deriving Show -data Arg =- ScalarArg String- | InvertedScalarArg String- | TensorArg String- deriving (Eq, Show)+data VarIndex+ = VSubscript String+ | VSuperscript String+ | VGroupScripts [VarIndex]+ | VSymmScripts [VarIndex]+ | VAntiSymmScripts [VarIndex]+ deriving Show -data Index a =- Subscript a+data IndexExpr a+ = Subscript a | Superscript a | SupSubscript a | MultiSubscript a a | MultiSuperscript a a- | DFscript Integer Integer -- DifferentialForm | Userscript a- deriving (Eq, Functor, Foldable, Generic, Traversable)--extractIndex :: Index a -> a-extractIndex (Subscript x) = x-extractIndex (Superscript x) = x-extractIndex (SupSubscript x) = x-extractIndex (Userscript x) = x-extractIndex _ = error "extractIndex: Not supported"--data InnerExpr =- ElementExpr EgisonExpr- | SubCollectionExpr EgisonExpr- deriving (Show, Eq)+ deriving (Show, Eq, Functor, Foldable, Traversable) data PMMode = BFSMode | DFSMode- deriving (Eq, Show)+ deriving Show -type BindingExpr = ([Var], EgisonExpr)-type MatchClause = (EgisonPattern, EgisonExpr)-type PatternDef = (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])+data BindingExpr+ = Bind PrimitiveDataPattern Expr+ | BindWithIndices VarWithIndices Expr+ deriving Show --- TODO(momohatt): AndPat and OrPat take only 2 arguments in new syntax-data EgisonPattern =- WildCard- | PatVar Var- | ValuePat EgisonExpr- | PredPat EgisonExpr- | IndexedPat EgisonPattern [EgisonExpr]- | LetPat [BindingExpr] EgisonPattern- | InfixPat Infix EgisonPattern EgisonPattern -- Includes AndPat,OrPat,InductivePat(cons/join)- | NotPat EgisonPattern- | AndPat [EgisonPattern]- | OrPat [EgisonPattern]- | ForallPat EgisonPattern EgisonPattern- | TuplePat [EgisonPattern]- | InductivePat String [EgisonPattern]- | LoopPat Var LoopRange EgisonPattern EgisonPattern+type MatchClause = (Pattern, Expr)+type PatternDef = (PrimitivePatPattern, Expr, [(PrimitiveDataPattern, Expr)])++data Pattern+ = WildCard+ | PatVar String+ | ValuePat Expr+ | PredPat Expr+ | IndexedPat Pattern [Expr]+ | LetPat [BindingExpr] Pattern+ | InfixPat Op Pattern Pattern -- Includes AndPat,OrPat,InductivePat(cons/join)+ | NotPat Pattern+ | AndPat Pattern Pattern+ | OrPat Pattern Pattern+ | ForallPat Pattern Pattern+ | TuplePat [Pattern]+ | InductivePat String [Pattern]+ | LoopPat String LoopRange Pattern Pattern | ContPat- | PApplyPat EgisonExpr [EgisonPattern]+ | PApplyPat Expr [Pattern] | VarPat String- | InductiveOrPApplyPat String [EgisonPattern]+ | InductiveOrPApplyPat String [Pattern] | SeqNilPat- | SeqConsPat EgisonPattern EgisonPattern+ | SeqConsPat Pattern Pattern | LaterPatVar -- For symbolic computing- | DApplyPat EgisonPattern [EgisonPattern]- | DivPat EgisonPattern EgisonPattern- | PlusPat [EgisonPattern]- | MultPat [EgisonPattern]- | PowerPat EgisonPattern EgisonPattern- deriving (Eq, Show)+ | DApplyPat Pattern [Pattern]+ deriving Show -data LoopRange = LoopRange EgisonExpr EgisonExpr EgisonPattern- deriving (Eq, Show)+data LoopRange = LoopRange Expr Expr Pattern+ deriving Show -data PrimitivePatPattern =- PPWildCard+data PrimitivePatPattern+ = PPWildCard | PPPatVar | PPValuePat String | PPInductivePat String [PrimitivePatPattern] | PPTuplePat [PrimitivePatPattern]- deriving (Show, Eq)+ deriving Show -data PrimitiveDataPattern =- PDWildCard- | PDPatVar String- | PDInductivePat String [PrimitiveDataPattern]- | PDTuplePat [PrimitiveDataPattern]+data PDPatternBase var+ = PDWildCard+ | PDPatVar var+ | PDInductivePat String [PDPatternBase var]+ | PDTuplePat [PDPatternBase var] | PDEmptyPat- | PDConsPat PrimitiveDataPattern PrimitiveDataPattern- | PDSnocPat PrimitiveDataPattern PrimitiveDataPattern- | PDConstantPat EgisonExpr- deriving (Show, Eq)+ | PDConsPat (PDPatternBase var) (PDPatternBase var)+ | PDSnocPat (PDPatternBase var) (PDPatternBase var)+ | PDConstantPat ConstantExpr+ deriving (Functor, Foldable, Show) -data Infix- = Infix { repr :: String -- syntastic representation- , func :: String -- semantics- , priority :: Int- , assoc :: BinOpAssoc- , isWedge :: Bool -- True if operator is prefixed with '!'. Only used for expression infix.- }+type PrimitiveDataPattern = PDPatternBase String++data Op+ = Op { repr :: String -- syntastic representation+ , priority :: Int+ , assoc :: Assoc+ , isWedge :: Bool -- True if operator is prefixed with '!'. Only used for expression infix.+ } deriving (Eq, Ord, Show) -data BinOpAssoc- = LeftAssoc- | RightAssoc- | NonAssoc+data Assoc+ = InfixL+ | InfixR+ | InfixN+ | Prefix deriving (Eq, Ord) -instance Show BinOpAssoc where- show LeftAssoc = "infixl"- show RightAssoc = "infixr"- show NonAssoc = "infix"+instance Show Assoc where+ show InfixL = "infixl"+ show InfixR = "infixr"+ show InfixN = "infix"+ show Prefix = "prefix" -reservedExprInfix :: [Infix]-reservedExprInfix =- [ makeInfix "^" "**" 8 LeftAssoc -- TODO: Make "**" into "^" when S-expr is deprecated- , makeInfix "^'" "**'" 8 LeftAssoc -- TODO: Make "**'" into "^'" when S-expr is deprecated- , makeInfix "*" "*" 7 LeftAssoc- , makeInfix "/" "/" 7 LeftAssoc- , makeInfix "*'" "*'" 7 LeftAssoc- , makeInfix "/'" "/'" 7 LeftAssoc- , makeInfix "." "." 7 LeftAssoc -- tensor multiplication- , makeInfix ".'" ".'" 7 LeftAssoc -- tensor multiplication- , makeInfix "%" "remainder" 7 LeftAssoc -- primitive function- , makeInfix "+" "+" 6 LeftAssoc- , makeInfix "-" "-" 6 LeftAssoc- , makeInfix "+'" "+'" 6 LeftAssoc- , makeInfix "-'" "-'" 6 LeftAssoc- , makeInfix "++" "append" 5 RightAssoc- , makeInfix "::" "cons" 5 RightAssoc- , makeInfix "=" "equal" 4 LeftAssoc -- primitive function- , makeInfix "<=" "lte" 4 LeftAssoc -- primitive function- , makeInfix ">=" "gte" 4 LeftAssoc -- primitive function- , makeInfix "<" "lt" 4 LeftAssoc -- primitive function- , makeInfix ">" "gt" 4 LeftAssoc -- primitive function- , makeInfix "&&" "&&" 3 RightAssoc- , makeInfix "||" "||" 2 RightAssoc- , makeInfix "$" "apply" 0 RightAssoc+reservedExprOp :: [Op]+reservedExprOp =+ [ Op "!" 8 Prefix False -- Wedge+ , Op "-" 7 Prefix False -- Negate+ , Op "%" 7 InfixL False -- primitive function+ , Op "*$" 7 Prefix False -- For InvertedScalarArg+ , Op "*$" 7 InfixL False -- For InvertedScalarArg+ , Op "++" 5 InfixR False+ , Op "::" 5 InfixR False+ , Op "=" 4 InfixL False -- primitive function+ , Op "<=" 4 InfixL False -- primitive function+ , Op ">=" 4 InfixL False -- primitive function+ , Op "<" 4 InfixL False -- primitive function+ , Op ">" 4 InfixL False -- primitive function ]- where- makeInfix r f p a =- Infix { repr = r, func = f, priority = p, assoc = a, isWedge = False } -reservedPatternInfix :: [Infix]-reservedPatternInfix =- [ makeInfix "^" "^" 8 LeftAssoc -- PowerPat- , makeInfix "*" "*" 7 LeftAssoc -- MultPat- , makeInfix "/" "div" 7 LeftAssoc -- DivPat- , makeInfix "+" "+" 6 LeftAssoc -- PlusPat- , makeInfix "::" "cons" 5 RightAssoc- , makeInfix "++" "join" 5 RightAssoc- , makeInfix "&" "&" 3 RightAssoc- , makeInfix "|" "|" 2 RightAssoc+reservedPatternOp :: [Op]+reservedPatternOp =+ [ Op "::" 5 InfixR False -- cons (desugared)+ , Op "++" 5 InfixR False -- join (desugared)+ , Op "&" 3 InfixR False+ , Op "|" 2 InfixR False ]- where- makeInfix r f p a =- Infix { repr = r, func = f, priority = p, assoc = a, isWedge = False } -findOpFrom :: String -> [Infix] -> Infix+findOpFrom :: String -> [Op] -> Op findOpFrom op table = fromJust $ find ((== op) . repr) table -instance Hashable (Index ())-instance Hashable Var--stringToVar :: String -> Var-stringToVar name = Var (splitOn "." name) []--stringToVarExpr :: String -> EgisonExpr-stringToVarExpr = VarExpr . stringToVar--instance Show Var where- show (Var xs is) = intercalate "." xs ++ concatMap show is--instance Show VarWithIndices where- show (VarWithIndices xs is) = intercalate "." xs ++ concatMap show is--varToVarWithIndices :: Var -> VarWithIndices-varToVarWithIndices (Var xs is) = VarWithIndices xs $ map f is- where- f :: Index () -> Index String- f index = (\() -> "") <$> index--instance Show (Index ()) where- show (Superscript ()) = "~"- show (Subscript ()) = "_"- show (SupSubscript ()) = "~_"- show (DFscript _ _) = ""- show (Userscript _) = "|"--instance Show (Index String) where- show (Superscript s) = "~" ++ s- show (Subscript s) = "_" ++ s- show (SupSubscript s) = "~_" ++ s- show (DFscript _ _) = ""- show (Userscript i) = "|" ++ show i+stringToVarWithIndices :: String -> VarWithIndices+stringToVarWithIndices name = VarWithIndices name [] -instance Show (Index EgisonExpr) where- show (Superscript i) = "~" ++ show i- show (Subscript i) = "_" ++ show i- show (SupSubscript i) = "~_" ++ show i- show (DFscript _ _) = ""- show (Userscript i) = "|" ++ show i+makeApply :: String -> [Expr] -> Expr+makeApply func args = ApplyExpr (VarExpr func) args
hs-src/Language/Egison/CmdOptions.hs view
@@ -12,6 +12,7 @@ ) where import Data.Char (isDigit)+import Data.List (intercalate) import Options.Applicative data EgisonOpts = EgisonOpts {@@ -31,11 +32,12 @@ optTestOnly :: Bool, optPrompt :: String, optMathExpr :: Maybe String,- optSExpr :: Bool+ optSExpr :: Bool,+ optMathNormalize :: Bool } defaultOption :: EgisonOpts-defaultOption = EgisonOpts Nothing False Nothing Nothing [] [] [] Nothing Nothing Nothing False False True False "> " Nothing False+defaultOption = EgisonOpts Nothing False Nothing Nothing [] [] [] Nothing Nothing Nothing False False True False "> " Nothing False True cmdParser :: ParserInfo EgisonOpts cmdParser = info (helper <*> cmdArgParser)@@ -79,12 +81,12 @@ <> long "substitute" <> metavar "EXPR" <> help "Operate input in tsv format as infinite stream"))- <*> optional ((\s -> "1#(map " ++ s ++ " %1)") <$> strOption+ <*> optional (strOption (short 'm' <> long "map" <> metavar "EXPR" <> help "Operate input in tsv format line by line"))- <*> optional ((\s -> "1#(filter " ++ s ++ " %1)") <$> strOption+ <*> optional (strOption (short 'f' <> long "filter" <> metavar "EXPR"@@ -118,18 +120,25 @@ (short 'S' <> long "sexpr-syntax" <> help "Use s-expression syntax")+ <*> flag True False+ (long "no-normalize"+ <> help "Turn off normalization of math expressions") readFieldOption :: String -> (String, String) readFieldOption str =- let (s, rs) = span isDigit str in- case rs of- ',':rs' -> let (e, opts) = span isDigit rs' in- case opts of- ['s'] -> ("{" ++ s ++ " " ++ e ++ "}", "")- ['c'] -> ("{}", "{" ++ s ++ " " ++ e ++ "}")- ['s', 'c'] -> ("{" ++ s ++ " " ++ e ++ "}", "{" ++ s ++ " " ++ e ++ "}")- ['c', 's'] -> ("{" ++ s ++ " " ++ e ++ "}", "{" ++ s ++ " " ++ e ++ "}")- ['s'] -> ("{" ++ s ++ "}", "")- ['c'] -> ("", "{" ++ s ++ "}")- ['s', 'c'] -> ("{" ++ s ++ "}", "{" ++ s ++ "}")- ['c', 's'] -> ("{" ++ s ++ "}", "{" ++ s ++ "}")+ let (s, c) = readFieldOption' str in (f s, f c)+ where+ f x = "[" ++ intercalate ", " x ++ "]"+ readFieldOption' str =+ let (s, rs) = span isDigit str in+ case rs of+ ',':rs' -> let (e, opts) = span isDigit rs' in+ case opts of+ ['s'] -> ([s, e], [])+ ['c'] -> ([], [s, e])+ ['s', 'c'] -> ([s, e], [s, e])+ ['c', 's'] -> ([s, e], [s, e])+ ['s'] -> ([s], [])+ ['c'] -> ([], [s])+ ['s', 'c'] -> ([s], [s])+ ['c', 's'] -> ([s], [s])
hs-src/Language/Egison/Completion.hs view
@@ -9,51 +9,39 @@ ( completeEgison ) where +import Data.HashMap.Strict (keys) import Data.List+import System.Console.Haskeline hiding (catch, handle, throwTo) -import System.Console.Haskeline hiding (catch, handle, throwTo)+import Language.Egison.Data (Env (..))+import Language.Egison.IExpr (Var (..))+import Language.Egison.Parser.NonS (upperReservedWords, lowerReservedWords) -- |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) $ egisonPrimitivesAfterOpenParen ++ egisonKeywordsAfterOpenParen--completeAfterOpenCons :: Monad m => String -> m [Completion]-completeAfterOpenCons str = return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) egisonKeywordsAfterOpenCons+completeEgison :: Monad m => Env -> CompletionFunc m+completeEgison _ arg@(')':_, _) = completeParen arg+completeEgison _ arg@(']':_, _) = completeParen 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 env arg = completeWord Nothing " \t[]{}$," (completeEgisonKeyword env) arg 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--egisonPrimitivesAfterOpenParen :: [String]-egisonPrimitivesAfterOpenParen = map ((:) '(') ["+", "-", "*", "/", "numerator", "denominator", "modulo", "quotient", "remainder", "neg", "abs", "eq?", "lt?", "lte?", "gt?", "gte?", "round", "floor", "ceiling", "truncate", "sqrt", "exp", "log", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh", "asinh", "acosh", "atanh", "itof", "rtof", "stoi", "read", "show", "empty?", "uncons", "unsnoc", "assert", "assert-equal"]--egisonKeywordsAfterOpenParen :: [String]-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", "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", "sort", "intersperse", "intercalate", "split", "split/m"]--egisonKeywordsAfterOpenCons :: [String]-egisonKeywordsAfterOpenCons = map ((:) '<') ["nil", "cons", "join", "snoc", "nioj"]--egisonKeywordsInNeutral :: [String]-egisonKeywordsInNeutral = "something" : ["bool", "string", "integer", "nats", "primes"]+completeEgisonKeyword :: Monad m => Env -> String -> m [Completion]+completeEgisonKeyword (Env env _) str = do+ let definedWords = filter f $ map (\(Var name _) -> name) $ concatMap keys env+ return $ map (\kwd -> Completion kwd kwd False) $ filter (isPrefixOf str) (egisonKeywords ++ definedWords)+ where+ f [_] = False+ f [_, '\''] = False+ f ('b':'.':_) = False+ f _ = True egisonKeywords :: [String]-egisonKeywords = egisonPrimitivesAfterOpenParen ++ egisonKeywordsAfterOpenParen ++ egisonKeywordsAfterOpenCons ++ egisonKeywordsInNeutral+egisonKeywords = upperReservedWords ++ lowerReservedWords completeParen :: Monad m => CompletionFunc m completeParen (lstr, _) = case closeParen lstr of@@ -82,15 +70,9 @@ 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/Core.hs view
@@ -11,1368 +11,1089 @@ -} module Language.Egison.Core- (- -- * Egison code evaluation- collectDefs- , evalTopExpr'- , evalExpr- , evalExprDeep- , evalRef- , evalRefDeep- , evalWHNF- , applyFunc- -- * Environment- , recursiveBind- -- * Pattern matching- , patternMatch- -- * Tuple, Collection- , tupleToList- , collectionToList- ) where--import Prelude hiding (mapM, mappend, mconcat)--import Control.Arrow-import Control.Monad.Except (throwError)-import Control.Monad.State hiding (mapM, join)-import Control.Monad.Trans.Maybe--import Data.Char (isUpper)-import Data.Foldable (toList)-import Data.IORef-import Data.List (partition)-import Data.Maybe-import Data.Sequence (Seq, ViewL (..), ViewR (..), (><))-import qualified Data.Sequence as Sq-import Data.Traversable (mapM)--import qualified Data.HashMap.Lazy as HL-import qualified Data.Vector as V--import Language.Egison.AST-import Language.Egison.CmdOptions-import Language.Egison.Data-import Language.Egison.MList-import Language.Egison.IState (MonadEval(..))-import Language.Egison.MathExpr-import Language.Egison.Parser-import Language.Egison.Pretty-import Language.Egison.Tensor------- Evaluator-----collectDefs :: EgisonOpts -> [EgisonTopExpr] -> [(Var, EgisonExpr)] -> [EgisonTopExpr] -> EvalM ([(Var, EgisonExpr)], [EgisonTopExpr])-collectDefs opts (expr:exprs) bindings rest =- case expr of- Define name expr -> collectDefs opts exprs ((name, expr) : bindings) rest- DefineWithIndices{} -> throwError =<< EgisonBug "should not reach here (desugared)" <$> getFuncNameStack- Redefine _ _ -> collectDefs opts exprs bindings $ if optTestOnly opts then expr : rest else rest- Test _ -> collectDefs opts exprs bindings $ if optTestOnly opts then expr : rest else rest- Execute _ -> collectDefs opts exprs bindings $ if optTestOnly opts then rest else expr : rest- LoadFile _ | optNoIO opts -> throwError (Default "No IO support")- LoadFile file -> do- exprs' <- loadFile file- collectDefs opts (exprs' ++ exprs) bindings rest- Load _ | optNoIO opts -> throwError (Default "No IO support")- Load file -> do- exprs' <- loadLibraryFile file- collectDefs opts (exprs' ++ exprs) bindings rest- InfixDecl{} -> collectDefs opts exprs bindings rest-collectDefs _ [] bindings rest = return (bindings, reverse rest)--evalTopExpr' :: EgisonOpts -> StateT [(Var, EgisonExpr)] EvalM Env -> EgisonTopExpr -> EvalM (Maybe String, StateT [(Var, EgisonExpr)] EvalM Env)-evalTopExpr' _ st (Define name expr) = return (Nothing, withStateT (\defines -> (name, expr):defines) st)-evalTopExpr' _ _ DefineWithIndices{} = throwError =<< EgisonBug "should not reach here (desugared)" <$> getFuncNameStack-evalTopExpr' _ st (Redefine name expr) = return (Nothing, mapStateT (>>= \(env, defines) -> (, defines) <$> recursiveRebind env (name, expr)) st)-evalTopExpr' opts st (Test expr) = do- pushFuncName "<stdin>"- val <- evalStateT st [] >>= flip evalExprDeep expr- popFuncName- case (optSExpr opts, optMathExpr opts) of- (False, Nothing) -> return (Just (show val), st)- _ -> return (Just (prettyS val), st)-evalTopExpr' _ st (Execute expr) = do- pushFuncName "<stdin>"- io <- evalStateT st [] >>= flip evalExpr expr- case io of- Value (IOFunc m) -> m >> popFuncName >> return (Nothing, st)- _ -> throwError =<< TypeMismatch "io" io <$> getFuncNameStack-evalTopExpr' opts st (Load file) = do- exprs <- loadLibraryFile file- (bindings, _) <- collectDefs opts exprs [] []- return (Nothing, withStateT (\defines -> bindings ++ defines) st)-evalTopExpr' opts st (LoadFile file) = do- exprs <- loadFile file- (bindings, _) <- collectDefs opts exprs [] []- return (Nothing, withStateT (\defines -> bindings ++ defines) st)-evalTopExpr' _ st InfixDecl{} = return (Nothing, st)--evalExpr :: Env -> EgisonExpr -> EvalM WHNFData-evalExpr _ (CharExpr c) = return . Value $ Char c-evalExpr _ (StringExpr s) = return . Value $ toEgison s-evalExpr _ (BoolExpr b) = return . Value $ Bool b-evalExpr _ (IntegerExpr x) = return . Value $ toEgison x-evalExpr _ (FloatExpr x) = return . Value $ Float x--evalExpr env (QuoteExpr expr) = do- whnf <- evalExpr env expr- case whnf of- Value (ScalarData s) -> return . Value $ ScalarData $ SingleTerm 1 [(Quote s, 1)]- _ -> throwError =<< TypeMismatch "scalar in quote" whnf <$> getFuncNameStack--evalExpr env (QuoteSymbolExpr expr) = do- whnf <- evalExpr env expr- case whnf of- Value fn@(Func (Just _) _ _ _) -> return . Value $ symbolScalarData "" (prettyS fn)- Value (ScalarData _) -> return whnf- _ -> throwError =<< TypeMismatch "value in quote-function" whnf <$> getFuncNameStack--evalExpr env (VarExpr var@(Var [name@(c:_)] [])) | isUpper c = refVar' env var >>= evalRef- where- refVar' :: Env -> Var -> EvalM ObjectRef- refVar' env var = maybe (newEvaluatedObjectRef (Value (InductiveData name []))) return- (refVar env var)--evalExpr env (VarExpr name) = refVar' env name >>= evalRef- where- refVar' :: Env -> Var -> EvalM ObjectRef- refVar' env var = maybe (newEvaluatedObjectRef (Value (symbolScalarData "" $ prettyStr var))) return- (refVar env var)--evalExpr env (AnonParamExpr n) = evalExpr env (stringToVarExpr ("::" ++ show n))--evalExpr _ (InductiveDataExpr name []) = return . Value $ InductiveData name []-evalExpr env (InductiveDataExpr name exprs) =- Intermediate . IInductiveData name <$> mapM (newObjectRef env) exprs--evalExpr _ (TupleExpr []) = return . Value $ Tuple []-evalExpr env (TupleExpr [expr]) = evalExpr env expr-evalExpr env (TupleExpr exprs) = Intermediate . ITuple <$> mapM (newObjectRef env) exprs--evalExpr _ (CollectionExpr []) = return . Value $ Collection Sq.empty--evalExpr env (CollectionExpr inners) = do- inners' <- mapM fromInnerExpr inners- innersSeq <- liftIO $ newIORef $ Sq.fromList inners'- return $ Intermediate $ ICollection innersSeq- where- fromInnerExpr :: InnerExpr -> EvalM Inner- fromInnerExpr (ElementExpr expr) = IElement <$> newObjectRef env expr- fromInnerExpr (SubCollectionExpr expr) = ISubCollection <$> newObjectRef env expr--evalExpr env@(Env frame maybe_vwi) (VectorExpr exprs) = do- let n = toInteger (length exprs)- let indices = [1 .. (n + 1)]- whnfs <- zipWithM evalWithIndex exprs indices- case whnfs of- Intermediate (ITensor Tensor{}):_ ->- mapM toTensor (zipWith f whnfs indices) >>= tConcat' >>= fromTensor- _ -> fromTensor (Tensor [n] (V.fromList whnfs) [])- where- evalWithIndex :: EgisonExpr -> Integer -> EvalM WHNFData- evalWithIndex expr index = evalExpr env' expr- where- env' = case maybe_vwi of- Nothing -> env- Just (VarWithIndices name indices) ->- Env frame (Just (VarWithIndices name (zipWith changeIndex indices [toEgison index])))- f (Intermediate (ITensor (Tensor ns xs indices))) i =- Intermediate (ITensor (Tensor ns xs' indices))- where- xs' = V.fromList $ zipWith g (V.toList xs) $ map (\ms -> map toEgison (i:ms)) $ enumTensorIndices ns- f x _ = x- g (Value (ScalarData (Div (Plus [Term 1 [(FunctionData fn argnames args js, 1)]]) p))) ms =- Value (ScalarData (Div (Plus [Term 1 [(FunctionData fn' argnames args js, 1)]]) p))- where- fn' = case maybe_vwi of- Nothing -> fn- Just (VarWithIndices name indices) ->- symbolScalarData' "" $ prettyStr (VarWithIndices name (zipWith changeIndex indices ms))- g x _ = x--evalExpr env (TensorExpr nsExpr xsExpr) = do- nsWhnf <- evalExpr env nsExpr- ns <- (fromCollection nsWhnf >>= fromMList >>= mapM evalRef >>= mapM fromWHNF) :: EvalM [Integer]- xsWhnf <- evalExpr env xsExpr- xs <- fromCollection xsWhnf >>= fromMList >>= mapM evalRef- if product ns == toInteger (length xs)- then fromTensor (initTensor ns xs)- else throwError =<< InconsistentTensorShape <$> getFuncNameStack--evalExpr env (HashExpr assocs) = do- let (keyExprs, exprs) = unzip assocs- keyWhnfs <- mapM (evalExpr env) keyExprs- keys <- mapM makeHashKey keyWhnfs- refs <- mapM (newObjectRef env) exprs- case keys of- CharKey _ : _ -> do- let keys' = map (\case CharKey c -> c) keys- return . Intermediate . ICharHash $ HL.fromList $ zip keys' refs- StrKey _ : _ -> do- let keys' = map (\case StrKey s -> s) keys- return . Intermediate . IStrHash $ HL.fromList $ zip keys' refs- _ -> do- let keys' = map (\case IntKey i -> i) keys- return . Intermediate . IIntHash $ HL.fromList $ zip keys' refs- where- makeHashKey :: WHNFData -> EvalM EgisonHashKey- makeHashKey (Value val) =- case val of- ScalarData _ -> IntKey <$> fromEgison val- Char c -> return (CharKey c)- String str -> return (StrKey str)- _ -> throwError =<< TypeMismatch "integer or string" (Value val) <$> getFuncNameStack- makeHashKey whnf = throwError =<< TypeMismatch "integer or string" whnf <$> getFuncNameStack--evalExpr env (IndexedExpr override expr indices) = do- tensor <- case expr of- VarExpr (Var xs is) -> do- let mObjRef = refVar env (Var xs $ is ++ map (const () <$>) indices)- case mObjRef of- Just objRef -> evalRef objRef- Nothing -> evalExpr env expr- _ -> evalExpr env expr- js <- mapM evalIndex indices- ret <- case tensor of- Value (ScalarData (SingleTerm 1 [(Symbol id name [], 1)])) -> do- js2 <- mapM evalIndexToScalar indices- return $ Value (ScalarData (SingleTerm 1 [(Symbol id name js2, 1)]))- Value (ScalarData (SingleTerm 1 [(Symbol id name js', 1)])) -> do- js2 <- mapM evalIndexToScalar indices- return $ Value (ScalarData (SingleTerm 1 [(Symbol id name (js' ++ js2), 1)]))- Value (TensorData t@Tensor{}) -> Value <$> refTensorWithOverride override js t- Intermediate (ITensor t@Tensor{}) -> refTensorWithOverride override js t- _ -> do- js2 <- mapM evalIndexToScalar indices- refArray tensor (map (ScalarData . extractIndex) js2)- return ret -- TODO: refactor- where- evalIndex :: Index EgisonExpr -> EvalM (Index EgisonValue)- evalIndex index = traverse (evalExprDeep env) index-- evalIndexToScalar :: Index EgisonExpr -> EvalM (Index ScalarData)- evalIndexToScalar index = traverse ((extractScalar =<<) . evalExprDeep env) index--evalExpr env (SubrefsExpr override expr jsExpr) = do- js <- map Subscript <$> (evalExpr env jsExpr >>= collectionToList)- tensor <- case expr of- VarExpr (Var xs is) -> do- let mObjRef = refVar env (Var xs $ is ++ replicate (length js) (Subscript ()))- case mObjRef of- Just objRef -> evalRef objRef- Nothing -> evalExpr env expr- _ -> evalExpr env expr- case tensor of- Value (ScalarData _) -> return tensor- Value (TensorData t@Tensor{}) -> Value <$> refTensorWithOverride override js t- Intermediate (ITensor t@Tensor{}) -> refTensorWithOverride override js t- _ -> throwError =<< NotImplemented "subrefs" <$> getFuncNameStack--evalExpr env (SuprefsExpr override expr jsExpr) = do- js <- map Superscript <$> (evalExpr env jsExpr >>= collectionToList)- tensor <- case expr of- VarExpr (Var xs is) -> do- let mObjRef = refVar env (Var xs $ is ++ replicate (length js) (Superscript ()))- case mObjRef of- Just objRef -> evalRef objRef- Nothing -> evalExpr env expr- _ -> evalExpr env expr- case tensor of- Value (ScalarData _) -> return tensor- Value (TensorData t@Tensor{}) -> Value <$> refTensorWithOverride override js t- Intermediate (ITensor t@Tensor{}) -> refTensorWithOverride override js t- _ -> throwError =<< NotImplemented "suprefs" <$> getFuncNameStack--evalExpr env (UserrefsExpr _ expr jsExpr) = do- val <- evalExprDeep env expr- js <- map Userscript <$> (evalExpr env jsExpr >>= collectionToList >>= mapM extractScalar)- case val of- ScalarData (SingleTerm 1 [(Symbol id name is, 1)]) ->- return $ Value (ScalarData (SingleTerm 1 [(Symbol id name (is ++ js), 1)]))- ScalarData (SingleTerm 1 [(FunctionData name argnames args is, 1)]) ->- return $ Value (ScalarData (SingleTerm 1 [(FunctionData name argnames args (is ++ js), 1)]))- _ -> throwError =<< NotImplemented "user-refs" <$> getFuncNameStack--evalExpr env (LambdaExpr names expr) = do- names' <- mapM (\case- TensorArg name' -> return name'- ScalarArg _ -> throwError =<< EgisonBug "scalar-arg remained" <$> getFuncNameStack) names- return . Value $ Func Nothing env names' expr--evalExpr env (AnonParamFuncExpr n expr) = return . Value $ AnonParamFunc env n expr--evalExpr env (CambdaExpr name expr) = return . Value $ CFunc Nothing env name expr--evalExpr env (PatternFunctionExpr names pattern) = return . Value $ PatternFunc env names pattern--evalExpr (Env _ Nothing) (FunctionExpr _) = throwError $ Default "function symbol is not bound to a variable"--evalExpr env@(Env _ (Just name)) (FunctionExpr args) = do- args' <- mapM (evalExprDeep env) args >>= mapM extractScalar- return . Value $ ScalarData (SingleTerm 1 [(FunctionData (symbolScalarData' "" (prettyStr name)) (map (symbolScalarData' "" . prettyStr') args) args' [], 1)])--evalExpr env (IfExpr test expr expr') = do- test <- evalExpr env test >>= fromWHNF- evalExpr env $ if test then expr else expr'--evalExpr env (LetExpr bindings expr) =- mapM extractBindings bindings >>= flip evalExpr expr . extendEnv env . concat- where- extractBindings :: BindingExpr -> EvalM [Binding]- extractBindings ([name], expr) =- case expr of- FunctionExpr _ ->- let Env frame _ = env- in makeBindings [name] . (:[]) <$> newObjectRef (Env frame (Just $ varToVarWithIndices name)) expr- _ -> makeBindings [name] . (:[]) <$> newObjectRef env expr- extractBindings (names, expr) =- makeBindings names <$> (evalExpr env expr >>= fromTuple)--evalExpr env (LetRecExpr bindings expr) =- let bindings' = evalState (concat <$> mapM extractBindings bindings) 0- in recursiveBind env bindings' >>= flip evalExpr expr- where- extractBindings :: BindingExpr -> State Int [(Var, EgisonExpr)]- extractBindings ([name], expr) = return [(name, expr)]- extractBindings (names, expr) = do- var <- genVar- let k = length names- target = VarExpr var- matcher = TupleExpr $ replicate k SomethingExpr- nth n =- let pattern = TuplePat $ flip map [1..k] $ \i ->- if i == n then PatVar (stringToVar "#_") else WildCard- in MatchExpr BFSMode target matcher [(pattern, stringToVarExpr "#_")]- return ((var, expr) : map (second nth) (zip names [1..]))-- genVar :: State Int Var- genVar = modify (1+) >> gets (stringToVar . ('#':) . show)--evalExpr env (TransposeExpr vars expr) = do- syms <- evalExpr env vars >>= collectionToList- whnf <- evalExpr env expr- case whnf of- Intermediate (ITensor t) -> Intermediate . ITensor <$> tTranspose' syms t- Value (TensorData t) -> Value . TensorData <$> tTranspose' syms t- _ -> return whnf--evalExpr env (FlipIndicesExpr expr) = do- whnf <- evalExpr env expr- case whnf of- Intermediate (ITensor t) -> Intermediate . ITensor <$> tFlipIndices t- Value (TensorData t) -> Value . TensorData <$> tFlipIndices t- _ -> return whnf--evalExpr env (WithSymbolsExpr vars expr) = do- symId <- fresh- syms <- mapM (newEvaluatedObjectRef . Value . symbolScalarData symId) vars- let bindings = zip (map stringToVar vars) syms- whnf <- evalExpr (extendEnv env bindings) expr- case whnf of- Value (TensorData t@Tensor{}) ->- Value . TensorData <$> removeTmpScripts symId t- Intermediate (ITensor t@Tensor{}) ->- Intermediate . ITensor <$> removeTmpScripts symId t- _ -> return whnf- where- isTmpSymbol :: String -> Index EgisonValue -> Bool- isTmpSymbol symId (Subscript (ScalarData (SingleTerm 1 [(Symbol id _ _, _)]))) = symId == id- isTmpSymbol symId (Superscript (ScalarData (SingleTerm 1 [(Symbol id _ _, _)]))) = symId == id- isTmpSymbol symId (SupSubscript (ScalarData (SingleTerm 1 [(Symbol id _ _, _)]))) = symId == id- isTmpSymbol symId (Userscript (ScalarData (SingleTerm 1 [(Symbol id _ _, _)]))) = symId == id- removeTmpScripts :: HasTensor a => String -> Tensor a -> EvalM (Tensor a)- removeTmpScripts symId (Tensor s xs is) = do- let (ds, js) = partition (isTmpSymbol symId) is- Tensor s ys _ <- tTranspose (js ++ ds) (Tensor s xs is)- return (Tensor s ys js)---evalExpr env (DoExpr bindings expr) = return $ Value $ IOFunc $ do- let body = foldr genLet (ApplyExpr expr $ TupleExpr [stringToVarExpr "#1"]) bindings- applyFunc env (Value $ Func Nothing env ["#1"] body) $ Value World- where- genLet (names, expr) expr' =- LetExpr [(map stringToVar ["#1", "#2"], ApplyExpr expr $ TupleExpr [stringToVarExpr "#1"])] $- LetExpr [(names, stringToVarExpr "#2")] expr'--evalExpr env (IoExpr expr) = do- io <- evalExpr env expr- case io of- Value (IOFunc m) -> do- val <- m >>= evalWHNF- case val of- Tuple [_, val'] -> return $ Value val'- _ -> throwError =<< TypeMismatch "io" io <$> getFuncNameStack--evalExpr env (MatchAllExpr pmmode target matcher clauses) = do- target <- evalExpr env target- matcher <- evalExpr env matcher >>= evalMatcherWHNF- f matcher target >>= fromMList- where- fromMList :: MList EvalM WHNFData -> EvalM WHNFData- fromMList MNil = return . Value $ Collection Sq.empty- fromMList (MCons val m) = do- head <- IElement <$> newEvaluatedObjectRef val- tail <- ISubCollection <$> (liftIO . newIORef . Thunk $ m >>= fromMList)- seqRef <- liftIO . newIORef $ Sq.fromList [head, tail]- return . Intermediate $ ICollection seqRef- f matcher target = do- let tryMatchClause (pattern, expr) results = do- result <- patternMatch pmmode env pattern target matcher- mmap (flip evalExpr expr . extendEnv env) result >>= (`mappend` results)- mfoldr tryMatchClause (return MNil) (fromList clauses)--evalExpr env (MatchExpr pmmode target matcher clauses) = do- target <- evalExpr env target- matcher <- evalExpr env matcher >>= evalMatcherWHNF- f matcher target- where- f matcher target = do- let tryMatchClause (pattern, expr) cont = do- result <- patternMatch pmmode env pattern target matcher- case result of- MCons bindings _ -> evalExpr (extendEnv env bindings) expr- MNil -> cont- currentFuncName <- topFuncName- callstack <- getFuncNameStack- foldr tryMatchClause (throwError $ MatchFailure currentFuncName callstack) clauses--evalExpr env (SeqExpr expr1 expr2) = do- _ <- evalExprDeep env expr1- evalExpr env expr2--evalExpr env (CApplyExpr func arg) = do- func <- evalExpr env func- args <- evalExpr env arg >>= collectionToList- case func of- Value (MemoizedFunc name ref hashRef env names body) -> do- indices' <- mapM fromEgison args- hash <- liftIO $ readIORef hashRef- case HL.lookup indices' hash of- Just objRef ->- evalRef objRef- Nothing -> do- whnf <- applyFunc env (Value (Func Nothing env names body)) (Value (makeTuple args))- retRef <- newEvaluatedObjectRef whnf- hash <- liftIO $ readIORef hashRef- liftIO $ writeIORef hashRef (HL.insert indices' retRef hash)- writeObjectRef ref (Value (MemoizedFunc name ref hashRef env names body))- return whnf- _ -> applyFunc env func (Value (makeTuple args))--evalExpr env (ApplyExpr func arg) = do- func <- evalExpr env func >>= appendDFscripts 0- case func of--- Value (ScalarData (SingleTerm 1 [(Symbol "" name@(c:_) [], 1)])) | isUpper c ->- Value (InductiveData name []) ->- case arg of- TupleExpr exprs ->- Intermediate . IInductiveData name <$> mapM (newObjectRef env) exprs- _ -> throwError $ Default "argument is not a tuple"- Value (TensorData t@Tensor{}) -> do- arg <- evalExpr env arg- Value <$> (tMap (\f -> applyFunc env (Value f) arg >>= evalWHNF) t >>= fromTensor) >>= removeDFscripts- Intermediate (ITensor t@Tensor{}) -> do- arg <- evalExpr env arg- tMap (\f -> applyFunc env f arg) t >>= fromTensor- Value (MemoizedFunc name ref hashRef env' names body) -> do- arg <- evalExpr env arg- indices <- evalWHNF arg- indices' <- mapM fromEgison $ fromTupleValue indices- hash <- liftIO $ readIORef hashRef- case HL.lookup indices' hash of- Just objRef ->- evalRef objRef- Nothing -> do- whnf <- applyFunc env' (Value (Func Nothing env' names body)) arg- retRef <- newEvaluatedObjectRef whnf- hash <- liftIO $ readIORef hashRef- liftIO $ writeIORef hashRef (HL.insert indices' retRef hash)- writeObjectRef ref (Value (MemoizedFunc name ref hashRef env' names body))- return whnf- _ -> do- arg <- evalExpr env arg- applyFunc env func arg >>= removeDFscripts--evalExpr env (WedgeApplyExpr func arg) = do- func <- evalExpr env func >>= appendDFscripts 0- arg <- evalExpr env arg >>= fromTupleWHNF- let k = fromIntegral (length arg)- arg <- zipWithM appendDFscripts [1..k] arg >>= makeITuple- case func of- Value (TensorData t@Tensor{}) ->- Value <$> (tMap (\f -> applyFunc env (Value f) arg >>= evalWHNF) t >>= fromTensor)- Intermediate (ITensor t@Tensor{}) ->- tMap (\f -> applyFunc env f arg) t >>= fromTensor- Value (MemoizedFunc name ref hashRef env names body) -> do- indices <- evalWHNF arg- indices' <- mapM fromEgison $ fromTupleValue indices- hash <- liftIO $ readIORef hashRef- case HL.lookup indices' hash of- Just objRef ->- evalRef objRef- Nothing -> do- whnf <- applyFunc env (Value (Func Nothing env names body)) arg- retRef <- newEvaluatedObjectRef whnf- hash <- liftIO $ readIORef hashRef- liftIO $ writeIORef hashRef (HL.insert indices' retRef hash)- writeObjectRef ref (Value (MemoizedFunc name ref hashRef env names body))- return whnf- _ -> applyFunc env func arg >>= removeDFscripts--evalExpr env (MatcherExpr info) = return $ Value $ UserMatcher env info--evalExpr env (GenerateTensorExpr fnExpr shapeExpr) = do- shape <- evalExpr env shapeExpr >>= collectionToList- ns <- mapM fromEgison shape :: EvalM Shape- xs <- mapM (indexToWHNF env . map toEgison) (enumTensorIndices ns)- fromTensor (Tensor ns (V.fromList xs) [])- where- indexToWHNF :: Env -> [EgisonValue] {- index -} -> EvalM WHNFData- indexToWHNF (Env frame maybe_vwi) ms = do- let env' = maybe env (\(VarWithIndices name indices) -> Env frame $ Just $ VarWithIndices name $ zipWith changeIndex indices ms) maybe_vwi- fn <- evalExpr env' fnExpr- applyFunc env fn $ Value $ makeTuple ms--evalExpr env (TensorContractExpr tExpr) = do- whnf <- evalExpr env tExpr- case whnf of- Intermediate (ITensor t@Tensor{}) -> do- ts <- tContract t- makeICollection (map tensorToWHNF ts)- Value (TensorData t@Tensor{}) -> do- ts <- tContract t- return $ Value $ Collection $ Sq.fromList $ map tensorToValue ts- _ -> makeICollection [whnf]--evalExpr env (TensorMapExpr fnExpr tExpr) = do- fn <- evalExpr env fnExpr- whnf <- evalExpr env tExpr- case whnf of- Intermediate (ITensor t) ->- tMap (applyFunc env fn) t >>= fromTensor- Value (TensorData t) ->- Value <$> (tMap (applyFunc' env fn) t >>= fromTensor)- _ -> applyFunc env fn whnf- where- applyFunc' :: Env -> WHNFData -> EgisonValue -> EvalM EgisonValue- applyFunc' env fn x = applyFunc env fn (Value x) >>= evalWHNF--evalExpr env (TensorMap2Expr fnExpr t1Expr t2Expr) = do- fn <- evalExpr env fnExpr- whnf1 <- evalExpr env t1Expr- whnf2 <- evalExpr env t2Expr- case (whnf1, whnf2) of- -- both of arguments are tensors- (Intermediate (ITensor t1), Intermediate (ITensor t2)) ->- tMap2 (applyFunc'' env fn) t1 t2 >>= fromTensor- (Intermediate (ITensor t), Value (TensorData (Tensor ns xs js))) -> do- let xs' = V.map Value xs- tMap2 (applyFunc'' env fn) t (Tensor ns xs' js) >>= fromTensor- (Value (TensorData (Tensor ns xs js)), Intermediate (ITensor t)) -> do- let xs' = V.map Value xs- tMap2 (applyFunc'' env fn) (Tensor ns xs' js) t >>= fromTensor- (Value (TensorData t1), Value (TensorData t2)) ->- Value <$> (tMap2 (\x y -> applyFunc' env fn (Tuple [x, y])) t1 t2 >>= fromTensor)- -- an argument is scalar- (Intermediate (ITensor (Tensor ns xs js)), whnf) -> do- ys <- V.mapM (\x -> applyFunc'' env fn x whnf) xs- return $ Intermediate (ITensor (Tensor ns ys js))- (whnf, Intermediate (ITensor (Tensor ns xs js))) -> do- ys <- V.mapM (applyFunc'' env fn whnf) xs- return $ Intermediate (ITensor (Tensor ns ys js))- (Value (TensorData (Tensor ns xs js)), whnf) -> do- ys <- V.mapM (\x -> applyFunc'' env fn (Value x) whnf) xs- return $ Intermediate (ITensor (Tensor ns ys js))- (whnf, Value (TensorData (Tensor ns xs js))) -> do- ys <- V.mapM (applyFunc'' env fn whnf . Value) xs- return $ Intermediate (ITensor (Tensor ns ys js))- _ -> applyFunc'' env fn whnf1 whnf2- where- applyFunc' :: Env -> WHNFData -> EgisonValue -> EvalM EgisonValue- applyFunc' env fn x = applyFunc env fn (Value x) >>= evalWHNF- applyFunc'' :: Env -> WHNFData -> WHNFData -> WHNFData -> EvalM WHNFData- applyFunc'' env fn x y = do- xRef <- newEvaluatedObjectRef x- yRef <- newEvaluatedObjectRef y- applyFunc env fn (Intermediate (ITuple [xRef, yRef]))---evalExpr _ SomethingExpr = return $ Value Something-evalExpr _ UndefinedExpr = return $ Value Undefined-evalExpr _ expr = throwError =<< NotImplemented ("evalExpr for " ++ show expr) <$> getFuncNameStack--evalExprDeep :: Env -> EgisonExpr -> EvalM EgisonValue-evalExprDeep env expr = evalExpr env expr >>= evalWHNF--evalRef :: ObjectRef -> EvalM WHNFData-evalRef ref = do- obj <- liftIO $ readIORef ref- case obj of- WHNF val -> return val- Thunk thunk -> do- val <- thunk- writeObjectRef ref val- return val--evalRefDeep :: ObjectRef -> EvalM EgisonValue-evalRefDeep ref = do- obj <- liftIO $ readIORef ref- case obj of- WHNF (Value val) -> return val- WHNF val -> do- val <- evalWHNF val- writeObjectRef ref $ Value val- return val- Thunk thunk -> do- val <- thunk >>= evalWHNF- writeObjectRef ref $ Value val- return val--evalWHNF :: WHNFData -> EvalM EgisonValue-evalWHNF (Value val) = return val-evalWHNF (Intermediate (IInductiveData name refs)) =- InductiveData name <$> mapM evalRefDeep refs-evalWHNF (Intermediate (IIntHash refs)) = do- refs' <- mapM evalRefDeep refs- return $ IntHash refs'-evalWHNF (Intermediate (ICharHash refs)) = do- refs' <- mapM evalRefDeep refs- return $ CharHash refs'-evalWHNF (Intermediate (IStrHash refs)) = do- refs' <- mapM evalRefDeep refs- return $ StrHash refs'-evalWHNF (Intermediate (ITuple [ref])) = evalRefDeep ref-evalWHNF (Intermediate (ITuple refs)) = Tuple <$> mapM evalRefDeep refs-evalWHNF (Intermediate (ITensor (Tensor ns whnfs js))) = do- vals <- mapM evalWHNF (V.toList whnfs)- return $ TensorData $ Tensor ns (V.fromList vals) js-evalWHNF coll = Collection <$> (fromCollection coll >>= fromMList >>= mapM evalRefDeep . Sq.fromList)--addscript :: (Index EgisonValue, Tensor a) -> Tensor a-addscript (subj, Tensor s t i) = Tensor s t (i ++ [subj])--valuetoTensor2 :: WHNFData -> Tensor WHNFData-valuetoTensor2 (Intermediate (ITensor t)) = t--applyFunc :: Env -> WHNFData -> WHNFData -> EvalM WHNFData-applyFunc env (Value (TensorData (Tensor s1 t1 i1))) tds = do- tds <- fromTupleWHNF tds- if length s1 > length i1 && all (\(Intermediate (ITensor (Tensor s _ i))) -> length s - length i == 1) tds- then do- symId <- fresh- let argnum = length tds- subjs = map (Subscript . symbolScalarData symId . show) [1 .. argnum]- supjs = map (Superscript . symbolScalarData symId . show) [1 .. argnum]- dot <- evalExpr env (stringToVarExpr ".")- makeITuple (Value (TensorData (Tensor s1 t1 (i1 ++ supjs))):map (Intermediate . ITensor . addscript) (zip subjs $ map valuetoTensor2 tds)) >>= applyFunc env dot- else throwError $ Default "applyfunc"--applyFunc env (Intermediate (ITensor (Tensor s1 t1 i1))) tds = do- tds <- fromTupleWHNF tds- if length s1 > length i1 && all (\(Intermediate (ITensor (Tensor s _ i))) -> length s - length i == 1) tds- then do- symId <- fresh- let argnum = length tds- subjs = map (Subscript . symbolScalarData symId . show) [1 .. argnum]- supjs = map (Superscript . symbolScalarData symId . show) [1 .. argnum]- dot <- evalExpr env (stringToVarExpr ".")- makeITuple (map Intermediate (ITensor (Tensor s1 t1 (i1 ++ supjs)):map (ITensor . addscript) (zip subjs $ map valuetoTensor2 tds))) >>= applyFunc env dot- else throwError $ Default "applyfunc"--applyFunc _ (Value (AnonParamFunc env n body)) arg = do- refs <- fromTuple arg- if n == fromIntegral (length refs)- then evalExpr (extendEnv env $ makeBindings (map (\n -> stringToVar $ "::" ++ show n) [1..n]) refs) body- else throwError =<< ArgumentsNumWithNames ["anonymous parameter function"] (fromIntegral n) (length refs) <$> getFuncNameStack-applyFunc _ (Value (Func (Just (Var [funcname] _)) env [name] body)) arg = do- pushFuncName funcname- ref <- newEvaluatedObjectRef arg- result <- evalExpr (extendEnv env $ makeBindings' [name] [ref]) body- popFuncName- return result-applyFunc _ (Value (Func _ env [name] body)) arg = do- ref <- newEvaluatedObjectRef arg- evalExpr (extendEnv env $ makeBindings' [name] [ref]) body-applyFunc _ (Value (Func (Just (Var [funcname] _)) env names body)) arg = do- pushFuncName funcname- refs <- fromTuple arg- result <- if length names == length refs- then evalExpr (extendEnv env $ makeBindings' names refs) body- else throwError =<< ArgumentsNumWithNames names (length names) (length refs) <$> getFuncNameStack- popFuncName- return result-applyFunc _ (Value (Func _ env names body)) arg = do- refs <- fromTuple arg- if length names == length refs- then evalExpr (extendEnv env $ makeBindings' names refs) body- else throwError =<< ArgumentsNumWithNames names (length names) (length refs) <$> getFuncNameStack-applyFunc _ (Value (CFunc _ env name body)) arg = do- refs <- fromTuple arg- seqRef <- liftIO . newIORef $ Sq.fromList (map IElement refs)- col <- liftIO . newIORef $ WHNF $ Intermediate $ ICollection seqRef- if not (null refs)- then evalExpr (extendEnv env $ makeBindings' [name] [col]) body- else throwError =<< ArgumentsNumWithNames [name] 1 0 <$> getFuncNameStack-applyFunc _ (Value (PrimitiveFunc _ func)) arg = func arg-applyFunc _ (Value (IOFunc m)) arg =- case arg of- Value World -> m- _ -> throwError =<< TypeMismatch "world" arg <$> getFuncNameStack-applyFunc _ (Value (ScalarData fn@(SingleTerm 1 [(Symbol{}, 1)]))) arg = do- args <- tupleToList arg- mExprs <- mapM (\arg -> case arg of- ScalarData _ -> extractScalar arg- _ -> throwError =<< EgisonBug "to use undefined functions, you have to use ScalarData args" <$> getFuncNameStack) args- return (Value (ScalarData (SingleTerm 1 [(Apply fn mExprs, 1)])))-applyFunc _ whnf _ = throwError =<< TypeMismatch "function" whnf <$> getFuncNameStack--refArray :: WHNFData -> [EgisonValue] -> EvalM WHNFData-refArray val [] = return val-refArray (Value (IntHash hash)) (index:indices) = do- 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 <- fromEgison index- case HL.lookup key hash of- Just ref -> evalRef ref >>= flip refArray indices- Nothing -> return $ Value Undefined-refArray (Value (CharHash hash)) (index:indices) = do- key <- fromEgison index- case HL.lookup key hash of- Just val -> refArray (Value val) indices- Nothing -> return $ Value Undefined-refArray (Intermediate (ICharHash hash)) (index:indices) = do- 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 <- fromEgison index- case HL.lookup key hash of- Just val -> refArray (Value val) indices- Nothing -> return $ Value Undefined-refArray (Intermediate (IStrHash hash)) (index:indices) = do- key <- fromEgison index- case HL.lookup key hash of- Just ref -> evalRef ref >>= flip refArray indices- Nothing -> return $ Value Undefined-refArray val _ = throwError =<< TypeMismatch "array or hash" val <$> getFuncNameStack--newThunk :: Env -> EgisonExpr -> Object-newThunk env expr = Thunk $ evalExpr env expr--newObjectRef :: Env -> EgisonExpr -> EvalM ObjectRef-newObjectRef env expr = liftIO $ newIORef $ newThunk env expr--writeObjectRef :: ObjectRef -> WHNFData -> EvalM ()-writeObjectRef ref val = liftIO . writeIORef ref $ WHNF val--newEvaluatedObjectRef :: WHNFData -> EvalM ObjectRef-newEvaluatedObjectRef = liftIO . newIORef . WHNF--makeBindings :: [Var] -> [ObjectRef] -> [Binding]-makeBindings = zip--makeBindings' :: [String] -> [ObjectRef] -> [Binding]-makeBindings' xs = zip (map stringToVar xs)--recursiveBind :: Env -> [(Var, EgisonExpr)] -> EvalM Env-recursiveBind env bindings = do- let (names, _) = unzip bindings- refs <- replicateM (length bindings) $ newObjectRef nullEnv UndefinedExpr- let env' = extendEnv env $ makeBindings names refs- let Env frame _ = env'- zipWithM_ (\ref (name,expr) ->- case expr of- MemoizedLambdaExpr names body -> do- hashRef <- liftIO $ newIORef HL.empty- liftIO . writeIORef ref . WHNF . Value $ MemoizedFunc (Just name) ref hashRef env' names body- LambdaExpr _ _ -> do- whnf <- evalExpr env' expr- case whnf of- Value (Func _ env args body) -> liftIO . writeIORef ref . WHNF $ Value (Func (Just name) env args body)- CambdaExpr _ _ -> do- whnf <- evalExpr env' expr- case whnf of- Value (CFunc _ env arg body) -> liftIO . writeIORef ref . WHNF $ Value (CFunc (Just name) env arg body)- FunctionExpr args -> liftIO . writeIORef ref . Thunk $ evalExpr (Env frame (Just $ varToVarWithIndices name)) $ FunctionExpr args- _ | isVarWithIndices name -> liftIO . writeIORef ref . Thunk $ evalExpr (Env frame (Just $ varToVarWithIndices name)) expr- | otherwise -> liftIO . writeIORef ref . Thunk $ evalExpr env' expr)- refs bindings- return env'- where- isVarWithIndices :: Var -> Bool- isVarWithIndices (Var _ xs) = not $ null xs--recursiveRebind :: Env -> (Var, EgisonExpr) -> EvalM Env-recursiveRebind env (name, expr) = do- case refVar env name of- Nothing -> throwError =<< UnboundVariable (prettyStr name) <$> getFuncNameStack- Just ref -> case expr of- MemoizedLambdaExpr names body -> do- hashRef <- liftIO $ newIORef HL.empty- liftIO . writeIORef ref . WHNF . Value $ MemoizedFunc (Just name) ref hashRef env names body- LambdaExpr _ _ -> do- whnf <- evalExpr env expr- case whnf of- Value (Func _ env args body) -> liftIO . writeIORef ref . WHNF $ Value (Func (Just name) env args body)- CambdaExpr _ _ -> do- whnf <- evalExpr env expr- case whnf of- Value (CFunc _ env arg body) -> liftIO . writeIORef ref . WHNF $ Value (CFunc (Just name) env arg body)- _ -> liftIO . writeIORef ref . Thunk $ evalExpr env expr- return env------- Pattern Match-----patternMatch :: PMMode -> Env -> EgisonPattern -> WHNFData -> Matcher -> EvalM (MList EvalM Match)-patternMatch pmmode env pattern target matcher =- case pmmode of- DFSMode -> processMStatesAllDFS (msingleton initMState)- BFSMode -> processMStatesAll [msingleton initMState]- where- initMState = MState { mStateEnv = env- , loopPatCtx = []- , seqPatCtx = []- , mStateBindings = []- , mTrees = [MAtom pattern target matcher]- }--processMStatesAllDFS :: MList EvalM MatchingState -> EvalM (MList EvalM Match)-processMStatesAllDFS MNil = return MNil-processMStatesAllDFS (MCons (MState _ _ [] bindings []) ms) = MCons bindings . processMStatesAllDFS <$> ms-processMStatesAllDFS (MCons mstate ms) = processMState mstate >>= (`mappend` ms) >>= processMStatesAllDFS--processMStatesAllDFSForall :: MList EvalM MatchingState -> EvalM (MList EvalM MatchingState)-processMStatesAllDFSForall MNil = return MNil-processMStatesAllDFSForall (MCons mstate@(MState _ _ (ForallPatContext _ _ : _) _ []) ms) = MCons mstate . processMStatesAllDFSForall <$> ms-processMStatesAllDFSForall (MCons mstate ms) = processMState mstate >>= (`mappend` ms) >>= processMStatesAllDFSForall--processMStatesAll :: [MList EvalM MatchingState] -> EvalM (MList EvalM Match)-processMStatesAll [] = return MNil-processMStatesAll streams = do- (matches, streams') <- mapM processMStates streams >>= extractMatches . concat- mappend (fromList matches) $ processMStatesAll streams'--processMStates :: MList EvalM MatchingState -> EvalM [MList EvalM MatchingState]-processMStates MNil = return []-processMStates (MCons state stream) = (\x y -> [x, y]) <$> processMState state <*> stream--extractMatches :: [MList EvalM MatchingState] -> EvalM ([Match], [MList EvalM MatchingState])-extractMatches = extractMatches' ([], [])- where- extractMatches' :: ([Match], [MList EvalM MatchingState]) -> [MList EvalM MatchingState] -> EvalM ([Match], [MList EvalM MatchingState])- extractMatches' (xs, ys) [] = return (xs, ys)- extractMatches' (xs, ys) (MCons (gatherBindings -> Just bindings) states : rest) = do- states' <- states- extractMatches' (xs ++ [bindings], ys ++ [states']) rest- extractMatches' (xs, ys) (stream:rest) = extractMatches' (xs, ys ++ [stream]) rest--gatherBindings :: MatchingState -> Maybe [Binding]-gatherBindings mstate@MState{ seqPatCtx = [], mTrees = [] } = return (mStateBindings mstate)-gatherBindings _ = Nothing--processMState :: MatchingState -> EvalM (MList EvalM MatchingState)-processMState state =- if nullMState state- then processMState' state- else case splitMState state of- (1, state1, state2) -> do- result <- processMStatesAllDFS (msingleton state1)- case result of- MNil -> return $ msingleton state2- _ -> return MNil- (0, MState e l s b [MAtom (ForallPat p1 p2) m t], MState{ mTrees = trees }) -> do- states <- processMStatesAllDFSForall (msingleton (MState e l (ForallPatContext [] []:s) b [MAtom p1 m t]))- statess' <- mmap (\(MState e' l' (ForallPatContext ms ts:s') b' []) -> do- let mat' = makeTuple ms- tgt' <- makeITuple ts- processMStatesAllDFSForall (msingleton (MState e' l' (ForallPatContext [] []:s') b' [MAtom p2 tgt' mat']))) states- b <- mAny (\s -> case s of- MNil -> return True- _ -> return False) statess'- if b- then return MNil--- else return MNil- else do nstatess <- mmap (\states' -> mmap (\(MState e' l' (ForallPatContext [] []:s') b' []) -> return $ MState e' l' s' b' trees) states') statess'- mconcat nstatess- _ -> processMState' state- where- nullMState :: MatchingState -> Bool- nullMState MState{ mTrees = [] } = True- nullMState MState{ mTrees = MNode _ state : _ } = nullMState state- nullMState _ = False- splitMState :: MatchingState -> (Integer, MatchingState, MatchingState)- splitMState mstate@MState{ mTrees = MAtom (NotPat pattern) target matcher : trees } =- (1, mstate { seqPatCtx = [], mTrees = [MAtom pattern target matcher] }, mstate { mTrees = trees })- splitMState mstate@MState{ mTrees = MAtom pattern target matcher : trees } =- (0, mstate { mTrees = [MAtom pattern target matcher] }, mstate { mTrees = trees })- splitMState mstate@MState{ mTrees = MNode penv state' : trees } =- (f, mstate { mTrees = [MNode penv state1] }, mstate { mTrees = MNode penv state2 : trees })- where (f, state1, state2) = splitMState state'--processMState' :: MatchingState -> EvalM (MList EvalM MatchingState)---processMState' MState{ seqPatCtx = [], mTrees = [] } = throwError =<< EgisonBug "should not reach here (empty matching-state)" <$> getFuncNameStack-processMState' mstate@MState{ seqPatCtx = [], mTrees = [] } = return . msingleton $ mstate -- for forall pattern used in matchAll (not matchAllDFS)---- Sequential patterns and forall pattern-processMState' mstate@MState{ seqPatCtx = SeqPatContext stack SeqNilPat [] []:seqs, mTrees = [] } =- return . msingleton $ mstate { seqPatCtx = seqs, mTrees = stack }-processMState' mstate@MState{ seqPatCtx = SeqPatContext stack seqPat mats tgts:seqs, mTrees = [] } = do- let mat' = makeTuple mats- tgt' <- makeITuple tgts- return . msingleton $ mstate { seqPatCtx = seqs, mTrees = MAtom seqPat tgt' mat' : stack }-processMState' mstate@MState{ seqPatCtx = ForallPatContext _ _:_, mTrees = [] } =- return . msingleton $ mstate---- Matching Nodes---processMState' MState{ mTrees = MNode _ MState{ mStateBindings = [], mTrees = [] }:_ } = throwError =<< EgisonBug "should not reach here (empty matching-node)" <$> getFuncNameStack-processMState' mstate@MState{ mTrees = MNode _ MState{ seqPatCtx = [], mTrees = [] }:trees } = return . msingleton $ mstate { mTrees = trees }--processMState' ms1@MState{ mTrees = MNode penv ms2@MState{ mTrees = MAtom (VarPat name) target matcher:trees' }:trees } =- case lookup name penv of- Just pattern ->- case trees' of- [] -> return . msingleton $ ms1 { mTrees = MAtom pattern target matcher:trees }- _ -> return . msingleton $ ms1 { mTrees = MAtom pattern target matcher:MNode penv (ms2 { mTrees = trees' }):trees }- Nothing -> throwError =<< UnboundVariable name <$> getFuncNameStack--processMState' ms1@(MState _ _ _ bindings (MNode penv ms2@(MState env' loops' _ _ (MAtom (IndexedPat (VarPat name) indices) target matcher:trees')):trees)) =- case lookup name penv of- Just pattern -> do- let env'' = extendEnvForNonLinearPatterns env' bindings loops'- indices' <- mapM (evalExpr env'' >=> fmap fromInteger . fromWHNF) indices- let pattern' = IndexedPat pattern $ map IntegerExpr indices'- case trees' of- [] -> return . msingleton $ ms1 { mTrees = MAtom pattern' target matcher:trees }- _ -> return . msingleton $ ms1 { mTrees = MAtom pattern' target matcher:MNode penv (ms2 { mTrees = trees' }):trees }- Nothing -> throwError =<< UnboundVariable name <$> getFuncNameStack--processMState' mstate@MState{ mTrees = MNode penv state:trees } =- processMState' state >>= mmap (\state' -> case state' of---egi MState { mTrees = [] } -> return $ mstate { mTrees = trees }- _ -> return $ mstate { mTrees = MNode penv state':trees })---- Matching Atoms-processMState' mstate@(MState env loops seqs bindings (MAtom pattern target matcher:trees)) =- let env' = extendEnvForNonLinearPatterns env bindings loops in- case pattern of- InductiveOrPApplyPat name args ->- case refVar env (stringToVar name) of- Nothing -> processMState' (mstate { mTrees = MAtom (InductivePat name args) target matcher:trees })- Just ref -> do- whnf <- evalRef ref- case whnf of- Value PatternFunc{} ->- processMState' (mstate { mTrees = MAtom (PApplyPat (VarExpr (stringToVar name)) args) target matcher:trees })- _ ->- processMState' (mstate { mTrees = MAtom (InductivePat name args) target matcher:trees })-- NotPat _ -> throwError =<< EgisonBug "should not reach here (not-pattern)" <$> getFuncNameStack- VarPat _ -> throwError $ Default $ "cannot use variable except in pattern function:" ++ prettyStr pattern-- LetPat bindings' pattern' -> do- b <- fmap concat (mapM extractBindings bindings')- return . msingleton $ mstate { mStateBindings = b ++ bindings, mTrees = MAtom pattern' target matcher:trees }- where- extractBindings ([name], expr) = makeBindings [name] . (:[]) <$> newObjectRef env' expr- extractBindings (names, expr) = makeBindings names <$> (evalExpr env' expr >>= fromTuple)-- PredPat predicate -> do- func <- evalExpr env' predicate- let arg = target- result <- applyFunc env func arg >>= fromWHNF- if result then return . msingleton $ mstate { mTrees = trees }- else return MNil-- PApplyPat func args -> do- func' <- evalExpr env' func- case func' of- Value (PatternFunc env'' names expr) ->- return . msingleton $ mstate { mTrees = MNode penv (MState env'' [] [] [] [MAtom expr target matcher]) : trees }- where penv = zip names args- _ -> throwError =<< TypeMismatch "pattern constructor" func' <$> getFuncNameStack-- DApplyPat func args ->- return . msingleton $ mstate { mTrees = MAtom (InductivePat "apply" [func, toListPat args]) target matcher:trees }-- LoopPat name (LoopRange start ends endPat) pat pat' -> do- startNum <- evalExpr env' start >>= fromWHNF :: (EvalM Integer)- startNumRef <- newEvaluatedObjectRef $ Value $ toEgison (startNum - 1)- ends' <- evalExpr env' ends- case ends' of- Value (ScalarData _) -> do -- the case when the end numbers are an integer- endsRef <- newEvaluatedObjectRef ends'- inners <- liftIO . newIORef $ Sq.fromList [IElement endsRef]- endsRef' <- liftIO $ newIORef (WHNF (Intermediate (ICollection inners)))- return . msingleton $ mstate { loopPatCtx = LoopPatContext (name, startNumRef) endsRef' endPat pat pat':loops- , mTrees = MAtom ContPat target matcher:trees }- _ -> do -- the case when the end numbers are a collection- endsRef <- newEvaluatedObjectRef ends'- return . msingleton $ mstate { loopPatCtx = LoopPatContext (name, startNumRef) endsRef endPat pat pat':loops- , mTrees = MAtom ContPat target matcher:trees }- ContPat ->- case loops of- [] -> throwError $ Default "cannot use cont pattern except in loop pattern"- LoopPatContext (name, startNumRef) endsRef endPat pat pat' : loops' -> do- startNumWhnf <- evalRef startNumRef- startNum <- fromWHNF startNumWhnf :: (EvalM Integer)- nextNumRef <- newEvaluatedObjectRef $ Value $ toEgison (startNum + 1)- ends <- evalRef endsRef- b <- isEmptyCollection ends- if b- then return MNil- else do- (carEndsRef, cdrEndsRef) <- fromJust <$> runMaybeT (unconsCollection ends)- b2 <- evalRef cdrEndsRef >>= isEmptyCollection- carEndsNum <- evalRef carEndsRef >>= fromWHNF- return $ if- | startNum > carEndsNum -> MNil- | startNum == carEndsNum && b2 ->- fromList [mstate { loopPatCtx = loops', mTrees = MAtom endPat startNumWhnf Something:MAtom pat' target matcher:trees }]- | startNum == carEndsNum ->- fromList [mstate { loopPatCtx = loops', mTrees = MAtom endPat startNumWhnf Something:MAtom pat' target matcher:trees },- mstate { loopPatCtx = LoopPatContext (name, nextNumRef) cdrEndsRef endPat pat pat':loops', mTrees = MAtom pat target matcher:trees }]- | otherwise ->- fromList [mstate { loopPatCtx = LoopPatContext (name, nextNumRef) endsRef endPat pat pat':loops', mTrees = MAtom pat target matcher:trees }]- SeqNilPat -> throwError =<< EgisonBug "should not reach here (seq nil pattern)" <$> getFuncNameStack- SeqConsPat pattern pattern' -> return . msingleton $ MState env loops (SeqPatContext trees pattern' [] []:seqs) bindings [MAtom pattern target matcher]- LaterPatVar ->- case seqs of- [] -> throwError $ Default "cannot use # out of seq patterns"- (SeqPatContext stack pat mats tgts:seqs) -> return . msingleton $ MState env loops (SeqPatContext stack pat (mats ++ [matcher]) (tgts ++ [target]):seqs) bindings trees- (ForallPatContext mats tgts:seqs) -> return . msingleton $ MState env loops (ForallPatContext (mats ++ [matcher]) (tgts ++ [target]):seqs) bindings trees- AndPat patterns ->- let trees' = map (\pat -> MAtom pat target matcher) patterns ++ trees- in return . msingleton $ mstate { mTrees = trees' }- OrPat patterns ->- return $ fromList $ flip map patterns $ \pat ->- mstate { mTrees = MAtom pat target matcher : trees }-- _ ->- case matcher of- UserMatcher{} -> do- (patterns, targetss, matchers) <- inductiveMatch env' pattern target matcher- case length patterns of- 1 ->- mfor targetss $ \ref -> do- targets <- evalRef ref >>= (\x -> return [x])- let trees' = zipWith3 MAtom patterns targets matchers ++ trees- return $ mstate { mTrees = trees' }- _ ->- mfor targetss $ \ref -> do- targets <- evalRef ref >>= fromTupleWHNF- let trees' = zipWith3 MAtom patterns targets matchers ++ trees- return $ mstate { mTrees = trees' }-- Tuple matchers ->- case pattern of- ValuePat _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }- WildCard -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }- PatVar _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }- IndexedPat _ _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }- TuplePat patterns -> do- targets <- fromTupleWHNF target- when (length patterns /= length targets) $ throwError =<< TupleLength (length patterns) (length targets) <$> getFuncNameStack- when (length patterns /= length matchers) $ throwError =<< TupleLength (length patterns) (length matchers) <$> getFuncNameStack- let trees' = zipWith3 MAtom patterns targets matchers ++ trees- return . msingleton $ mstate { mTrees = trees' }- _ -> throwError $ Default $ "should not reach here. matcher: " ++ show matcher ++ ", pattern: " ++ show pattern-- Something ->- case pattern of- ValuePat valExpr -> do- val <- evalExprDeep env' valExpr- tgtVal <- evalWHNF target- if val == tgtVal- then return . msingleton $ mstate { mTrees = trees }- else return MNil- WildCard -> return . msingleton $ mstate { mTrees = trees }- PatVar name -> do- targetRef <- newEvaluatedObjectRef target- return . msingleton $ mstate { mStateBindings = (name, targetRef):bindings, mTrees = trees }- IndexedPat (PatVar name) indices -> do- indices <- mapM (evalExpr env' >=> fmap fromInteger . fromWHNF) indices- case lookup name bindings of- Just ref -> do- obj <- evalRef ref >>= updateHash indices >>= newEvaluatedObjectRef- return . msingleton $ mstate { mStateBindings = subst name obj bindings, mTrees = trees }- Nothing -> do- obj <- updateHash indices (Intermediate . IIntHash $ HL.empty) >>= newEvaluatedObjectRef- return . msingleton $ mstate { mStateBindings = (name,obj):bindings, mTrees = trees }- where- updateHash :: [Integer] -> WHNFData -> EvalM WHNFData- updateHash [index] (Intermediate (IIntHash hash)) = do- targetRef <- newEvaluatedObjectRef target- return . Intermediate . IIntHash $ HL.insert index targetRef hash- updateHash (index:indices) (Intermediate (IIntHash hash)) = do- val <- maybe (return $ Intermediate $ IIntHash HL.empty) evalRef $ HL.lookup index hash- ref <- updateHash indices val >>= newEvaluatedObjectRef- return . Intermediate . IIntHash $ HL.insert index ref hash- updateHash indices (Value (IntHash hash)) = do- let keys = HL.keys hash- vals <- mapM (newEvaluatedObjectRef . Value) $ HL.elems hash- updateHash indices (Intermediate $ IIntHash $ HL.fromList $ zip keys vals)- updateHash _ v = throwError $ Default $ "expected hash value: " ++ show v- subst :: (Eq a) => a -> b -> [(a, b)] -> [(a, b)]- subst k nv ((k', v'):xs) | k == k' = (k', nv):subst k nv xs- | otherwise = (k', v'):subst k nv xs- subst _ _ [] = []- IndexedPat pattern _ -> throwError $ Default ("invalid indexed-pattern: " ++ prettyStr pattern)- TuplePat patterns -> do- targets <- fromTupleWHNF target- when (length patterns /= length targets) $ throwError =<< TupleLength (length patterns) (length targets) <$> getFuncNameStack- let trees' = zipWith3 MAtom patterns targets (replicate (length patterns) Something) ++ trees- return . msingleton $ mstate { mTrees = trees' }- _ -> throwError $ Default $ "something can only match with a pattern variable. not: " ++ prettyStr pattern- _ -> throwError =<< EgisonBug ("should not reach here. matcher: " ++ show matcher ++ ", pattern: " ++ show pattern) <$> getFuncNameStack--inductiveMatch :: Env -> EgisonPattern -> WHNFData -> Matcher ->- EvalM ([EgisonPattern], MList EvalM ObjectRef, [Matcher])-inductiveMatch env pattern target (UserMatcher matcherEnv clauses) =- foldr tryPPMatchClause failPPPatternMatch clauses- where- tryPPMatchClause (pat, matchers, clauses) cont = do- result <- runMaybeT $ primitivePatPatternMatch env pat pattern- case result of- Just ([pattern], bindings) -> do- targetss <- foldr (tryPDMatchClause bindings) failPDPatternMatch clauses- matcher <- evalExpr matcherEnv matchers >>= evalMatcherWHNF- return ([pattern], targetss, [matcher])- Just (patterns, bindings) -> do- targetss <- foldr (tryPDMatchClause bindings) failPDPatternMatch clauses- matchers <- fromTupleValue <$> (evalExpr matcherEnv matchers >>= evalMatcherWHNF)- return (patterns, targetss, matchers)- _ -> cont- tryPDMatchClause bindings (pat, expr) cont = do- result <- runMaybeT $ primitiveDataPatternMatch pat target- case result of- Just bindings' -> do- let env = extendEnv matcherEnv $ bindings ++ bindings'- evalExpr env expr >>= fromCollection- _ -> cont- failPPPatternMatch = throwError $ Default "failed primitive pattern pattern match"- failPDPatternMatch = throwError $ Default "failed primitive data pattern match"--primitivePatPatternMatch :: Env -> PrimitivePatPattern -> EgisonPattern ->- MatchM ([EgisonPattern], [Binding])-primitivePatPatternMatch _ PPWildCard WildCard = return ([], [])-primitivePatPatternMatch _ PPPatVar pattern = return ([pattern], [])-primitivePatPatternMatch env (PPValuePat name) (ValuePat expr) = do- ref <- lift $ newObjectRef env expr- return ([], [(stringToVar name, ref)])-primitivePatPatternMatch env (PPInductivePat name patterns) (InductivePat name' exprs)- | name == name' && length patterns == length exprs =- (concat *** concat) . unzip <$> zipWithM (primitivePatPatternMatch env) patterns exprs- | otherwise = matchFail-primitivePatPatternMatch env (PPTuplePat patterns) (TuplePat exprs)- | length patterns == length exprs =- (concat *** concat) . unzip <$> zipWithM (primitivePatPatternMatch env) patterns exprs- | otherwise = matchFail-primitivePatPatternMatch _ _ _ = matchFail--primitiveDataPatternMatch :: PrimitiveDataPattern -> WHNFData -> MatchM [Binding]-primitiveDataPatternMatch PDWildCard _ = return []-primitiveDataPatternMatch (PDPatVar name) whnf = do- ref <- lift $ newEvaluatedObjectRef whnf- return [(stringToVar name, ref)]-primitiveDataPatternMatch (PDInductivePat name patterns) whnf =- case whnf of- Intermediate (IInductiveData name' refs) | name == name' -> do- whnfs <- lift $ mapM evalRef refs- concat <$> zipWithM primitiveDataPatternMatch patterns whnfs- Value (InductiveData name' vals) | name == name' -> do- let whnfs = map Value vals- concat <$> zipWithM primitiveDataPatternMatch patterns whnfs- _ -> matchFail-primitiveDataPatternMatch (PDTuplePat patterns) whnf =- case whnf of- Intermediate (ITuple refs) -> do- whnfs <- lift $ mapM evalRef refs- concat <$> zipWithM primitiveDataPatternMatch patterns whnfs- Value (Tuple vals) -> do- let whnfs = map Value vals- concat <$> zipWithM primitiveDataPatternMatch patterns whnfs- _ -> matchFail-primitiveDataPatternMatch PDEmptyPat whnf = do- isEmpty <- lift $ isEmptyCollection whnf- if isEmpty then return [] else matchFail-primitiveDataPatternMatch (PDConsPat pattern pattern') whnf = do- (head, tail) <- unconsCollection whnf- head' <- lift $ evalRef head- tail' <- lift $ evalRef tail- (++) <$> primitiveDataPatternMatch pattern head'- <*> primitiveDataPatternMatch pattern' tail'-primitiveDataPatternMatch (PDSnocPat pattern pattern') whnf = do- (init, last) <- unsnocCollection whnf- init' <- lift $ evalRef init- last' <- lift $ evalRef last- (++) <$> primitiveDataPatternMatch pattern init'- <*> primitiveDataPatternMatch pattern' last'-primitiveDataPatternMatch (PDConstantPat expr) whnf = do- target <- either (const matchFail) return $ extractPrimitiveValue whnf- isEqual <- lift $ (==) <$> evalExprDeep nullEnv expr <*> pure target- if isEqual then return [] else matchFail- where- extractPrimitiveValue :: WHNFData -> Either ([String] -> EgisonError) EgisonValue- extractPrimitiveValue (Value val@(Char _)) = return val- extractPrimitiveValue (Value val@(Bool _)) = return val- extractPrimitiveValue (Value val@(ScalarData _)) = return val- extractPrimitiveValue (Value val@(Float _)) = return val- extractPrimitiveValue whnf =- -- we don't need to extract call stack since detailed error information is not used- throwError $ TypeMismatch "primitive value" whnf--expandCollection :: WHNFData -> EvalM (Seq Inner)-expandCollection (Value (Collection vals)) =- mapM (fmap IElement . newEvaluatedObjectRef . Value) vals-expandCollection (Intermediate (ICollection innersRef)) = liftIO $ readIORef innersRef-expandCollection val = throwError =<< TypeMismatch "collection" val <$> getFuncNameStack--isEmptyCollection :: WHNFData -> EvalM Bool-isEmptyCollection (Value (Collection col)) = return $ Sq.null col-isEmptyCollection coll@(Intermediate (ICollection innersRef)) = do- inners <- liftIO $ readIORef innersRef- case Sq.viewl inners of- EmptyL -> return True- ISubCollection ref' :< tInners -> do- hInners <- evalRef ref' >>= expandCollection- liftIO $ writeIORef innersRef (hInners >< tInners)- isEmptyCollection coll- _ -> return False-isEmptyCollection _ = return False--unconsCollection :: WHNFData -> MatchM (ObjectRef, ObjectRef)-unconsCollection (Value (Collection col)) =- case Sq.viewl col of- EmptyL -> matchFail- val :< vals ->- lift $ (,) <$> newEvaluatedObjectRef (Value val)- <*> newEvaluatedObjectRef (Value $ Collection vals)-unconsCollection coll@(Intermediate (ICollection innersRef)) = do- inners <- liftIO $ readIORef innersRef- case Sq.viewl inners of- EmptyL -> matchFail- IElement ref' :< tInners -> do- tInnersRef <- liftIO $ newIORef tInners- lift $ (ref', ) <$> newEvaluatedObjectRef (Intermediate $ ICollection tInnersRef)- ISubCollection ref' :< tInners -> do- hInners <- lift $ evalRef ref' >>= expandCollection- liftIO $ writeIORef innersRef (hInners >< tInners)- unconsCollection coll-unconsCollection _ = matchFail--unsnocCollection :: WHNFData -> MatchM (ObjectRef, ObjectRef)-unsnocCollection (Value (Collection col)) =- case Sq.viewr col of- EmptyR -> matchFail- vals :> val ->- lift $ (,) <$> newEvaluatedObjectRef (Value $ Collection vals)- <*> newEvaluatedObjectRef (Value val)-unsnocCollection coll@(Intermediate (ICollection innersRef)) = do- inners <- liftIO $ readIORef innersRef- case Sq.viewr inners of- EmptyR -> matchFail- hInners :> IElement ref' -> do- hInnersRef <- liftIO $ newIORef hInners- lift $ (, ref') <$> newEvaluatedObjectRef (Intermediate $ ICollection hInnersRef)- hInners :> ISubCollection ref' -> do- tInners <- lift $ evalRef ref' >>= expandCollection- liftIO $ writeIORef innersRef (hInners >< tInners)- unsnocCollection coll-unsnocCollection _ = matchFail--extendEnvForNonLinearPatterns :: Env -> [Binding] -> [LoopPatContext] -> Env-extendEnvForNonLinearPatterns env bindings loops = extendEnv env $ bindings ++ map (\(LoopPatContext binding _ _ _ _) -> binding) loops--evalMatcherWHNF :: WHNFData -> EvalM Matcher-evalMatcherWHNF (Value matcher@Something) = return matcher-evalMatcherWHNF (Value matcher@UserMatcher{}) = return matcher-evalMatcherWHNF (Value (Tuple ms)) = Tuple <$> mapM (evalMatcherWHNF . Value) ms-evalMatcherWHNF (Intermediate (ITuple refs)) = do- whnfs <- mapM evalRef refs- ms <- mapM evalMatcherWHNF whnfs- return $ Tuple ms-evalMatcherWHNF whnf = throwError =<< TypeMismatch "matcher" whnf <$> getFuncNameStack------- Util----toListPat :: [EgisonPattern] -> EgisonPattern-toListPat [] = InductivePat "nil" []-toListPat (pat:pats) = InductivePat "cons" [pat, toListPat pats]--fromTuple :: WHNFData -> EvalM [ObjectRef]-fromTuple (Intermediate (ITuple refs)) = return refs-fromTuple (Value (Tuple vals)) = mapM (newEvaluatedObjectRef . Value) vals-fromTuple whnf = return <$> newEvaluatedObjectRef whnf--fromTupleWHNF :: WHNFData -> EvalM [WHNFData]-fromTupleWHNF (Intermediate (ITuple refs)) = mapM evalRef refs-fromTupleWHNF (Value (Tuple vals)) = return $ map Value vals-fromTupleWHNF whnf = return [whnf]--fromTupleValue :: EgisonValue -> [EgisonValue]-fromTupleValue (Tuple vals) = vals-fromTupleValue val = [val]--fromCollection :: WHNFData -> EvalM (MList EvalM ObjectRef)-fromCollection (Value (Collection vals)) =- if Sq.null vals then return MNil- else fromSeq <$> mapM (newEvaluatedObjectRef . Value) vals-fromCollection whnf@(Intermediate (ICollection _)) = do- isEmpty <- isEmptyCollection whnf- if isEmpty- then return MNil- else do- (head, tail) <- fromJust <$> runMaybeT (unconsCollection whnf)- tail' <- evalRef tail- return $ MCons head (fromCollection tail')-fromCollection whnf = throwError =<< TypeMismatch "collection" whnf <$> getFuncNameStack--tupleToList :: WHNFData -> EvalM [EgisonValue]-tupleToList whnf = do- val <- evalWHNF whnf- return $ tupleToList' val- where- tupleToList' (Tuple vals) = vals- tupleToList' val = [val]--collectionToList :: WHNFData -> EvalM [EgisonValue]-collectionToList whnf = do- val <- evalWHNF whnf- collectionToList' val- where- collectionToList' :: EgisonValue -> EvalM [EgisonValue]- collectionToList' (Collection sq) = return $ toList sq- collectionToList' val = throwError =<< TypeMismatch "collection" (Value val) <$> getFuncNameStack--makeTuple :: [EgisonValue] -> EgisonValue-makeTuple [] = Tuple []-makeTuple [x] = x-makeTuple xs = Tuple xs--makeITuple :: [WHNFData] -> EvalM WHNFData-makeITuple [] = return $ Intermediate (ITuple [])-makeITuple [x] = return x-makeITuple xs = Intermediate . ITuple <$> mapM newEvaluatedObjectRef xs--makeICollection :: [WHNFData] -> EvalM WHNFData-makeICollection xs = do- is <- mapM (\x -> IElement <$> newEvaluatedObjectRef x) xs- v <- liftIO $ newIORef $ Sq.fromList is- return $ Intermediate $ ICollection v---- Refer the specified tensor index with potential overriding of the index.-refTensorWithOverride :: HasTensor a => Bool -> [Index EgisonValue] -> Tensor a -> EvalM a-refTensorWithOverride override js (Tensor ns xs is) =- tref js' (Tensor ns xs js') >>= toTensor >>= tContract' >>= fromTensor+ -- * Egison code evaluation+ ( evalExprShallow+ , evalExprDeep+ , evalWHNF+ -- * Environment+ , recursiveBind+ -- * Pattern matching+ , patternMatch+ ) where++import Prelude hiding (mapM, mappend, mconcat)++import Control.Arrow+import Control.Monad.Except (throwError)+import Control.Monad.State hiding (mapM, join)+import Control.Monad.Trans.Maybe++import Data.Char (isUpper)+import Data.Foldable (toList)+import Data.IORef+import Data.List (partition)+import Data.Maybe+import qualified Data.Sequence as Sq+import Data.Traversable (mapM)++import qualified Data.HashMap.Lazy as HL+import qualified Data.Vector as V++import Language.Egison.Data+import Language.Egison.Data.Collection+import Language.Egison.Data.Utils+import Language.Egison.EvalState (MonadEval(..), mLabelFuncName)+import Language.Egison.IExpr+import Language.Egison.Match+import Language.Egison.Math+import Language.Egison.MList+import Language.Egison.RState+import Language.Egison.Tensor+++evalConstant :: ConstantExpr -> EgisonValue+evalConstant (CharExpr c) = Char c+evalConstant (StringExpr s) = toEgison s+evalConstant (BoolExpr b) = Bool b+evalConstant (IntegerExpr x) = toEgison x+evalConstant (FloatExpr x) = Float x+evalConstant SomethingExpr = Something+evalConstant UndefinedExpr = Undefined++evalExprShallow :: Env -> IExpr -> EvalM WHNFData+evalExprShallow _ (IConstantExpr c) = return $ Value (evalConstant c)++evalExprShallow env (IQuoteExpr expr) = do+ whnf <- evalExprShallow env expr+ case whnf of+ Value (ScalarData s) -> return . Value . ScalarData $ SingleTerm 1 [(Quote s, 1)]+ _ -> throwError =<< TypeMismatch "scalar in quote" whnf <$> getFuncNameStack++evalExprShallow env (IQuoteSymbolExpr expr) = do+ whnf <- evalExprShallow env expr+ case whnf of+ Value (Func (Just name) _ _ _) -> return . Value $ symbolScalarData "" name+ Value (ScalarData _) -> return whnf+ _ -> throwError =<< TypeMismatch "value in quote-function" whnf <$> getFuncNameStack++evalExprShallow env (IVarExpr name) =+ case refVar env (Var name []) of+ Nothing | isUpper (head name) ->+ return $ Value (InductiveData name [])+ Nothing -> return $ Value (symbolScalarData "" name)+ Just ref -> evalRef ref++evalExprShallow _ (ITupleExpr []) = return . Value $ Tuple []+evalExprShallow env (ITupleExpr [expr]) = evalExprShallow env expr+evalExprShallow env (ITupleExpr exprs) = ITuple <$> mapM (newThunkRef env) exprs++evalExprShallow _ (ICollectionExpr []) = return . Value $ Collection Sq.empty++evalExprShallow env (ICollectionExpr inners) = do+ inners' <- mapM ((IElement <$>) . newThunkRef env) inners+ innersSeq <- liftIO $ newIORef $ Sq.fromList inners'+ return $ ICollection innersSeq++evalExprShallow env (IConsExpr x xs) = do+ x' <- newThunkRef env x+ xs' <- newThunkRef env xs+ innersSeq <- liftIO $ newIORef $ Sq.fromList [IElement x', ISubCollection xs']+ return $ ICollection innersSeq++evalExprShallow env (IJoinExpr xs ys) = do+ xs' <- newThunkRef env xs+ ys' <- newThunkRef env ys+ innersSeq <- liftIO $ newIORef $ Sq.fromList [ISubCollection xs', ISubCollection ys']+ return $ ICollection innersSeq++evalExprShallow env@(Env frame maybe_vwi) (IVectorExpr exprs) = do+ let n = toInteger (length exprs)+ whnfs <- zipWithM evalWithIndex exprs [1..]+ case whnfs of+ ITensor Tensor{}:_ ->+ zipWithM f whnfs [1..] >>= tConcat' >>= fromTensor+ _ -> makeITensorFromWHNF [n] whnfs+ where+ evalWithIndex :: IExpr -> Integer -> EvalM WHNFData+ evalWithIndex expr index = evalExprShallow env' expr+ where+ env' = case maybe_vwi of+ Nothing -> env+ Just (name, indices) ->+ Env frame (Just (name, zipWith changeIndex indices [toEgison index]))+ f (ITensor (Tensor ns xs indices)) i = do+ xs <- mapM evalRef xs+ let xs' = V.zipWith g xs $ V.fromList (map (\ms -> map toEgison (i:ms)) $ enumTensorIndices ns)+ xs' <- mapM newEvaluatedObjectRef xs'+ return $ Tensor ns xs' indices+ f x _ = Scalar <$> newEvaluatedObjectRef x+ g (Value (ScalarData (Div (Plus [Term 1 [(FunctionData fn argnames args js, 1)]]) p))) ms =+ Value (ScalarData (Div (Plus [Term 1 [(FunctionData fn' argnames args js, 1)]]) p))+ where+ fn' = case maybe_vwi of+ Nothing -> fn+ Just (name, indices) ->+ symbolScalarData' (name ++ concatMap show (zipWith changeIndex indices ms))+ g x _ = x++evalExprShallow env (ITensorExpr nsExpr xsExpr) = do+ nsWhnf <- evalExprShallow env nsExpr+ ns <- (collectionToRefs nsWhnf >>= fromMList >>= mapM evalRefDeep >>= mapM fromEgison) :: EvalM [Integer]+ xsWhnf <- evalExprShallow env xsExpr+ xs <- collectionToRefs xsWhnf >>= fromMList >>= mapM evalRef+ if product ns == toInteger (length xs)+ then makeITensorFromWHNF ns xs+ else throwError =<< InconsistentTensorShape <$> getFuncNameStack++evalExprShallow env (IHashExpr assocs) = do+ let (keyExprs, exprs) = unzip assocs+ keyWhnfs <- mapM (evalExprShallow env) keyExprs+ keys <- mapM makeHashKey keyWhnfs+ refs <- mapM (newThunkRef env) exprs+ case keys of+ CharKey _ : _ -> do+ let keys' = map (\case CharKey c -> c) keys+ return . ICharHash $ HL.fromList $ zip keys' refs+ StrKey _ : _ -> do+ let keys' = map (\case StrKey s -> s) keys+ return . IStrHash $ HL.fromList $ zip keys' refs+ _ -> do+ let keys' = map (\case IntKey i -> i) keys+ return . IIntHash $ HL.fromList $ zip keys' refs+ where+ makeHashKey :: WHNFData -> EvalM EgisonHashKey+ makeHashKey (Value val) =+ case val of+ ScalarData _ -> IntKey <$> fromEgison val+ Char c -> return (CharKey c)+ String str -> return (StrKey str)+ _ -> throwError =<< TypeMismatch "integer or string" (Value val) <$> getFuncNameStack+ makeHashKey whnf = throwError =<< TypeMismatch "integer or string" whnf <$> getFuncNameStack++evalExprShallow env (IIndexedExpr override expr indices) = do+ -- Tensor or hash+ tensor <- case expr of+ IVarExpr xs -> do+ let mObjRef = refVar env (Var xs (map (const () <$>) indices))+ case mObjRef of+ Just objRef -> evalRef objRef+ Nothing -> evalExprShallow env expr+ _ -> evalExprShallow env expr+ case tensor of+ Value (ScalarData (SingleTerm 1 [(Symbol id name js', 1)])) -> do+ js2 <- mapM evalIndexToScalar indices+ return $ Value (ScalarData (SingleTerm 1 [(Symbol id name (js' ++ js2), 1)]))+ Value (TensorData t@Tensor{}) -> do+ js <- mapM evalIndex indices+ Value <$> refTensorWithOverride override js t+ ITensor t@Tensor{} -> do+ js <- mapM evalIndex indices+ refTensorWithOverride override js t+ _ -> do+ js <- mapM evalIndex indices+ refHash tensor (map extractIndex js)+ where+ evalIndex :: Index IExpr -> EvalM (Index EgisonValue)+ evalIndex index = traverse (evalExprDeep env) index++ evalIndexToScalar :: Index IExpr -> EvalM (Index ScalarData)+ evalIndexToScalar index = traverse ((extractScalar =<<) . evalExprDeep env) index++evalExprShallow env (ISubrefsExpr override expr jsExpr) = do+ js <- map Sub <$> (evalExprDeep env jsExpr >>= collectionToList)+ tensor <- case expr of+ IVarExpr xs -> do+ let mObjRef = refVar env (Var xs (map (\_ -> Sub ()) js))+ case mObjRef of+ Just objRef -> evalRef objRef+ Nothing -> evalExprShallow env expr+ _ -> evalExprShallow env expr+ case tensor of+ Value (ScalarData _) -> return tensor+ Value (TensorData t@Tensor{}) -> Value <$> refTensorWithOverride override js t+ ITensor t@Tensor{} -> refTensorWithOverride override js t+ _ -> throwError =<< NotImplemented "subrefs" <$> getFuncNameStack++evalExprShallow env (ISuprefsExpr override expr jsExpr) = do+ js <- map Sup <$> (evalExprDeep env jsExpr >>= collectionToList)+ tensor <- case expr of+ IVarExpr xs -> do+ let mObjRef = refVar env (Var xs (map (\_ -> Sup ()) js))+ case mObjRef of+ Just objRef -> evalRef objRef+ Nothing -> evalExprShallow env expr+ _ -> evalExprShallow env expr+ case tensor of+ Value (ScalarData _) -> return tensor+ Value (TensorData t@Tensor{}) -> Value <$> refTensorWithOverride override js t+ ITensor t@Tensor{} -> refTensorWithOverride override js t+ _ -> throwError =<< NotImplemented "suprefs" <$> getFuncNameStack++evalExprShallow env (IUserrefsExpr _ expr jsExpr) = do+ val <- evalExprDeep env expr+ js <- map User <$> (evalExprDeep env jsExpr >>= collectionToList >>= mapM extractScalar)+ case val of+ ScalarData (SingleTerm 1 [(Symbol id name is, 1)]) ->+ return $ Value (ScalarData (SingleTerm 1 [(Symbol id name (is ++ js), 1)]))+ ScalarData (SingleTerm 1 [(FunctionData name argnames args is, 1)]) ->+ return $ Value (ScalarData (SingleTerm 1 [(FunctionData name argnames args (is ++ js), 1)]))+ _ -> throwError =<< NotImplemented "user-refs" <$> getFuncNameStack++evalExprShallow env (ILambdaExpr fnname names expr) = do+ return . Value $ Func fnname env names expr++evalExprShallow env (IMemoizedLambdaExpr names body) = do+ hashRef <- liftIO $ newIORef HL.empty+ return . Value $ MemoizedFunc hashRef env names body++evalExprShallow env (ICambdaExpr name expr) = return . Value $ CFunc env name expr++evalExprShallow env (IPatternFunctionExpr names pattern) = return . Value $ PatternFunc env names pattern++evalExprShallow (Env _ Nothing) (IFunctionExpr _) = throwError $ Default "function symbol is not bound to a variable"++evalExprShallow env@(Env _ (Just (name, is))) (IFunctionExpr args) = do+ args' <- mapM (evalExprDeep env . IVarExpr) args >>= mapM extractScalar+ return . Value $ ScalarData (SingleTerm 1 [(FunctionData (symbolScalarData' (name ++ concatMap show is)) (map symbolScalarData' args) args' [], 1)])++evalExprShallow env (IIfExpr test expr expr') = do+ test <- evalExprDeep env test >>= fromEgison+ evalExprShallow env $ if test then expr else expr'++evalExprShallow env (ILetExpr bindings expr) = do+ binding <- concat <$> mapM extractBindings bindings+ evalExprShallow (extendEnv env binding) expr+ where+ extractBindings :: IBindingExpr -> EvalM [Binding]+ extractBindings (PDPatVar var, expr) =+ makeBindings [var] . (:[]) <$> newThunkRef (memorizeVarInEnv env var) expr+ extractBindings (pdp, expr) = do+ thunk <- newThunkRef env expr+ bindPrimitiveDataPattern pdp thunk++evalExprShallow env (ILetRecExpr bindings expr) = do+ env' <- recursiveMatchBind env bindings+ evalExprShallow env' expr++evalExprShallow env (ITransposeExpr vars expr) = do+ syms <- evalExprDeep env vars >>= collectionToList+ whnf <- evalExprShallow env expr+ case whnf of+ ITensor t -> ITensor <$> tTranspose' syms t+ Value (TensorData t) -> Value . TensorData <$> tTranspose' syms t+ _ -> return whnf++evalExprShallow env (IFlipIndicesExpr expr) = do+ whnf <- evalExprShallow env expr+ case whnf of+ ITensor t -> ITensor <$> tFlipIndices t+ Value (TensorData t) -> Value . TensorData <$> tFlipIndices t+ _ -> return whnf++evalExprShallow env (IWithSymbolsExpr vars expr) = do+ symId <- fresh+ syms <- mapM (newEvaluatedObjectRef . Value . symbolScalarData symId) vars+ whnf <- evalExprShallow (extendEnv env (makeBindings' vars syms)) expr+ case whnf of+ Value (TensorData t@Tensor{}) ->+ Value . TensorData <$> removeTmpScripts symId t+ ITensor t@Tensor{} ->+ ITensor <$> removeTmpScripts symId t+ _ -> return whnf+ where+ isTmpSymbol :: String -> Index EgisonValue -> Bool+ isTmpSymbol symId index = symId == getSymId (extractIndex index)++ removeTmpScripts :: String -> Tensor a -> EvalM (Tensor a)+ removeTmpScripts symId (Tensor s xs is) = do+ let (ds, js) = partition (isTmpSymbol symId) is+ Tensor s ys _ <- tTranspose (js ++ ds) (Tensor s xs is)+ return (Tensor s ys js)+++evalExprShallow env (IDoExpr bindings expr) = return $ Value $ IOFunc $ do+ let body = foldr genLet (IApplyExpr expr [IVarExpr "#1"]) bindings+ applyObj env (Value $ Func Nothing env ["#1"] body) [WHNF (Value World)]+ where+ genLet (names, expr) expr' =+ ILetExpr [(PDTuplePat (map PDPatVar [stringToVar "#1", stringToVar "#2"]), IApplyExpr expr [IVarExpr "#1"])] $+ ILetExpr [(names, IVarExpr "#2")] expr'++evalExprShallow env (IMatchAllExpr pmmode target matcher clauses) = do+ target <- evalExprShallow env target+ matcher <- evalExprShallow env matcher >>= evalMatcherWHNF+ f matcher target >>= fromMList+ where+ fromMList :: MList EvalM WHNFData -> EvalM WHNFData+ fromMList MNil = return . Value $ Collection Sq.empty+ fromMList (MCons val m) = do+ head <- IElement <$> newEvaluatedObjectRef val+ tail <- ISubCollection <$> (liftIO . newIORef . Thunk $ m >>= fromMList)+ seqRef <- liftIO . newIORef $ Sq.fromList [head, tail]+ return $ ICollection seqRef+ f matcher target = do+ let tryMatchClause (pattern, expr) results = do+ result <- patternMatch pmmode env pattern target matcher+ mmap (flip evalExprShallow expr . extendEnv env) result >>= (`mappend` results)+ mfoldr tryMatchClause (return MNil) (fromList clauses)++evalExprShallow env (IMatchExpr pmmode target matcher clauses) = do+ target <- evalExprShallow env target+ matcher <- evalExprShallow env matcher >>= evalMatcherWHNF+ f matcher target+ where+ f matcher target = do+ let tryMatchClause (pattern, expr) cont = do+ result <- patternMatch pmmode env pattern target matcher+ case result of+ MCons bindings _ -> evalExprShallow (extendEnv env bindings) expr+ MNil -> cont+ callstack <- getFuncNameStack+ foldr tryMatchClause (throwError $ MatchFailure callstack) clauses++evalExprShallow env (ISeqExpr expr1 expr2) = do+ _ <- evalExprDeep env expr1+ evalExprShallow env expr2++evalExprShallow env (ICApplyExpr func arg) = do+ func <- evalExprShallow env func+ args <- evalExprDeep env arg >>= collectionToList+ case func of+ Value (MemoizedFunc hashRef env names body) ->+ evalMemoizedFunc hashRef env names body args+ _ -> applyObj env func (map (WHNF . Value) args)++evalExprShallow env (IApplyExpr func args) = do+ func <- appendDF 0 <$> evalExprShallow env func+ case func of+ Value (InductiveData name []) ->+ IInductiveData name <$> mapM (newThunkRef env) args+ Value (TensorData t@Tensor{}) -> do+ let args' = map (newThunk env) args+ tMap (\f -> newApplyObjThunkRef env (Value f) args') t >>= fromTensor >>= removeDF+ ITensor t@Tensor{} -> do+ let args' = map (newThunk env) args+ tMap (\f -> do+ f <- evalRef f+ newApplyObjThunkRef env f args') t >>= fromTensor >>= removeDF+ Value (MemoizedFunc hashRef env' names body) -> do+ args <- mapM (evalExprDeep env) args+ evalMemoizedFunc hashRef env' names body args+ _ -> do+ let args' = map (newThunk env) args+ applyObj env func args' >>= removeDF++evalExprShallow env (IWedgeApplyExpr func args) = do+ func <- appendDF 0 <$> evalExprShallow env func+ args <- mapM (evalExprShallow env) args+ let args' = map WHNF (zipWith appendDF [1..] args)+ case func of+ Value (TensorData t@Tensor{}) ->+ tMap (\f -> newApplyObjThunkRef env (Value f) args') t >>= fromTensor+ ITensor t@Tensor{} ->+ tMap (\f -> do+ f <- evalRef f+ newApplyObjThunkRef env f args') t >>= fromTensor+ Value (MemoizedFunc hashRef env names body) -> do+ args <- mapM evalWHNF args+ evalMemoizedFunc hashRef env names body args+ _ -> applyObj env func args' >>= removeDF++evalExprShallow env (IMatcherExpr info) = return $ Value $ UserMatcher env info++evalExprShallow env (IGenerateTensorExpr fnExpr shapeExpr) = do+ shape <- evalExprDeep env shapeExpr >>= collectionToList+ ns <- mapM fromEgison shape :: EvalM Shape+ xs <- mapM (indexToWHNF env . map toEgison) (enumTensorIndices ns)+ return $ newITensor ns xs+ where+ indexToWHNF :: Env -> [EgisonValue] {- index -} -> EvalM ObjectRef+ indexToWHNF (Env frame maybe_vwi) ms = do+ let env' = maybe env (\(name, indices) -> Env frame $ Just (name, zipWith changeIndex indices ms)) maybe_vwi+ fn <- evalExprShallow env' fnExpr+ newApplyObjThunkRef env fn (map (WHNF . Value) ms)++evalExprShallow env (ITensorContractExpr tExpr) = do+ whnf <- evalExprShallow env tExpr+ case whnf of+ ITensor t@Tensor{} -> do+ ts <- tContract t >>= mapM fromTensor+ makeICollection ts+ Value (TensorData t@Tensor{}) -> do+ ts <- tContract t >>= mapM fromTensor+ return $ Value $ Collection $ Sq.fromList ts+ _ -> makeICollection [whnf]++evalExprShallow env (ITensorMapExpr fnExpr tExpr) = do+ fn <- evalExprShallow env fnExpr+ whnf <- evalExprShallow env tExpr+ case whnf of+ ITensor t ->+ tMap (\x -> newApplyThunkRef env fn [x]) t >>= fromTensor+ Value (TensorData t) ->+ tMap (\x -> newApplyObjThunkRef env fn [WHNF (Value x)]) t >>= fromTensor+ _ -> applyObj env fn [WHNF whnf]++evalExprShallow env (ITensorMap2Expr fnExpr t1Expr t2Expr) = do+ fn <- evalExprShallow env fnExpr+ whnf1 <- evalExprShallow env t1Expr+ whnf2 <- evalExprShallow env t2Expr+ case (whnf1, whnf2) of+ -- both of arguments are tensors+ (ITensor t1, ITensor t2) ->+ tMap2 (\x y -> newApplyThunkRef env fn [x, y]) t1 t2 >>= fromTensor+ (ITensor t1, Value (TensorData t2)) -> do+ tMap2 (\x y -> do+ y <- newEvaluatedObjectRef (Value y)+ newApplyThunkRef env fn [x, y]) t1 t2 >>= fromTensor+ (Value (TensorData t1), ITensor t2) -> do+ tMap2 (\x y -> do+ x <- newEvaluatedObjectRef (Value x)+ newApplyThunkRef env fn [x, y]) t1 t2 >>= fromTensor+ (Value (TensorData t1), Value (TensorData t2)) ->+ tMap2 (\x y -> newApplyObjThunkRef env fn [WHNF (Value x), WHNF (Value y)]) t1 t2 >>= fromTensor+ -- an argument is scalar+ (ITensor t1, _) -> do+ y <- newEvaluatedObjectRef whnf2+ tMap (\x -> newApplyThunkRef env fn [x, y]) t1 >>= fromTensor+ (_, ITensor t2) -> do+ x <- newEvaluatedObjectRef whnf1+ tMap (\y -> newApplyThunkRef env fn [x, y]) t2 >>= fromTensor+ (Value (TensorData t1), _) -> do+ y <- newEvaluatedObjectRef whnf2+ tMap (\x -> do+ x <- newEvaluatedObjectRef (Value x)+ newApplyThunkRef env fn [x, y]) t1 >>= fromTensor+ (_, Value (TensorData t2)) -> do+ x <- newEvaluatedObjectRef whnf1+ tMap (\y -> do+ y <- newEvaluatedObjectRef (Value y)+ newApplyThunkRef env fn [x, y]) t2 >>= fromTensor+ _ -> applyObj env fn [WHNF whnf1, WHNF whnf2]++evalExprShallow _ expr = throwError =<< NotImplemented ("evalExprShallow for " ++ show expr) <$> getFuncNameStack++evalExprDeep :: Env -> IExpr -> EvalM EgisonValue+evalExprDeep env expr = evalExprShallow env expr >>= evalWHNF++evalRefDeep :: ObjectRef -> EvalM EgisonValue+evalRefDeep ref = do+ obj <- liftIO $ readIORef ref+ case obj of+ WHNF (Value val) -> return val+ WHNF val -> do+ val <- evalWHNF val+ writeObjectRef ref $ Value val+ return val+ Thunk thunk -> do+ val <- thunk >>= evalWHNF+ writeObjectRef ref $ Value val+ return val++evalMemoizedFunc+ :: (IORef (HL.HashMap [Integer] WHNFData)) -> Env -> [String] -> IExpr+ -> [EgisonValue] -> EvalM WHNFData+evalMemoizedFunc hashRef env names body args = do+ indices <- mapM fromEgison args+ hash <- liftIO $ readIORef hashRef+ case HL.lookup indices hash of+ Just whnf -> return whnf+ Nothing -> do+ whnf <- applyObj env (Value (Func Nothing env names body)) (map (WHNF . Value) args)+ liftIO $ modifyIORef hashRef (HL.insert indices whnf)+ return whnf++evalWHNF :: WHNFData -> EvalM EgisonValue+evalWHNF (Value val) = return val+evalWHNF (IInductiveData name refs) =+ InductiveData name <$> mapM evalRefDeep refs+evalWHNF (IIntHash refs) = IntHash <$> mapM evalRefDeep refs+evalWHNF (ICharHash refs) = CharHash <$> mapM evalRefDeep refs+evalWHNF (IStrHash refs) = StrHash <$> mapM evalRefDeep refs+evalWHNF (ITuple [ref]) = evalRefDeep ref+evalWHNF (ITuple refs) = Tuple <$> mapM evalRefDeep refs+evalWHNF (ITensor (Tensor ns whnfs js)) = do+ vals <- V.mapM evalRefDeep whnfs+ return $ TensorData $ Tensor ns vals js+evalWHNF coll = Collection <$> (collectionToRefs coll >>= fromMList >>= mapM evalRefDeep . Sq.fromList)++addscript :: (Index EgisonValue, Tensor a) -> Tensor a+addscript (subj, Tensor s t i) = Tensor s t (i ++ [subj])++newApplyThunk :: Env -> WHNFData -> [ObjectRef] -> Object+newApplyThunk env fn refs = Thunk $ applyRef env fn refs++newApplyThunkRef :: Env -> WHNFData -> [ObjectRef] -> EvalM ObjectRef+newApplyThunkRef env fn refs = liftIO . newIORef $ newApplyThunk env fn refs++newApplyObjThunk :: Env -> WHNFData -> [Object] -> Object+newApplyObjThunk env fn objs = Thunk $ applyObj env fn objs++newApplyObjThunkRef :: Env -> WHNFData -> [Object] -> EvalM ObjectRef+newApplyObjThunkRef env fn objs = liftIO . newIORef $ newApplyObjThunk env fn objs++applyRef :: Env -> WHNFData -> [ObjectRef] -> EvalM WHNFData+applyRef env (Value (TensorData (Tensor s1 t1 i1))) refs = do+ tds <- mapM evalRef refs+ if length s1 > length i1 && all (\(ITensor (Tensor s _ i)) -> length s - length i == 1) tds+ then do+ symId <- fresh+ let argnum = length tds+ subjs = map (Sub . symbolScalarData symId . show) [1 .. argnum]+ supjs = map (Sup . symbolScalarData symId . show) [1 .. argnum]+ dot <- evalExprShallow env (IVarExpr ".")+ tds' <- mapM toTensor tds+ let args' = Value (TensorData (Tensor s1 t1 (i1 ++ supjs))) : map (ITensor . addscript) (zip subjs tds')+ applyObj env dot (map WHNF args')+ else throwError $ Default "applyObj"+applyRef env (ITensor (Tensor s1 t1 i1)) refs = do+ tds <- mapM evalRef refs+ if length s1 > length i1 && all (\(ITensor (Tensor s _ i)) -> length s - length i == 1) tds+ then do+ symId <- fresh+ let argnum = length tds+ subjs = map (Sub . symbolScalarData symId . show) [1 .. argnum]+ supjs = map (Sup . symbolScalarData symId . show) [1 .. argnum]+ dot <- evalExprShallow env (IVarExpr ".")+ tds' <- mapM toTensor tds+ let args' = ITensor (Tensor s1 t1 (i1 ++ supjs)) : map (ITensor . addscript) (zip subjs tds')+ applyObj env dot (map WHNF args')+ else throwError $ Default "applyfunc"+applyRef env' (Value (Func mFuncName env names body)) refs =+ mLabelFuncName mFuncName $+ if | length names == length refs -> do+ evalExprShallow (extendEnv env (makeBindings' names refs)) body+ | length names > length refs -> do -- Currying+ let (bound, rest) = splitAt (length refs) names+ return . Value $ Func mFuncName (extendEnv env (makeBindings' bound refs)) rest body+ | otherwise -> do+ let (used, rest) = splitAt (length names) refs+ func <- evalExprShallow (extendEnv env (makeBindings' names used)) body+ applyRef env' func rest+applyRef _ (Value (CFunc env name body)) refs = do+ seqRef <- liftIO . newIORef $ Sq.fromList (map IElement refs)+ col <- liftIO . newIORef $ WHNF $ ICollection seqRef+ evalExprShallow (extendEnv env $ makeBindings' [name] [col]) body+applyRef _ (Value (PrimitiveFunc func)) refs = do+ vals <- mapM (\ref -> evalRef ref >>= evalWHNF) refs+ Value <$> func vals+applyRef _ (Value (LazyPrimitiveFunc func)) refs = do+ whnfs <- mapM evalRef refs+ func whnfs+applyRef _ (Value (IOFunc m)) refs = do+ args <- mapM evalRef refs+ case args of+ [Value World] -> m+ arg : _ -> throwError =<< TypeMismatch "world" arg <$> getFuncNameStack+applyRef _ (Value (ScalarData fn@(SingleTerm 1 [(Symbol{}, 1)]))) refs = do+ args <- mapM (\ref -> evalRef ref >>= evalWHNF) refs+ mExprs <- mapM (\arg -> case arg of+ ScalarData _ -> extractScalar arg+ _ -> throwError =<< EgisonBug "to use undefined functions, you have to use ScalarData args" <$> getFuncNameStack) args+ return (Value (ScalarData (SingleTerm 1 [(Apply fn mExprs, 1)])))+applyRef _ whnf _ = throwError =<< TypeMismatch "function" whnf <$> getFuncNameStack++applyObj :: Env -> WHNFData -> [Object] -> EvalM WHNFData+applyObj env fn args = do+ refs <- liftIO $ mapM newIORef args+ applyRef env fn refs++refHash :: WHNFData -> [EgisonValue] -> EvalM WHNFData+refHash val [] = return val+refHash val (index:indices) =+ case val of+ Value (IntHash hash) -> refHash' hash+ Value (CharHash hash) -> refHash' hash+ Value (StrHash hash) -> refHash' hash+ IIntHash hash -> irefHash hash+ ICharHash hash -> irefHash hash+ IStrHash hash -> irefHash hash+ _ -> throwError =<< TypeMismatch "hash" val <$> getFuncNameStack+ where+ refHash' hash = do+ key <- fromEgison index+ case HL.lookup key hash of+ Just val -> refHash (Value val) indices+ Nothing -> return $ Value Undefined++ irefHash hash = do+ key <- fromEgison index+ case HL.lookup key hash of+ Just ref -> evalRef ref >>= flip refHash indices+ Nothing -> return $ Value Undefined++updateHash :: [Integer] -> WHNFData -> WHNFData -> EvalM WHNFData+updateHash [index] tgt (IIntHash hash) = do+ targetRef <- newEvaluatedObjectRef tgt+ return . IIntHash $ HL.insert index targetRef hash+updateHash (index:indices) tgt (IIntHash hash) = do+ val <- maybe (return $ IIntHash HL.empty) evalRef $ HL.lookup index hash+ ref <- updateHash indices tgt val >>= newEvaluatedObjectRef+ return . IIntHash $ HL.insert index ref hash+updateHash indices tgt (Value (IntHash hash)) = do+ let keys = HL.keys hash+ vals <- mapM (newEvaluatedObjectRef . Value) $ HL.elems hash+ updateHash indices tgt (IIntHash $ HL.fromList $ zip keys vals)+updateHash _ _ v = throwError $ Default $ "expected hash value: " ++ show v++subst :: (Eq a) => a -> b -> [(a, b)] -> [(a, b)]+subst k nv ((k', v'):xs) | k == k' = (k', nv):subst k nv xs+ | otherwise = (k', v'):subst k nv xs+subst _ _ [] = []++newThunk :: Env -> IExpr -> Object+newThunk env expr = Thunk $ evalExprShallow env expr++newThunkRef :: Env -> IExpr -> EvalM ObjectRef+newThunkRef env expr = liftIO . newIORef $ newThunk env expr++recursiveBind :: Env -> [(Var, IExpr)] -> EvalM Env+recursiveBind env bindings = do+ -- Create dummy bindings first. Since this is a reference,+ -- it can be overwritten later.+ binds <- mapM (\(var, _) -> (var,) <$> newThunkRef nullEnv (IConstantExpr UndefinedExpr)) bindings+ let env' = extendEnv env binds+ forM_ bindings $ \(var, expr) -> do+ let env'' = memorizeVarInEnv env' var+ let ref = fromJust (refVar env' var)+ liftIO $ writeIORef ref (newThunk env'' expr)+ return env'++recursiveMatchBind :: Env -> [IBindingExpr] -> EvalM Env+recursiveMatchBind env bindings = do+ -- List of variables defined in |bindings|+ let names = concatMap (\(pd, _) -> toList pd) bindings+ -- Create dummy bindings for |names| first. Since this is a reference,+ -- it can be overwritten later.+ binds <- mapM (\name -> (name,) <$> newThunkRef nullEnv (IConstantExpr UndefinedExpr)) names+ let env' = extendEnv env binds+ forM_ bindings $ \(pd, expr) -> do+ -- Modify |env'| for some cases+ let env'' = case pd of+ PDPatVar var -> memorizeVarInEnv env' var+ _ -> env'+ thunk <- newThunkRef env'' expr+ binds <- bindPrimitiveDataPattern pd thunk+ forM_ binds $ \(var, objref) -> do+ -- |obj| is an Object being bound to |var|.+ obj <- liftIO $ readIORef objref+ let ref = fromJust (refVar env' var)+ liftIO $ writeIORef ref obj+ return env'++memorizeVarInEnv :: Env -> Var -> Env+memorizeVarInEnv (Env frame _) (Var var is) =+ Env frame (Just (var, map (fmap (const "")) is))++--+-- Pattern Match+--++patternMatch :: PMMode -> Env -> IPattern -> WHNFData -> Matcher -> EvalM (MList EvalM Match)+patternMatch pmmode env pattern target matcher =+ case pmmode of+ DFSMode -> processMStatesAllDFS (msingleton initMState)+ BFSMode -> processMStatesAll [msingleton initMState]+ where+ initMState = MState { mStateEnv = env+ , loopPatCtx = []+ , seqPatCtx = []+ , mStateBindings = []+ , mTrees = [MAtom pattern target matcher]+ }++processMStatesAllDFS :: MList EvalM MatchingState -> EvalM (MList EvalM Match)+processMStatesAllDFS MNil = return MNil+processMStatesAllDFS (MCons (MState _ _ [] bindings []) ms) = MCons bindings . processMStatesAllDFS <$> ms+processMStatesAllDFS (MCons mstate ms) = processMState mstate >>= (`mappend` ms) >>= processMStatesAllDFS++processMStatesAllDFSForall :: MList EvalM MatchingState -> EvalM (MList EvalM MatchingState)+processMStatesAllDFSForall MNil = return MNil+processMStatesAllDFSForall (MCons mstate@(MState _ _ (ForallPatContext _ _ : _) _ []) ms) = MCons mstate . processMStatesAllDFSForall <$> ms+processMStatesAllDFSForall (MCons mstate ms) = processMState mstate >>= (`mappend` ms) >>= processMStatesAllDFSForall++processMStatesAll :: [MList EvalM MatchingState] -> EvalM (MList EvalM Match)+processMStatesAll [] = return MNil+processMStatesAll streams = do+ (matches, streams') <- mapM processMStates streams >>= extractMatches . concat+ mappend (fromList matches) $ processMStatesAll streams'++processMStates :: MList EvalM MatchingState -> EvalM [MList EvalM MatchingState]+processMStates MNil = return []+processMStates (MCons state stream) = (\x y -> [x, y]) <$> processMState state <*> stream++extractMatches :: [MList EvalM MatchingState] -> EvalM ([Match], [MList EvalM MatchingState])+extractMatches = extractMatches' ([], [])+ where+ extractMatches' :: ([Match], [MList EvalM MatchingState]) -> [MList EvalM MatchingState] -> EvalM ([Match], [MList EvalM MatchingState])+ extractMatches' (xs, ys) [] = return (xs, ys)+ extractMatches' (xs, ys) (MCons (gatherBindings -> Just bindings) states : rest) = do+ states' <- states+ extractMatches' (xs ++ [bindings], ys ++ [states']) rest+ extractMatches' (xs, ys) (stream:rest) = extractMatches' (xs, ys ++ [stream]) rest++gatherBindings :: MatchingState -> Maybe [Binding]+gatherBindings MState{ seqPatCtx = [], mStateBindings = b, mTrees = [] } = return b+gatherBindings _ = Nothing++processMState :: MatchingState -> EvalM (MList EvalM MatchingState)+processMState state | nullMState state = processMState' state+processMState state =+ case splitMState state of+ (1, state1, state2) -> do+ result <- processMStatesAllDFS (msingleton state1)+ case result of+ MNil -> return $ msingleton state2+ _ -> return MNil+ (0, MState e l s b [MAtom (IForallPat p1 p2) m t], MState{ mTrees = trees }) -> do+ states <- processMStatesAllDFSForall (msingleton (MState e l (ForallPatContext [] []:s) b [MAtom p1 m t]))+ statess' <- mmap (\(MState e' l' (ForallPatContext ms ts:s') b' []) -> do+ let mat' = makeTuple ms+ tgt' <- makeITuple ts+ processMStatesAllDFSForall (msingleton (MState e' l' (ForallPatContext [] []:s') b' [MAtom p2 tgt' mat']))) states+ b <- mAny (\case+ MNil -> return True+ _ -> return False) statess'+ if b+ then return MNil+-- else return MNil+ else do nstatess <- mmap (\states' -> mmap (\(MState e' l' (ForallPatContext [] []:s') b' []) -> return $ MState e' l' s' b' trees) states') statess'+ mconcat nstatess+ _ -> processMState' state+ where+ splitMState :: MatchingState -> (Integer, MatchingState, MatchingState)+ splitMState mstate@MState{ mTrees = MAtom (INotPat pattern) target matcher : trees } =+ (1, mstate { seqPatCtx = [], mTrees = [MAtom pattern target matcher] }, mstate { mTrees = trees })+ splitMState mstate@MState{ mTrees = MAtom pattern target matcher : trees } =+ (0, mstate { mTrees = [MAtom pattern target matcher] }, mstate { mTrees = trees })+ splitMState mstate@MState{ mTrees = MNode penv state' : trees } =+ (f, mstate { mTrees = [MNode penv state1] }, mstate { mTrees = MNode penv state2 : trees })+ where (f, state1, state2) = splitMState state'++processMState' :: MatchingState -> EvalM (MList EvalM MatchingState)+--processMState' MState{ seqPatCtx = [], mTrees = [] } = throwError =<< EgisonBug "should not reach here (empty matching-state)" <$> getFuncNameStack+processMState' mstate@MState{ seqPatCtx = [], mTrees = [] } = return . msingleton $ mstate -- for forall pattern used in matchAll (not matchAllDFS)++-- Sequential patterns and forall pattern+processMState' mstate@MState{ seqPatCtx = SeqPatContext stack ISeqNilPat [] []:seqs, mTrees = [] } =+ return . msingleton $ mstate { seqPatCtx = seqs, mTrees = stack }+processMState' mstate@MState{ seqPatCtx = SeqPatContext stack seqPat mats tgts:seqs, mTrees = [] } = do+ let mat' = makeTuple mats+ tgt' <- makeITuple tgts+ return . msingleton $ mstate { seqPatCtx = seqs, mTrees = MAtom seqPat tgt' mat' : stack }+processMState' mstate@MState{ seqPatCtx = ForallPatContext _ _:_, mTrees = [] } =+ return . msingleton $ mstate++-- Matching Nodes+--processMState' MState{ mTrees = MNode _ MState{ mStateBindings = [], mTrees = [] }:_ } = throwError =<< EgisonBug "should not reach here (empty matching-node)" <$> getFuncNameStack+processMState' mstate@MState{ mTrees = MNode _ MState{ seqPatCtx = [], mTrees = [] }:trees } = return . msingleton $ mstate { mTrees = trees }++processMState' ms1@MState{ mTrees = MNode penv ms2@MState{ mTrees = MAtom (IVarPat name) target matcher:trees' }:trees } =+ case lookup name penv of+ Just pattern ->+ case trees' of+ [] -> return . msingleton $ ms1 { mTrees = MAtom pattern target matcher:trees }+ _ -> return . msingleton $ ms1 { mTrees = MAtom pattern target matcher:MNode penv (ms2 { mTrees = trees' }):trees }+ Nothing -> throwError =<< UnboundVariable name <$> getFuncNameStack++processMState' ms1@(MState _ _ _ bindings (MNode penv ms2@(MState env' loops' _ _ (MAtom (IIndexedPat (IVarPat name) indices) target matcher:trees')):trees)) =+ case lookup name penv of+ Just pattern -> do+ let env'' = extendEnvForNonLinearPatterns env' bindings loops'+ indices <- mapM (evalExprDeep env'' >=> fmap fromInteger . fromEgison) indices+ let pattern' = IIndexedPat pattern $ map (IConstantExpr . IntegerExpr) indices+ case trees' of+ [] -> return . msingleton $ ms1 { mTrees = MAtom pattern' target matcher:trees }+ _ -> return . msingleton $ ms1 { mTrees = MAtom pattern' target matcher:MNode penv (ms2 { mTrees = trees' }):trees }+ Nothing -> throwError =<< UnboundVariable name <$> getFuncNameStack++processMState' mstate@MState{ mTrees = MNode penv state:trees } =+ processMState' state >>= mmap (\state' -> case state' of+--egi MState { mTrees = [] } -> return $ mstate { mTrees = trees }+ _ -> return $ mstate { mTrees = MNode penv state':trees })++-- Matching Atoms+processMState' mstate@(MState env loops seqs bindings (MAtom pattern target matcher:trees)) =+ let env' = extendEnvForNonLinearPatterns env bindings loops in+ case pattern of+ IInductiveOrPApplyPat name args ->+ case refVar env (stringToVar name) of+ Nothing -> processMState' (mstate { mTrees = MAtom (IInductivePat name args) target matcher:trees })+ Just ref -> do+ whnf <- evalRef ref+ case whnf of+ Value PatternFunc{} ->+ processMState' (mstate { mTrees = MAtom (IPApplyPat (IVarExpr name) args) target matcher:trees })+ _ ->+ processMState' (mstate { mTrees = MAtom (IInductivePat name args) target matcher:trees })++ INotPat _ -> throwError =<< EgisonBug "should not reach here (not-pattern)" <$> getFuncNameStack+ IVarPat _ -> throwError $ Default $ "cannot use variable except in pattern function:" ++ show pattern++ ILetPat bindings' pattern' -> do+ b <- concat <$> mapM extractBindings bindings'+ return . msingleton $ mstate { mStateBindings = b ++ bindings, mTrees = MAtom pattern' target matcher:trees }+ where+ extractBindings (pdp, expr) = do+ thunk <- newThunkRef (extendEnv env bindings) expr+ bindPrimitiveDataPattern pdp thunk++ IPredPat predicate -> do+ func <- evalExprShallow env' predicate+ result <- applyObj env func [WHNF target] >>= evalWHNF >>= fromEgison+ if result then return . msingleton $ mstate { mTrees = trees }+ else return MNil++ IPApplyPat func args -> do+ func' <- evalExprShallow env' func+ case func' of+ Value (PatternFunc env'' names expr) ->+ return . msingleton $ mstate { mTrees = MNode penv (MState env'' [] [] [] [MAtom expr target matcher]) : trees }+ where penv = zip names args+ _ -> throwError =<< TypeMismatch "pattern constructor" func' <$> getFuncNameStack++ IDApplyPat func args ->+ return . msingleton $ mstate { mTrees = MAtom (IInductivePat "apply" [func, toListPat args]) target matcher:trees }++ ILoopPat name (ILoopRange start ends endPat) pat pat' -> do+ startNum <- evalExprDeep env' start >>= fromEgison :: (EvalM Integer)+ startNumRef <- newEvaluatedObjectRef $ Value $ toEgison (startNum - 1)+ ends' <- evalExprShallow env' ends+ case ends' of+ Value (ScalarData _) -> do -- the case when the end numbers are an integer+ endsRef <- newEvaluatedObjectRef ends'+ inners <- liftIO . newIORef $ Sq.fromList [IElement endsRef]+ endsRef' <- liftIO $ newIORef (WHNF (ICollection inners))+ return . msingleton $ mstate { loopPatCtx = LoopPatContext (name, startNumRef) endsRef' endPat pat pat':loops+ , mTrees = MAtom IContPat target matcher:trees }+ _ -> do -- the case when the end numbers are a collection+ endsRef <- newEvaluatedObjectRef ends'+ return . msingleton $ mstate { loopPatCtx = LoopPatContext (name, startNumRef) endsRef endPat pat pat':loops+ , mTrees = MAtom IContPat target matcher:trees }+ IContPat ->+ case loops of+ [] -> throwError $ Default "cannot use cont pattern except in loop pattern"+ LoopPatContext (name, startNumRef) endsRef endPat pat pat' : loops' -> do+ startNumVal <- evalRefDeep startNumRef+ startNum <- fromEgison startNumVal :: (EvalM Integer)+ nextNumRef <- newEvaluatedObjectRef $ Value $ toEgison (startNum + 1)+ ends <- evalRef endsRef+ b <- isEmptyCollection ends+ if b+ then return MNil+ else do+ (carEndsRef, cdrEndsRef) <- fromJust <$> runMaybeT (unconsCollection ends)+ b2 <- evalRef cdrEndsRef >>= isEmptyCollection+ carEndsNum <- evalRefDeep carEndsRef >>= fromEgison+ return $ if+ | startNum > carEndsNum -> MNil+ | startNum == carEndsNum && b2 ->+ fromList [mstate { loopPatCtx = loops', mTrees = MAtom endPat (Value startNumVal) Something:MAtom pat' target matcher:trees }]+ | startNum == carEndsNum ->+ fromList [mstate { loopPatCtx = loops', mTrees = MAtom endPat (Value startNumVal) Something:MAtom pat' target matcher:trees },+ mstate { loopPatCtx = LoopPatContext (name, nextNumRef) cdrEndsRef endPat pat pat':loops', mTrees = MAtom pat target matcher:trees }]+ | otherwise ->+ fromList [mstate { loopPatCtx = LoopPatContext (name, nextNumRef) endsRef endPat pat pat':loops', mTrees = MAtom pat target matcher:trees }]+ ISeqNilPat -> throwError =<< EgisonBug "should not reach here (seq nil pattern)" <$> getFuncNameStack+ ISeqConsPat pattern pattern' -> return . msingleton $ MState env loops (SeqPatContext trees pattern' [] []:seqs) bindings [MAtom pattern target matcher]+ ILaterPatVar ->+ case seqs of+ [] -> throwError $ Default "cannot use # out of seq patterns"+ SeqPatContext stack pat mats tgts:seqs ->+ return . msingleton $ MState env loops (SeqPatContext stack pat (mats ++ [matcher]) (tgts ++ [target]):seqs) bindings trees+ ForallPatContext mats tgts:seqs ->+ return . msingleton $ MState env loops (ForallPatContext (mats ++ [matcher]) (tgts ++ [target]):seqs) bindings trees+ IAndPat pat1 pat2 ->+ let trees' = [MAtom pat1 target matcher, MAtom pat2 target matcher] ++ trees+ in return . msingleton $ mstate { mTrees = trees' }+ IOrPat pat1 pat2 ->+ return $ fromList [mstate { mTrees = MAtom pat1 target matcher : trees }, mstate { mTrees = MAtom pat2 target matcher : trees }]++ _ ->+ case matcher of+ UserMatcher{} -> do+ (patterns, targetss, matchers) <- inductiveMatch env' pattern target matcher+ case length patterns of+ 1 ->+ mfor targetss $ \ref -> do+ targets <- evalRef ref >>= (\x -> return [x])+ let trees' = zipWith3 MAtom patterns targets matchers ++ trees+ return $ mstate { mTrees = trees' }+ _ ->+ mfor targetss $ \ref -> do+ targets <- evalRef ref >>= tupleToListWHNF+ let trees' = zipWith3 MAtom patterns targets matchers ++ trees+ return $ mstate { mTrees = trees' }++ Tuple matchers ->+ case pattern of+ IValuePat _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }+ IWildCard -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }+ IPatVar _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }+ IIndexedPat _ _ -> return . msingleton $ mstate { mTrees = MAtom pattern target Something:trees }+ ITuplePat patterns -> do+ targets <- tupleToListWHNF target+ when (length patterns /= length targets) $ throwError =<< TupleLength (length patterns) (length targets) <$> getFuncNameStack+ when (length patterns /= length matchers) $ throwError =<< TupleLength (length patterns) (length matchers) <$> getFuncNameStack+ let trees' = zipWith3 MAtom patterns targets matchers ++ trees+ return . msingleton $ mstate { mTrees = trees' }+ _ -> throwError $ Default $ "should not reach here. matcher: " ++ show matcher ++ ", pattern: " ++ show pattern++ Something ->+ case pattern of+ IValuePat valExpr -> do+ val <- evalExprDeep env' valExpr+ tgtVal <- evalWHNF target+ if val == tgtVal+ then return . msingleton $ mstate { mTrees = trees }+ else return MNil+ IWildCard -> return . msingleton $ mstate { mTrees = trees }+ IPatVar name -> do+ targetRef <- newEvaluatedObjectRef target+ return . msingleton $ mstate { mStateBindings = (stringToVar name, targetRef):bindings, mTrees = trees }+ IIndexedPat (IPatVar name') indices -> do+ let name = stringToVar name'+ indices <- mapM (evalExprDeep env' >=> fmap fromInteger . fromEgison) indices+ case lookup name bindings of+ Just ref -> do+ obj <- evalRef ref >>= updateHash indices target >>= newEvaluatedObjectRef+ return . msingleton $ mstate { mStateBindings = subst name obj bindings, mTrees = trees }+ Nothing -> do+ obj <- updateHash indices target (IIntHash (HL.empty)) >>= newEvaluatedObjectRef+ return . msingleton $ mstate { mStateBindings = (name,obj):bindings, mTrees = trees }+ IIndexedPat pattern _ -> throwError $ Default ("invalid indexed-pattern: " ++ show pattern)+ ITuplePat patterns -> do+ targets <- tupleToListWHNF target+ when (length patterns /= length targets) $ throwError =<< TupleLength (length patterns) (length targets) <$> getFuncNameStack+ let trees' = zipWith3 MAtom patterns targets (map (const Something) patterns) ++ trees+ return . msingleton $ mstate { mTrees = trees' }+ _ -> throwError $ Default $ "something can only match with a pattern variable. not: " ++ show pattern+ _ -> throwError =<< EgisonBug ("should not reach here. matcher: " ++ show matcher ++ ", pattern: " ++ show pattern) <$> getFuncNameStack++inductiveMatch :: Env -> IPattern -> WHNFData -> Matcher ->+ EvalM ([IPattern], MList EvalM ObjectRef, [Matcher])+inductiveMatch env pattern target (UserMatcher matcherEnv clauses) =+ foldr tryPPMatchClause failPPPatternMatch clauses+ where+ tryPPMatchClause (pat, matchers, clauses) cont = do+ result <- runMaybeT $ primitivePatPatternMatch env pat pattern+ case result of+ Just ([pattern], bindings) -> do+ targetss <- foldr (tryPDMatchClause bindings) failPDPatternMatch clauses+ matcher <- evalExprShallow matcherEnv matchers >>= evalMatcherWHNF+ return ([pattern], targetss, [matcher])+ Just (patterns, bindings) -> do+ targetss <- foldr (tryPDMatchClause bindings) failPDPatternMatch clauses+ matchers <- tupleToList <$> (evalExprShallow matcherEnv matchers >>= evalMatcherWHNF)+ return (patterns, targetss, matchers)+ _ -> cont+ tryPDMatchClause bindings (pat, expr) cont = do+ ref <- newEvaluatedObjectRef target+ result <- runMaybeT $ primitiveDataPatternMatch pat ref+ case result of+ Just bindings' -> do+ let env = extendEnv matcherEnv $ bindings ++ bindings'+ evalExprShallow env expr >>= collectionToRefs+ _ -> cont+ failPPPatternMatch = throwError (Default "failed primitive pattern pattern match")+ failPDPatternMatch = throwError =<< PrimitiveMatchFailure <$> getFuncNameStack++primitivePatPatternMatch :: Env -> PrimitivePatPattern -> IPattern ->+ MatchM ([IPattern], [Binding])+primitivePatPatternMatch _ PPWildCard IWildCard = return ([], [])+primitivePatPatternMatch _ PPPatVar pattern = return ([pattern], [])+primitivePatPatternMatch env (PPValuePat name) (IValuePat expr) = do+ ref <- lift $ newThunkRef env expr+ return ([], [(stringToVar name, ref)])+primitivePatPatternMatch env (PPInductivePat name patterns) (IInductivePat name' exprs)+ | name == name' && length patterns == length exprs =+ (concat *** concat) . unzip <$> zipWithM (primitivePatPatternMatch env) patterns exprs+ | otherwise = matchFail+primitivePatPatternMatch env (PPTuplePat patterns) (ITuplePat exprs)+ | length patterns == length exprs =+ (concat *** concat) . unzip <$> zipWithM (primitivePatPatternMatch env) patterns exprs+ | otherwise = matchFail+primitivePatPatternMatch _ _ _ = matchFail++bindPrimitiveDataPattern :: IPrimitiveDataPattern -> ObjectRef -> EvalM [Binding]+bindPrimitiveDataPattern pdp ref = do+ r <- runMaybeT $ primitiveDataPatternMatch pdp ref+ case r of+ Nothing -> throwError =<< PrimitiveMatchFailure <$> getFuncNameStack+ Just binding -> return binding++primitiveDataPatternMatch :: IPrimitiveDataPattern -> ObjectRef -> MatchM [Binding]+primitiveDataPatternMatch PDWildCard _ = return []+primitiveDataPatternMatch (PDPatVar name) ref = return [(name, ref)]+primitiveDataPatternMatch (PDInductivePat name patterns) ref = do+ whnf <- lift $ evalRef ref+ case whnf of+ IInductiveData name' refs | name == name' ->+ concat <$> zipWithM primitiveDataPatternMatch patterns refs+ Value (InductiveData name' vals) | name == name' -> do+ whnfs <- lift $ mapM (newEvaluatedObjectRef . Value) vals+ concat <$> zipWithM primitiveDataPatternMatch patterns whnfs+ _ -> matchFail+primitiveDataPatternMatch (PDTuplePat patterns) ref = do+ whnf <- lift $ evalRef ref+ case whnf of+ ITuple refs -> do+ concat <$> zipWithM primitiveDataPatternMatch patterns refs+ Value (Tuple vals) -> do+ whnfs <- lift $ mapM (newEvaluatedObjectRef . Value) vals+ concat <$> zipWithM primitiveDataPatternMatch patterns whnfs+ _ -> matchFail+primitiveDataPatternMatch PDEmptyPat ref = do+ whnf <- lift $ evalRef ref+ isEmpty <- lift $ isEmptyCollection whnf+ if isEmpty then return [] else matchFail+primitiveDataPatternMatch (PDConsPat pattern pattern') ref = do+ whnf <- lift $ evalRef ref+ (head, tail) <- unconsCollection whnf+ (++) <$> primitiveDataPatternMatch pattern head+ <*> primitiveDataPatternMatch pattern' tail+primitiveDataPatternMatch (PDSnocPat pattern pattern') ref = do+ whnf <- lift $ evalRef ref+ (init, last) <- unsnocCollection whnf+ (++) <$> primitiveDataPatternMatch pattern init+ <*> primitiveDataPatternMatch pattern' last+primitiveDataPatternMatch (PDConstantPat expr) ref = do+ whnf <- lift $ evalRef ref+ case whnf of+ Value val | val == evalConstant expr -> return []+ _ -> matchFail++extendEnvForNonLinearPatterns :: Env -> [Binding] -> [LoopPatContext] -> Env+extendEnvForNonLinearPatterns env bindings loops = extendEnv env $ bindings ++ map (\(LoopPatContext (name, ref) _ _ _ _) -> (stringToVar name, ref)) loops++evalMatcherWHNF :: WHNFData -> EvalM Matcher+evalMatcherWHNF (Value matcher@Something) = return matcher+evalMatcherWHNF (Value matcher@UserMatcher{}) = return matcher+evalMatcherWHNF (Value (Tuple ms)) = Tuple <$> mapM (evalMatcherWHNF . Value) ms+evalMatcherWHNF (ITuple refs) = do+ whnfs <- mapM evalRef refs+ ms <- mapM evalMatcherWHNF whnfs+ return $ Tuple ms+evalMatcherWHNF whnf = throwError =<< TypeMismatch "matcher" whnf <$> getFuncNameStack++--+-- Util+--+toListPat :: [IPattern] -> IPattern+toListPat [] = IInductivePat "nil" []+toListPat (pat:pats) = IInductivePat "::" [pat, toListPat pats]++makeITensorFromWHNF :: Shape -> [WHNFData] -> EvalM WHNFData+makeITensorFromWHNF s xs = do+ xs' <- mapM newEvaluatedObjectRef xs+ return $ ITensor (Tensor s (V.fromList xs') [])++newITensor :: Shape -> [ObjectRef] -> WHNFData+newITensor s refs = ITensor (Tensor s (V.fromList refs) [])++-- Refer the specified tensor index with potential overriding of the index.+refTensorWithOverride :: TensorComponent a b => Bool -> [Index EgisonValue] -> Tensor b -> EvalM a+refTensorWithOverride override js (Tensor ns xs is) =+ tref js' (Tensor ns xs js') >>= tContract' >>= fromTensor where js' = if override then js else is ++ js
hs-src/Language/Egison/Data.hs view
@@ -1,12 +1,7 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE QuasiQuotes #-} {- | Module : Language.Egison.Data@@ -21,11 +16,11 @@ EgisonValue (..) , Matcher , PrimitiveFunc+ , LazyPrimitiveFunc , EgisonHashKey (..) , EgisonData (..) , Tensor (..) , Shape- , HasTensor (..) -- * Scalar , symbolScalarData , symbolScalarData'@@ -34,45 +29,29 @@ , mathExprToEgison , egisonToScalarData , extractScalar- , extractScalar'- -- * Tensor- , tensorToWHNF- , tensorToValue -- * Internal data , Object (..) , ObjectRef , WHNFData (..)- , Intermediate (..) , Inner (..)- , EgisonWHNF (..) -- * Environment , Env (..) , Binding , nullEnv , extendEnv , refVar- -- * Pattern matching- , Match- , MatchingTree (..)- , MatchingState (..)- , PatternBinding- , LoopPatContext (..)- , SeqPatContext (..) -- * Errors , EgisonError (..) -- * Monads- , EvalM (..)+ , EvalM , fromEvalM- , MatchM- , matchFail+ , fromEvalT ) where import Control.Exception-import Data.Typeable import Control.Monad.Except hiding (join)-import Control.Monad.Trans.Maybe-import Control.Monad.Trans.State+import Control.Monad.Trans.State.Strict import Data.Foldable (toList) import Data.HashMap.Strict (HashMap)@@ -84,23 +63,23 @@ import Data.List (intercalate) import Data.Text (Text)+import Text.Show.Unicode (ushow) import Data.Ratio import System.IO -import Control.Egison hiding (Integer, MList, MNil, MCons, Matcher, Something, mappend)-import qualified Control.Egison as M--import Language.Egison.AST hiding (PatVar)-import Language.Egison.IState-import Language.Egison.MathExpr+import Language.Egison.CmdOptions+import Language.Egison.EvalState+import Language.Egison.IExpr+import Language.Egison.Math+import Language.Egison.RState -- -- Values -- -data EgisonValue =- World+data EgisonValue+ = World | Char Char | String Text | Bool Bool@@ -113,13 +92,13 @@ | IntHash (HashMap Integer EgisonValue) | CharHash (HashMap Char EgisonValue) | StrHash (HashMap Text EgisonValue)- | UserMatcher Env [PatternDef]- | Func (Maybe Var) Env [String] EgisonExpr- | AnonParamFunc Env Integer EgisonExpr- | CFunc (Maybe Var) Env String EgisonExpr- | MemoizedFunc (Maybe Var) ObjectRef (IORef (HashMap [Integer] ObjectRef)) Env [String] EgisonExpr- | PatternFunc Env [String] EgisonPattern- | PrimitiveFunc String PrimitiveFunc+ | UserMatcher Env [IPatternDef]+ | Func (Maybe String) Env [String] IExpr+ | CFunc Env String IExpr+ | MemoizedFunc (IORef (HashMap [Integer] WHNFData)) Env [String] IExpr+ | PatternFunc Env [String] IPattern+ | PrimitiveFunc PrimitiveFunc+ | LazyPrimitiveFunc LazyPrimitiveFunc | IOFunc (EvalM WHNFData) | Port Handle | RefBox (IORef EgisonValue)@@ -128,10 +107,11 @@ type Matcher = EgisonValue -type PrimitiveFunc = WHNFData -> EvalM WHNFData+type PrimitiveFunc = [EgisonValue] -> EvalM EgisonValue+type LazyPrimitiveFunc = [WHNFData] -> EvalM WHNFData -data EgisonHashKey =- IntKey Integer+data EgisonHashKey+ = IntKey Integer | CharKey Char | StrKey Text @@ -139,41 +119,13 @@ -- Scalar and Tensor Types -- -data Tensor a =- Tensor Shape (V.Vector a) [Index EgisonValue]+data Tensor a+ = Tensor Shape (V.Vector a) [Index EgisonValue] | Scalar a- deriving (Show)+ deriving Show type Shape = [Integer] -class HasTensor a where- tensorElems :: a -> V.Vector a- tensorShape :: a -> Shape- tensorIndices :: a -> [Index EgisonValue]- fromTensor :: Tensor a -> EvalM a- toTensor :: a -> EvalM (Tensor a)- undef :: a--instance HasTensor EgisonValue where- tensorElems (TensorData (Tensor _ xs _)) = xs- tensorShape (TensorData (Tensor ns _ _)) = ns- tensorIndices (TensorData (Tensor _ _ js)) = js- fromTensor t@Tensor{} = return $ TensorData t- fromTensor (Scalar x) = return x- toTensor (TensorData t) = return t- toTensor x = return $ Scalar x- undef = Undefined--instance HasTensor WHNFData where- tensorElems (Intermediate (ITensor (Tensor _ xs _))) = xs- tensorShape (Intermediate (ITensor (Tensor ns _ _))) = ns- tensorIndices (Intermediate (ITensor (Tensor _ _ js))) = js- fromTensor t@Tensor{} = return $ Intermediate $ ITensor t- fromTensor (Scalar x) = return x- toTensor (Intermediate (ITensor t)) = return t- toTensor x = return $ Scalar x- undef = Value Undefined- -- -- Scalars --@@ -181,11 +133,11 @@ symbolScalarData :: String -> String -> EgisonValue symbolScalarData id name = ScalarData (SingleTerm 1 [(Symbol id name [], 1)]) -symbolScalarData' :: String -> String -> ScalarData-symbolScalarData' id name = SingleTerm 1 [(Symbol id name [], 1)]+symbolScalarData' :: String -> ScalarData+symbolScalarData' name = SingleTerm 1 [(Symbol "" name [], 1)] getSymId :: EgisonValue -> String-getSymId (ScalarData (SingleTerm 1 [(Symbol id _ [], 1)])) = id+getSymId (ScalarData (SingleTerm 1 [(Symbol id _ _, _)])) = id getSymName :: EgisonValue -> String getSymName (ScalarData (SingleTerm 1 [(Symbol _ name [], 1)])) = name@@ -211,10 +163,11 @@ f js = Collection (Sq.fromList (map scalarIndexToEgison js)) scalarIndexToEgison :: Index ScalarData -> EgisonValue-scalarIndexToEgison (Superscript k) = InductiveData "Sup" [ScalarData k]-scalarIndexToEgison (Subscript k) = InductiveData "Sub" [ScalarData k]-scalarIndexToEgison (Userscript k) = InductiveData "User" [ScalarData k]+scalarIndexToEgison (Sup k) = InductiveData "Sup" [ScalarData k]+scalarIndexToEgison (Sub k) = InductiveData "Sub" [ScalarData k]+scalarIndexToEgison (User k) = InductiveData "User" [ScalarData k] +-- Implementation of 'toMathExpr' (Primitive function) egisonToScalarData :: EgisonValue -> EvalM ScalarData egisonToScalarData (InductiveData "Div" [p1, p2]) = Div <$> egisonToPolyExpr p1 <*> egisonToPolyExpr p2 egisonToScalarData p1@(InductiveData "Plus" _) = Div <$> egisonToPolyExpr p1 <*> return (Plus [Term 1 []])@@ -272,9 +225,9 @@ egisonToScalarIndex :: EgisonValue -> EvalM (Index ScalarData) egisonToScalarIndex j = case j of- InductiveData "Sup" [ScalarData k] -> return (Superscript k)- InductiveData "Sub" [ScalarData k] -> return (Subscript k)- InductiveData "User" [ScalarData k] -> return (Userscript k)+ InductiveData "Sup" [ScalarData k] -> return (Sup k)+ InductiveData "Sub" [ScalarData k] -> return (Sub k)+ InductiveData "User" [ScalarData k] -> return (User k) _ -> throwError =<< TypeMismatch "math symbol expression" (Value j) <$> getFuncNameStack --@@ -285,27 +238,11 @@ extractScalar (ScalarData mExpr) = return mExpr extractScalar val = throwError =<< TypeMismatch "math expression" (Value val) <$> getFuncNameStack -extractScalar' :: WHNFData -> EvalM ScalarData-extractScalar' (Value (ScalarData x)) = return x-extractScalar' val = throwError =<< TypeMismatch "integer or string" val <$> getFuncNameStack------- Tensor-----tensorToWHNF :: Tensor WHNFData -> WHNFData-tensorToWHNF (Scalar whnf) = whnf-tensorToWHNF t@(Tensor _ _ _) = Intermediate (ITensor t)--tensorToValue :: Tensor EgisonValue -> EgisonValue-tensorToValue (Scalar val) = val-tensorToValue t@(Tensor _ _ _) = TensorData t- -- New-syntax version of EgisonValue pretty printer. -- TODO(momohatt): Don't make it a show instance of EgisonValue. instance Show EgisonValue where show (Char c) = '\'' : c : "'"- show (String str) = show str+ show (String str) = ushow str show (Bool True) = "True" show (Bool False) = "False" show (ScalarData mExpr) = show mExpr@@ -314,7 +251,7 @@ show (TensorData (Tensor [_, j] xs js)) = "[| " ++ intercalate ", " (f (fromIntegral j) (V.toList xs)) ++ " |]" ++ concatMap show js where f _ [] = []- f j xs = ["[| " ++ intercalate ", " (map show (take j xs)) ++ " |]"] ++ f j (drop j xs)+ f j xs = ("[| " ++ intercalate ", " (map show (take j xs)) ++ " |]") : f j (drop j xs) show (TensorData (Tensor ns xs js)) = "(tensor [" ++ intercalate ", " (map show ns) ++ "] [" ++ intercalate ", " (map show (V.toList xs)) ++ "] )" ++ concatMap show js show (Float x) = show x show (InductiveData name vals) = name ++ concatMap ((' ':) . show') vals@@ -327,17 +264,15 @@ show (CharHash hash) = "{|" ++ intercalate ", " (map (\(key, val) -> "[" ++ show key ++ ", " ++ show val ++ "]") $ HashMap.toList hash) ++ "|}" show (StrHash hash) = "{|" ++ intercalate ", " (map (\(key, val) -> "[" ++ show key ++ ", " ++ show val ++ "]") $ HashMap.toList hash) ++ "|}" show UserMatcher{} = "#<user-matcher>"- show (Func Nothing _ args _) = "(lambda [" ++ intercalate ", " (map show args) ++ "] ...)"- show (Func (Just name) _ _ _) = show name- show (AnonParamFunc _ n expr) = show n ++ "#" ++ show expr- show (CFunc Nothing _ name _) = "(cambda " ++ name ++ " ...)"- show (CFunc (Just name) _ _ _) = show name- show (MemoizedFunc Nothing _ _ _ names _) = "(memoized-lambda [" ++ intercalate ", " names ++ "] ...)"- show (MemoizedFunc (Just name) _ _ _ _ _) = show name+ show (Func _ _ args _) = "#<lambda [" ++ intercalate ", " (map show args) ++ "] ...>"+ show (CFunc _ name _) = "#<cambda " ++ name ++ " ...>"+ show (MemoizedFunc _ _ names _) = "#<memoized-lambda [" ++ intercalate ", " names ++ "] ...>" show PatternFunc{} = "#<pattern-function>"- show (PrimitiveFunc name _) = "#<primitive-function " ++ name ++ ">"- show (IOFunc _) = "#<io-function>"- show (Port _) = "#<port>"+ show PrimitiveFunc{} = "#<primitive-function>"+ show LazyPrimitiveFunc{} = "#<primitive-function>"+ show IOFunc{} = "#<io-function>"+ show Port{} = "#<port>"+ show RefBox{} = "#<refbox>" show Something = "something" show Undefined = "undefined" show World = "#<world>"@@ -350,25 +285,21 @@ isAtomic _ = True instance Eq EgisonValue where- (Char c) == (Char c') = c == c'- (String str) == (String str') = str == str'- (Bool b) == (Bool b') = b == b'- (ScalarData x) == (ScalarData y) = x == y- (TensorData (Tensor js xs _)) == (TensorData (Tensor js' xs' _)) = (js == js') && (xs == xs')- (Float x) == (Float x') = x == x'- (InductiveData name vals) == (InductiveData name' vals') = (name == name') && (vals == vals')- (Tuple vals) == (Tuple vals') = vals == vals'- (Collection vals) == (Collection vals') = vals == vals'- (IntHash vals) == (IntHash vals') = vals == vals'- (CharHash vals) == (CharHash vals') = vals == vals'- (StrHash vals) == (StrHash vals') = vals == vals'- (PrimitiveFunc name1 _) == (PrimitiveFunc name2 _) = name1 == name2- -- Temporary: searching a better solution- (Func Nothing _ xs1 expr1) == (Func Nothing _ xs2 expr2) = (xs1 == xs2) && (expr1 == expr2)- (Func (Just name1) _ _ _) == (Func (Just name2) _ _ _) = name1 == name2- (CFunc Nothing _ x1 expr1) == (CFunc Nothing _ x2 expr2) = (x1 == x2) && (expr1 == expr2)- (CFunc (Just name1) _ _ _) == (CFunc (Just name2) _ _ _) = name1 == name2- _ == _ = False+ (Char c) == (Char c') = c == c'+ (String str) == (String str') = str == str'+ (Bool b) == (Bool b') = b == b'+ (ScalarData x) == (ScalarData y) = x == y+ (TensorData (Tensor js xs _)) == (TensorData (Tensor js' xs' _)) = js == js' && xs == xs'+ (Float x) == (Float x') = x == x'+ (InductiveData name vals) == (InductiveData name' vals') = name == name' && vals == vals'+ (Tuple vals) == (Tuple vals') = vals == vals'+ (Collection vals) == (Collection vals') = vals == vals'+ (IntHash vals) == (IntHash vals') = vals == vals'+ (CharHash vals) == (CharHash vals') = vals == vals'+ (StrHash vals) == (StrHash vals') = vals == vals'+ -- Temporary: searching a better solution+ (Func (Just name1) _ _ _) == (Func (Just name2) _ _ _) = name1 == name2+ _ == _ = False -- -- Egison data and Haskell data@@ -393,8 +324,8 @@ fromEgison val = throwError =<< TypeMismatch "bool" (Value val) <$> getFuncNameStack instance EgisonData Integer where- toEgison 0 = ScalarData $ mathNormalize' (Div (Plus []) (Plus [Term 1 []]))- toEgison i = ScalarData $ mathNormalize' (SingleTerm i [])+ toEgison 0 = ScalarData (Div (Plus []) (Plus [Term 1 []]))+ toEgison i = ScalarData (SingleTerm i []) fromEgison (ScalarData (Div (Plus []) (Plus [Term 1 []]))) = return 0 fromEgison (ScalarData (SingleTerm x [])) = return x fromEgison val = throwError =<< TypeMismatch "integer" (Value val) <$> getFuncNameStack@@ -461,37 +392,34 @@ -- |For memoization type ObjectRef = IORef Object -data Object =- Thunk (EvalM WHNFData)+data Object+ = Thunk (EvalM WHNFData) | WHNF WHNFData -data WHNFData =- Intermediate Intermediate- | Value EgisonValue--data Intermediate =- IInductiveData String [ObjectRef]+data WHNFData+ = Value EgisonValue+ | IInductiveData String [ObjectRef] | ITuple [ObjectRef] | ICollection (IORef (Seq Inner)) | IIntHash (HashMap Integer ObjectRef) | ICharHash (HashMap Char ObjectRef) | IStrHash (HashMap Text ObjectRef)- | ITensor (Tensor WHNFData)+ | ITensor (Tensor ObjectRef) -data Inner =- IElement ObjectRef+data Inner+ = IElement ObjectRef | ISubCollection ObjectRef instance Show WHNFData where show (Value val) = show val- show (Intermediate (IInductiveData name _)) = "<" ++ name ++ " ...>"- show (Intermediate (ITuple _)) = "[...]"- show (Intermediate (ICollection _)) = "{...}"- show (Intermediate (IIntHash _)) = "{|...|}"- show (Intermediate (ICharHash _)) = "{|...|}"- show (Intermediate (IStrHash _)) = "{|...|}"- show (Intermediate (ITensor (Tensor ns xs _))) = "[|" ++ show (length ns) ++ show (V.length xs) ++ "|]"- show (Intermediate (ITensor (Scalar _))) = "scalar"+ show (IInductiveData name _) = "<" ++ name ++ " ...>"+ show (ITuple _) = "(...)"+ show (ICollection _) = "[...]"+ show (IIntHash _) = "{|...|}"+ show (ICharHash _) = "{|...|}"+ show (IStrHash _) = "{|...|}"+ show (ITensor (Tensor ns xs _)) = "[|" ++ show (length ns) ++ show (V.length xs) ++ "|]"+ show (ITensor (Scalar _)) = "scalar" instance Show Object where show (Thunk _) = "#<thunk>"@@ -501,105 +429,38 @@ show _ = "#<ref>" ----- Extract data from WHNF----class EgisonData a => EgisonWHNF a where- toWHNF :: a -> WHNFData- fromWHNF :: WHNFData -> EvalM a- toWHNF = Value . toEgison--instance EgisonWHNF Char where- fromWHNF (Value (Char c)) = return c- fromWHNF whnf = throwError =<< TypeMismatch "char" whnf <$> getFuncNameStack--instance EgisonWHNF Text where- fromWHNF (Value (String str)) = return str- fromWHNF whnf = throwError =<< TypeMismatch "string" whnf <$> getFuncNameStack--instance EgisonWHNF Bool where- fromWHNF (Value (Bool b)) = return b- fromWHNF whnf = throwError =<< TypeMismatch "bool" whnf <$> getFuncNameStack--instance EgisonWHNF Integer where- fromWHNF (Value (ScalarData (Div (Plus []) (Plus [Term 1 []])))) = return 0- fromWHNF (Value (ScalarData (SingleTerm x []))) = return x- fromWHNF whnf = throwError =<< TypeMismatch "integer" whnf <$> getFuncNameStack--instance EgisonWHNF Double where- fromWHNF (Value (Float f)) = return f- fromWHNF whnf = throwError =<< TypeMismatch "float" whnf <$> getFuncNameStack--instance EgisonWHNF Handle where- fromWHNF (Value (Port h)) = return h- fromWHNF whnf = throwError =<< TypeMismatch "port" whnf <$> getFuncNameStack---- -- Environment -- -data Env = Env [HashMap Var ObjectRef] (Maybe VarWithIndices)- deriving (Show)+data Env = Env [HashMap Var ObjectRef] (Maybe (String, [Index String])) type Binding = (Var, ObjectRef) -instance Show (Index EgisonValue) where- show (Superscript i) = case i of+instance {-# OVERLAPPING #-} Show (Index EgisonValue) where+ show (Sup i) = case i of ScalarData (SingleTerm 1 [(Symbol _ _ (_:_), 1)]) -> "~[" ++ show i ++ "]" _ -> "~" ++ show i- show (Subscript i) = case i of+ show (Sub i) = case i of ScalarData (SingleTerm 1 [(Symbol _ _ (_:_), 1)]) -> "_[" ++ show i ++ "]" _ -> "_" ++ show i- show (SupSubscript i) = "~_" ++ show i- show (DFscript i j) = "_d" ++ show i ++ show j- show (Userscript i) = case i of+ show (SupSub i) = "~_" ++ show i+ show (User i) = case i of ScalarData (SingleTerm 1 [(Symbol _ _ (_:_), 1)]) -> "_[" ++ show i ++ "]" _ -> "|" ++ show i+ show (DF i j) = "_d" ++ show i ++ show j nullEnv :: Env nullEnv = Env [] Nothing extendEnv :: Env -> [Binding] -> Env-extendEnv (Env env idx) bdg = Env ((: env) $ HashMap.fromList bdg) idx+extendEnv (Env env idx) bdg = Env (HashMap.fromList bdg : env) idx refVar :: Env -> Var -> Maybe ObjectRef refVar (Env env _) var@(Var _ []) = msum $ map (HashMap.lookup var) env refVar e@(Env env _) var@(Var name is) = case msum $ map (HashMap.lookup var) env of- Nothing -> match is (List M.Something)- [[mc| $his ++ _ : [] -> refVar e (Var name his) |]]- Just x -> Just x------- Pattern Match-----type Match = [Binding]--data MatchingState- = MState { mStateEnv :: Env- , loopPatCtx :: [LoopPatContext]- , seqPatCtx :: [SeqPatContext]- , mStateBindings :: [Binding]- , mTrees :: [MatchingTree]- }--instance Show MatchingState where- show ms = "(MState " ++ unwords ["_", "_", "_", show (mStateBindings ms), show (mTrees ms)] ++ ")"--data MatchingTree =- MAtom EgisonPattern WHNFData Matcher- | MNode [PatternBinding] MatchingState- deriving (Show)--type PatternBinding = (String, EgisonPattern)--data LoopPatContext = LoopPatContext Binding ObjectRef EgisonPattern EgisonPattern EgisonPattern- deriving (Show)--data SeqPatContext =- SeqPatContext [MatchingTree] EgisonPattern [Matcher] [WHNFData]- | ForallPatContext [Matcher] [WHNFData]- deriving (Show)+ Nothing -> refVar e (Var name (init is))+ Just x -> Just x -- -- Errors@@ -607,11 +468,10 @@ type CallStack = [String] -data EgisonError =- UnboundVariable String CallStack+data EgisonError+ = UnboundVariable String CallStack | TypeMismatch String WHNFData CallStack- | ArgumentsNumWithNames [String] Int Int CallStack- | ArgumentsNumPrimitive Int Int CallStack+ | ArgumentsNumPrimitive String Int Int CallStack | TupleLength Int Int CallStack | InconsistentTensorShape CallStack | InconsistentTensorIndex CallStack@@ -620,20 +480,17 @@ | Assertion String CallStack | Parser String | EgisonBug String CallStack- | MatchFailure String CallStack- | UnknownFileExtension String+ | MatchFailure CallStack+ | PrimitiveMatchFailure CallStack | Default String- deriving Typeable instance Show EgisonError where show (UnboundVariable var stack) = "Unbound variable: " ++ show var ++ showTrace stack show (TypeMismatch expected found stack) = "Expected " ++ expected ++ ", but found: " ++ show found ++ showTrace stack- show (ArgumentsNumWithNames names expected got stack) =- "Wrong number of arguments: " ++ show names ++ ": expected " ++ show expected ++ ", but got " ++ show got ++ showTrace stack- show (ArgumentsNumPrimitive expected got stack) =- "Wrong number of arguments for a primitive function: expected " ++ show expected ++ ", but got " ++ show got ++ showTrace stack+ show (ArgumentsNumPrimitive name expected got stack) =+ "Wrong number of arguments for a primitive function '" ++ name ++ "': expected " ++ show expected ++ ", but got " ++ show got ++ showTrace stack show (TupleLength expected got stack) = "Inconsistent tuple lengths: expected " ++ show expected ++ ", but got " ++ show got ++ showTrace stack show (InconsistentTensorShape stack) = "Inconsistent tensor shape" ++ showTrace stack@@ -643,11 +500,8 @@ show (Assertion message stack) = "Assertion failed: " ++ message ++ showTrace stack show (Parser err) = "Parse error at: " ++ err show (EgisonBug message stack) = "Egison Error: " ++ message ++ showTrace stack- show (MatchFailure currentFunc stack) = "Failed pattern match in: " ++ currentFunc ++ showTrace stack- show (UnknownFileExtension name) =- "Unknown file extension: " ++ name ++- "\nFile name should be suffixed with either \".egi\" (for Haskell-like syntax)" ++- " or \".segi\" (for S-expression syntax)"+ show (MatchFailure stack) = "Pattern match failed" ++ showTrace stack+ show (PrimitiveMatchFailure stack) = "Primitive data pattern match failed" ++ showTrace stack show (Default message) = "Error: " ++ message showTrace :: CallStack -> String@@ -659,35 +513,18 @@ -- Monads -- -newtype EvalM a = EvalM {- unEvalM :: StateT IState (ExceptT EgisonError IO) a- } deriving (Functor, Applicative, Monad, MonadIO, MonadError EgisonError)+type EvalT m = StateT EvalState (ExceptT EgisonError m) -instance MonadFail EvalM where- fail msg = throwError =<< EgisonBug msg <$> getFuncNameStack+type EvalM = EvalT RuntimeM -instance MonadEval EvalM where- fresh = EvalM $ do- st <- get; modify (\st -> st { indexCounter = indexCounter st + 1 })- return $ "$_" ++ show (indexCounter st)- freshV = EvalM $ do- st <- get; modify (\st -> st {indexCounter = indexCounter st + 1 })- return $ Var ["$_" ++ show (indexCounter st)] []- pushFuncName name = EvalM $ do- st <- get- put $ st { funcNameStack = name : funcNameStack st }- return ()- topFuncName = EvalM $ head . funcNameStack <$> get- popFuncName = EvalM $ do- st <- get- put $ st { funcNameStack = tail $ funcNameStack st }- return ()- getFuncNameStack = EvalM $ funcNameStack <$> get+instance {-# OVERLAPPING #-} MonadFail EvalM where+ fail msg = throwError =<< EgisonBug msg <$> getFuncNameStack -fromEvalM :: EvalM a -> IO (Either EgisonError a)-fromEvalM = runExceptT . modifyCounter . unEvalM+instance MonadRuntime EvalM where+ fresh = lift $ lift fresh -type MatchM = MaybeT EvalM+fromEvalT :: EvalM a -> RuntimeM (Either EgisonError a)+fromEvalT m = runExceptT (evalStateT m initialEvalState) -matchFail :: MatchM a-matchFail = MaybeT $ return Nothing+fromEvalM :: EgisonOpts -> EvalM a -> IO (Either EgisonError a)+fromEvalM opts = evalRuntimeT opts . fromEvalT
+ hs-src/Language/Egison/Data/Collection.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE TupleSections #-}++{- |+Module : Language.Egison.Data.Collection+Licence : MIT++This module provides some helper functions that operates on / returns+collections.+-}++module Language.Egison.Data.Collection+ ( expandCollection+ , isEmptyCollection+ , unconsCollection+ , unsnocCollection+ , collectionToRefs+ , collectionToList+ , makeICollection+ ) where++import Control.Monad.Except (throwError, lift, liftIO)+import Control.Monad.Trans.Maybe (runMaybeT)++import Data.Foldable (toList)+import Data.IORef+import Data.Maybe (fromJust)+import Data.Sequence (Seq, ViewL (..), ViewR (..), (><))+import qualified Data.Sequence as Sq++import Language.Egison.Data+import Language.Egison.Data.Utils+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.Match+import Language.Egison.MList++expandCollection :: WHNFData -> EvalM (Seq Inner)+expandCollection (Value (Collection vals)) =+ mapM (fmap IElement . newEvaluatedObjectRef . Value) vals+expandCollection (ICollection innersRef) = liftIO $ readIORef innersRef+expandCollection val = throwError =<< TypeMismatch "collection" val <$> getFuncNameStack++isEmptyCollection :: WHNFData -> EvalM Bool+isEmptyCollection (Value (Collection col)) = return $ Sq.null col+isEmptyCollection coll@(ICollection innersRef) = do+ inners <- liftIO $ readIORef innersRef+ case Sq.viewl inners of+ EmptyL -> return True+ ISubCollection ref' :< tInners -> do+ hInners <- evalRef ref' >>= expandCollection+ liftIO $ writeIORef innersRef (hInners >< tInners)+ isEmptyCollection coll+ _ -> return False+isEmptyCollection _ = return False++unconsCollection :: WHNFData -> MatchM (ObjectRef, ObjectRef)+unconsCollection (Value (Collection col)) =+ case Sq.viewl col of+ EmptyL -> matchFail+ val :< vals ->+ lift $ (,) <$> newEvaluatedObjectRef (Value val)+ <*> newEvaluatedObjectRef (Value $ Collection vals)+unconsCollection coll@(ICollection innersRef) = do+ inners <- liftIO $ readIORef innersRef+ case Sq.viewl inners of+ EmptyL -> matchFail+ IElement ref' :< tInners -> do+ tInnersRef <- liftIO $ newIORef tInners+ lift $ (ref', ) <$> newEvaluatedObjectRef (ICollection tInnersRef)+ ISubCollection ref' :< tInners -> do+ hInners <- lift $ evalRef ref' >>= expandCollection+ liftIO $ writeIORef innersRef (hInners >< tInners)+ unconsCollection coll+unconsCollection _ = matchFail++unsnocCollection :: WHNFData -> MatchM (ObjectRef, ObjectRef)+unsnocCollection (Value (Collection col)) =+ case Sq.viewr col of+ EmptyR -> matchFail+ vals :> val ->+ lift $ (,) <$> newEvaluatedObjectRef (Value $ Collection vals)+ <*> newEvaluatedObjectRef (Value val)+unsnocCollection coll@(ICollection innersRef) = do+ inners <- liftIO $ readIORef innersRef+ case Sq.viewr inners of+ EmptyR -> matchFail+ hInners :> IElement ref' -> do+ hInnersRef <- liftIO $ newIORef hInners+ lift $ (, ref') <$> newEvaluatedObjectRef (ICollection hInnersRef)+ hInners :> ISubCollection ref' -> do+ tInners <- lift $ evalRef ref' >>= expandCollection+ liftIO $ writeIORef innersRef (hInners >< tInners)+ unsnocCollection coll+unsnocCollection _ = matchFail++collectionToRefs :: WHNFData -> EvalM (MList EvalM ObjectRef)+collectionToRefs (Value (Collection vals)) =+ if Sq.null vals then return MNil+ else fromSeq <$> mapM (newEvaluatedObjectRef . Value) vals+collectionToRefs whnf@(ICollection _) = do+ isEmpty <- isEmptyCollection whnf+ if isEmpty+ then return MNil+ else do+ (head, tail) <- fromJust <$> runMaybeT (unconsCollection whnf)+ tail' <- evalRef tail+ return $ MCons head (collectionToRefs tail')+collectionToRefs whnf = throwError =<< TypeMismatch "collection" whnf <$> getFuncNameStack++collectionToList :: EgisonValue -> EvalM [EgisonValue]+collectionToList (Collection sq) = return $ toList sq+collectionToList val = throwError =<< TypeMismatch "collection" (Value val) <$> getFuncNameStack++makeICollection :: [WHNFData] -> EvalM WHNFData+makeICollection xs = do+ is <- mapM (\x -> IElement <$> newEvaluatedObjectRef x) xs+ v <- liftIO $ newIORef $ Sq.fromList is+ return $ ICollection v
+ hs-src/Language/Egison/Data/Utils.hs view
@@ -0,0 +1,78 @@+{- |+Module : Language.Egison.Data.Utils+Licence : MIT++This module provides some helper functions for handling Egison data.+-}++module Language.Egison.Data.Utils+ ( evalRef+ , evalObj+ , writeObjectRef+ , newEvaluatedObjectRef+ , makeBindings+ , makeBindings'+ , tupleToRefs+ , tupleToListWHNF+ , tupleToList+ , makeTuple+ , makeITuple+ ) where++import Control.Monad.State (liftIO)++import Data.IORef++import Language.Egison.Data+import Language.Egison.IExpr (Var, stringToVar)+++evalRef :: ObjectRef -> EvalM WHNFData+evalRef ref = do+ obj <- liftIO $ readIORef ref+ case obj of+ WHNF val -> return val+ Thunk thunk -> do+ val <- thunk+ writeObjectRef ref val+ return val++evalObj :: Object -> EvalM WHNFData+evalObj (WHNF val) = return val+evalObj (Thunk thunk) = thunk++writeObjectRef :: ObjectRef -> WHNFData -> EvalM ()+writeObjectRef ref val = liftIO . writeIORef ref $ WHNF val++newEvaluatedObjectRef :: WHNFData -> EvalM ObjectRef+newEvaluatedObjectRef = liftIO . newIORef . WHNF++makeBindings :: [Var] -> [ObjectRef] -> [Binding]+makeBindings = zip++makeBindings' :: [String] -> [ObjectRef] -> [Binding]+makeBindings' xs = zip (map stringToVar xs)++tupleToRefs :: WHNFData -> EvalM [ObjectRef]+tupleToRefs (ITuple refs) = return refs+tupleToRefs (Value (Tuple vals)) = mapM (newEvaluatedObjectRef . Value) vals+tupleToRefs whnf = return <$> newEvaluatedObjectRef whnf++tupleToListWHNF :: WHNFData -> EvalM [WHNFData]+tupleToListWHNF (ITuple refs) = mapM evalRef refs+tupleToListWHNF (Value (Tuple vals)) = return $ map Value vals+tupleToListWHNF whnf = return [whnf]++tupleToList :: EgisonValue -> [EgisonValue]+tupleToList (Tuple vals) = vals+tupleToList val = [val]++makeTuple :: [EgisonValue] -> EgisonValue+makeTuple [] = Tuple []+makeTuple [x] = x+makeTuple xs = Tuple xs++makeITuple :: [WHNFData] -> EvalM WHNFData+makeITuple [] = return (ITuple [])+makeITuple [x] = return x+makeITuple xs = ITuple <$> mapM newEvaluatedObjectRef xs
hs-src/Language/Egison/Desugar.hs view
@@ -1,122 +1,139 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TupleSections #-} {- | Module : Language.Egison.Desugar Licence : MIT -This module provide desugar functions.+This module provides desugar functions. -} module Language.Egison.Desugar- (- desugarTopExpr+ ( desugarTopExpr+ , desugarTopExprs , desugarExpr ) where import Control.Monad.Except (throwError) import Data.Char (toUpper)-import Data.Set (Set)-import qualified Data.Set as S+import Data.Foldable (foldrM)+import Data.List (union) import Language.Egison.AST import Language.Egison.Data-import Language.Egison.IState (fresh, freshV)+import Language.Egison.IExpr+import Language.Egison.RState -desugarTopExpr :: EgisonTopExpr -> EvalM EgisonTopExpr-desugarTopExpr (Define name expr) = Define name <$> desugar expr-desugarTopExpr (DefineWithIndices (VarWithIndices name is) expr) = do- body <- desugar expr- let indexNames = map extractIndex is- let indexNamesCollection = CollectionExpr (map (ElementExpr . stringToVarExpr) indexNames)- return $ Define (Var name (map (const () <$>) is))- (WithSymbolsExpr indexNames (TransposeExpr indexNamesCollection body))-desugarTopExpr (Redefine name expr) = Redefine name <$> desugar expr-desugarTopExpr (Test expr) = Test <$> desugar expr-desugarTopExpr (Execute expr) = Execute <$> desugar expr-desugarTopExpr expr = return expr -desugarExpr :: EgisonExpr -> EvalM EgisonExpr+desugarTopExpr :: TopExpr -> EvalM (Maybe ITopExpr)+desugarTopExpr (Define (VarWithIndices name []) expr) = do+ expr' <- desugar expr+ case expr' of+ ILambdaExpr Nothing args body -> return . Just $ IDefine (Var name []) (ILambdaExpr (Just name) args body)+ _ -> return . Just $ IDefine (Var name []) expr'+desugarTopExpr (Define vwi expr) = do+ (var, iexpr) <- desugarDefineWithIndices vwi expr+ return . Just $ IDefine var iexpr+desugarTopExpr (Test expr) = Just . ITest <$> desugar expr+desugarTopExpr (Execute expr) = Just . IExecute <$> desugar expr+desugarTopExpr (Load file) = return . Just $ ILoad file+desugarTopExpr (LoadFile file) = return . Just $ ILoadFile file+desugarTopExpr _ = return Nothing++desugarTopExprs :: [TopExpr] -> EvalM [ITopExpr]+desugarTopExprs [] = return []+desugarTopExprs (expr : exprs) = do+ expr' <- desugarTopExpr expr+ case expr' of+ Nothing -> desugarTopExprs exprs+ Just expr' -> (expr' :) <$> desugarTopExprs exprs++desugarExpr :: Expr -> EvalM IExpr desugarExpr = desugar -desugar :: EgisonExpr -> EvalM EgisonExpr+desugar :: Expr -> EvalM IExpr+desugar (ConstantExpr c) = return $ IConstantExpr c+desugar (VarExpr var) = return $ IVarExpr var+ desugar (AlgebraicDataMatcherExpr patterns) = do- matcherName <- freshV- let matcherRef = VarExpr matcherName+ matcherName <- fresh+ let matcherRef = IVarExpr matcherName matcher <- genMatcherClauses patterns matcherRef- return $ LetRecExpr [([matcherName], matcher)] matcherRef+ return $ ILetRecExpr [(PDPatVar (stringToVar matcherName), matcher)] matcherRef where- genMatcherClauses :: [(String, [EgisonExpr])] -> EgisonExpr -> EvalM EgisonExpr+ genMatcherClauses :: [(String, [Expr])] -> IExpr -> EvalM IExpr genMatcherClauses patterns matcher = do main <- genMainClause patterns matcher body <- mapM genMatcherClause patterns footer <- genSomethingClause let clauses = [main] ++ body ++ [footer]- return $ MatcherExpr clauses+ return $ IMatcherExpr clauses - genMainClause :: [(String, [EgisonExpr])] -> EgisonExpr -> EvalM (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])+ genMainClause :: [(String, [Expr])] -> IExpr -> EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)]) genMainClause patterns matcher = do clauses <- genClauses patterns- return (PPValuePat "val", TupleExpr []- ,[(PDPatVar "tgt", MatchExpr BFSMode- (TupleExpr [stringToVarExpr "val", stringToVarExpr "tgt"])- (TupleExpr [matcher, matcher])- clauses)])+ return (PPValuePat "val", ITupleExpr [],+ [(PDPatVar (stringToVar "tgt"),+ IMatchExpr BFSMode+ (ITupleExpr [IVarExpr "val", IVarExpr "tgt"])+ (ITupleExpr [matcher, matcher])+ clauses)]) where- genClauses :: [(String, [EgisonExpr])] -> EvalM [MatchClause]+ genClauses :: [(String, [Expr])] -> EvalM [IMatchClause] genClauses patterns = (++) <$> mapM genClause patterns- <*> pure [(TuplePat [WildCard, WildCard], matchingFailure)]+ <*> pure [(ITuplePat [IWildCard, IWildCard], matchingFailure)] - genClause :: (String, [EgisonExpr]) -> EvalM MatchClause+ genClause :: (String, [Expr]) -> EvalM IMatchClause genClause pattern = do (pat0, pat1) <- genMatchingPattern pattern- return (TuplePat [pat0, pat1], matchingSuccess)+ return (ITuplePat [pat0, pat1], matchingSuccess) - genMatchingPattern :: (String, [EgisonExpr]) -> EvalM (EgisonPattern, EgisonPattern)+ genMatchingPattern :: (String, [Expr]) -> EvalM (IPattern, IPattern) genMatchingPattern (name, patterns) = do- names <- mapM (const freshV) patterns- return (InductivePat name (map PatVar names),- InductivePat name (map (ValuePat . VarExpr) names))+ names <- mapM (const fresh) patterns+ return (IInductivePat name (map IPatVar names),+ IInductivePat name (map (IValuePat . IVarExpr) names)) - genMatcherClause :: (String, [EgisonExpr]) -> EvalM (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])+ genMatcherClause :: (String, [Expr]) -> EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)]) genMatcherClause pattern = do (ppat, matchers) <- genPrimitivePatPat pattern (dpat, body) <- genPrimitiveDataPat pattern- return (ppat, TupleExpr matchers, [(dpat, CollectionExpr [ElementExpr . TupleExpr $ body]), (PDWildCard, matchingFailure)])+ return (ppat, ITupleExpr matchers, [(dpat, ICollectionExpr [ITupleExpr body]), (PDWildCard, matchingFailure)]) where- genPrimitivePatPat :: (String, [EgisonExpr]) -> EvalM (PrimitivePatPattern, [EgisonExpr])+ genPrimitivePatPat :: (String, [Expr]) -> EvalM (PrimitivePatPattern, [IExpr]) genPrimitivePatPat (name, matchers) = do patterns' <- mapM (const $ return PPPatVar) matchers- return (PPInductivePat name patterns', matchers)+ matchers' <- mapM desugar matchers+ return (PPInductivePat name patterns', matchers') - genPrimitiveDataPat :: (String, [EgisonExpr]) -> EvalM (PrimitiveDataPattern, [EgisonExpr])+ genPrimitiveDataPat :: (String, [Expr]) -> EvalM (IPrimitiveDataPattern, [IExpr]) genPrimitiveDataPat (name, patterns) = do- patterns' <- mapM (const freshV) patterns- return (PDInductivePat (capitalize name) $ map (PDPatVar . show) patterns', map VarExpr patterns')+ patterns' <- mapM (const fresh) patterns+ return (PDInductivePat (capitalize name) $ map (PDPatVar . stringToVar) patterns', map IVarExpr patterns') capitalize :: String -> String capitalize (x:xs) = toUpper x : xs - genSomethingClause :: EvalM (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])+ genSomethingClause :: EvalM (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)]) genSomethingClause =- return (PPPatVar, TupleExpr [SomethingExpr], [(PDPatVar "tgt", CollectionExpr [ElementExpr (stringToVarExpr "tgt")])])+ return (PPPatVar, ITupleExpr [IConstantExpr SomethingExpr], [(PDPatVar (stringToVar "tgt"), ICollectionExpr [IVarExpr "tgt"])]) - matchingSuccess :: EgisonExpr- matchingSuccess = CollectionExpr [ElementExpr $ TupleExpr []]+ matchingSuccess :: IExpr+ matchingSuccess = ICollectionExpr [ITupleExpr []] - matchingFailure :: EgisonExpr- matchingFailure = CollectionExpr []+ matchingFailure :: IExpr+ matchingFailure = ICollectionExpr [] desugar (MatchAllLambdaExpr matcher clauses) = do name <- fresh- desugar $ LambdaExpr [TensorArg name] (MatchAllExpr BFSMode (stringToVarExpr name) matcher clauses)+ ILambdaExpr Nothing [name] <$>+ desugar (MatchAllExpr BFSMode (VarExpr name) matcher clauses) desugar (MatchLambdaExpr matcher clauses) = do name <- fresh- desugar $ LambdaExpr [TensorArg name] (MatchExpr BFSMode (stringToVarExpr name) matcher clauses)+ ILambdaExpr Nothing [name] <$>+ desugar (MatchExpr BFSMode (VarExpr name) matcher clauses) -- TODO: Allow nested MultiSubscript and MultiSuperscript desugar (IndexedExpr b expr indices) =@@ -124,347 +141,425 @@ [MultiSubscript x y] -> case (x, y) of (IndexedExpr b1 e1 [n1], IndexedExpr _ _ [n2]) ->- desugarMultiScript SubrefsExpr b1 e1 n1 n2- (TupleExpr [IndexedExpr b1 e1 [n1]], TupleExpr [IndexedExpr _ _ [n2]]) ->- desugarMultiScript SubrefsExpr b1 e1 n1 n2+ desugarMultiScript ISubrefsExpr b1 e1 n1 n2 _ -> throwError $ Default "Index should be IndexedExpr for multi subscript" [MultiSuperscript x y] -> case (x, y) of (IndexedExpr b1 e1 [n1], IndexedExpr _ _ [n2]) ->- desugarMultiScript SuprefsExpr b1 e1 n1 n2- (TupleExpr [IndexedExpr b1 e1 [n1]], TupleExpr [IndexedExpr _ _ [n2]]) ->- desugarMultiScript SuprefsExpr b1 e1 n1 n2+ desugarMultiScript ISuprefsExpr b1 e1 n1 n2 _ -> throwError $ Default "Index should be IndexedExpr for multi superscript"- _ -> IndexedExpr b <$> desugar expr <*> mapM desugarIndex indices+ _ -> IIndexedExpr b <$> desugar expr <*> mapM desugarIndex indices where desugarMultiScript refExpr b1 e1 n1 n2 = do- k <- fresh- return $ refExpr b expr (makeApply "map"- [LambdaExpr [TensorArg k] (IndexedExpr b1 e1 [Subscript $ stringToVarExpr k]),- makeApply "between" [extractIndex n1, extractIndex n2]])+ k <- fresh+ n1' <- desugar (extractIndexExpr n1)+ n2' <- desugar (extractIndexExpr n2)+ e1' <- desugar e1+ expr' <- desugar expr+ return $ refExpr b expr' (makeIApply "map"+ [ILambdaExpr Nothing [k] (IIndexedExpr b1 e1' [Sub (IVarExpr k)]),+ makeIApply "between" [n1', n2']]) desugar (SubrefsExpr bool expr1 expr2) =- SubrefsExpr bool <$> desugar expr1 <*> desugar expr2+ ISubrefsExpr bool <$> desugar expr1 <*> desugar expr2 desugar (SuprefsExpr bool expr1 expr2) =- SuprefsExpr bool <$> desugar expr1 <*> desugar expr2+ ISuprefsExpr bool <$> desugar expr1 <*> desugar expr2 desugar (UserrefsExpr bool expr1 expr2) =- UserrefsExpr bool <$> desugar expr1 <*> desugar expr2--desugar (PowerExpr expr1 expr2) =- (\x y -> makeApply "**" [x, y]) <$> desugar expr1 <*> desugar expr2--desugar (InductiveDataExpr name exprs) =- InductiveDataExpr name <$> mapM desugar exprs--desugar (TupleExpr exprs) =- TupleExpr <$> mapM desugar exprs--desugar expr@(CollectionExpr []) = return expr--desugar (CollectionExpr (ElementExpr elm:inners)) = do- elm' <- desugar elm- CollectionExpr inners' <- desugar (CollectionExpr inners)- return $ CollectionExpr (ElementExpr elm':inners')+ IUserrefsExpr bool <$> desugar expr1 <*> desugar expr2 -desugar (CollectionExpr (SubCollectionExpr sub:inners)) = do- sub' <- desugar sub- CollectionExpr inners' <- desugar (CollectionExpr inners)- return $ CollectionExpr (SubCollectionExpr sub':inners')+desugar (TupleExpr exprs) = ITupleExpr <$> mapM desugar exprs+desugar (CollectionExpr xs) = ICollectionExpr <$> mapM desugar xs+desugar (ConsExpr x xs) = IConsExpr <$> desugar x <*> desugar xs+desugar (JoinExpr x xs) = IJoinExpr <$> desugar x <*> desugar xs desugar (HashExpr exprPairs) =- HashExpr <$> mapM (\(expr1, expr2) -> (,) <$> desugar expr1 <*> desugar expr2) exprPairs+ IHashExpr <$> mapM (\(expr1, expr2) -> (,) <$> desugar expr1 <*> desugar expr2) exprPairs desugar (VectorExpr exprs) =- VectorExpr <$> mapM desugar exprs+ IVectorExpr <$> mapM desugar exprs desugar (TensorExpr nsExpr xsExpr) =- TensorExpr <$> desugar nsExpr <*> desugar xsExpr+ ITensorExpr <$> desugar nsExpr <*> desugar xsExpr -desugar (LambdaExpr names expr) = do+-- Desugar of LambdaExpr takes place in 2 stages.+-- * LambdaExpr -> LambdaExpr' : Desugar pattern matches at the arg positions+-- * LambdaExpr' -> ILambdaExpr : Desugar ScalarArg and InvertedScalarArg+desugar (LambdaExpr args expr) = do+ (args', expr') <- foldrM desugarArg ([], expr) args+ desugar $ LambdaExpr' args' expr'+ where+ desugarArg :: Arg ArgPattern -> ([Arg String], Expr) -> EvalM ([Arg String], Expr)+ desugarArg (TensorArg x) (args, expr) = do+ (var, expr') <- desugarArgPat x expr+ return (TensorArg var : args, expr')+ desugarArg (ScalarArg x) (args, expr) = do+ (var, expr') <- desugarArgPat x expr+ return (ScalarArg var : args, expr')+ desugarArg (InvertedScalarArg x) (args, expr) = do+ (var, expr') <- desugarArgPat x expr+ return (InvertedScalarArg var : args, expr')++ -- Desugar argument patterns. Examples:+ -- \$(%x, %y) -> expr ==> \$tmp -> let (tmp1, tmp2) := tmp in (\%x %y -> expr) tmp1 tmp2+ -- \(x, (y, z)) -> expr ==> \tmp -> let (tmp1, tmp2) := tmp in (\x (y, z) -> expr) tmp1 tmp2+ desugarArgPat :: ArgPattern -> Expr -> EvalM (String, Expr)+ desugarArgPat APWildCard expr = do+ tmp <- fresh+ return (tmp, LetExpr [Bind PDWildCard (VarExpr tmp)] expr)+ desugarArgPat (APPatVar var) expr = return (var, expr)+ desugarArgPat (APTuplePat args) expr = do+ tmp <- fresh+ tmps <- mapM (const fresh) args+ return (tmp, LetExpr [Bind (PDTuplePat (map PDPatVar tmps)) (VarExpr tmp)]+ (ApplyExpr (LambdaExpr args expr) (map VarExpr tmps)))+ desugarArgPat (APInductivePat ctor args) expr = do+ tmp <- fresh+ tmps <- mapM (const fresh) args+ return (tmp, LetExpr [Bind (PDInductivePat ctor (map PDPatVar tmps)) (VarExpr tmp)]+ (ApplyExpr (LambdaExpr args expr) (map VarExpr tmps)))+ desugarArgPat APEmptyPat expr = do+ tmp <- fresh+ return (tmp, LetExpr [Bind PDEmptyPat (VarExpr tmp)] expr)+ desugarArgPat (APConsPat arg1 arg2) expr = do+ tmp <- fresh+ tmp1 <- fresh+ tmp2 <- fresh+ return (tmp, LetExpr [Bind (PDConsPat (PDPatVar tmp1) (PDPatVar tmp2)) (VarExpr tmp)]+ (ApplyExpr (LambdaExpr [arg1, arg2] expr) [VarExpr tmp1, VarExpr tmp2]))+ desugarArgPat (APSnocPat arg1 arg2) expr = do+ tmp <- fresh+ tmp1 <- fresh+ tmp2 <- fresh+ return (tmp, LetExpr [Bind (PDSnocPat (PDPatVar tmp1) (PDPatVar tmp2)) (VarExpr tmp)]+ (ApplyExpr (LambdaExpr [arg1, arg2] expr) [VarExpr tmp1, VarExpr tmp2]))++desugar (LambdaExpr' names expr) = do let (args', expr') = foldr desugarInvertedArgs ([], expr) names- expr'' <- desugar expr'- return $ LambdaExpr args' expr''+ expr' <- desugar expr'+ return $ ILambdaExpr Nothing args' expr' where- desugarInvertedArgs :: Arg -> ([Arg], EgisonExpr) -> ([Arg], EgisonExpr)- desugarInvertedArgs (TensorArg x) (args, expr) = (TensorArg x : args, expr)+ desugarInvertedArgs :: Arg String -> ([String], Expr) -> ([String], Expr)+ desugarInvertedArgs (TensorArg x) (args, expr) = (x : args, expr) desugarInvertedArgs (ScalarArg x) (args, expr) =- (TensorArg x : args,- TensorMapExpr (LambdaExpr [TensorArg x] expr) (stringToVarExpr x))+ (x : args,+ TensorMapExpr (LambdaExpr' [TensorArg x] expr) (VarExpr x)) desugarInvertedArgs (InvertedScalarArg x) (args, expr) =- (TensorArg x : args,- TensorMapExpr (LambdaExpr [TensorArg x] expr) (FlipIndicesExpr (stringToVarExpr x)))+ (x : args,+ TensorMapExpr (LambdaExpr' [TensorArg x] expr) (FlipIndicesExpr (VarExpr x))) desugar (MemoizedLambdaExpr names expr) =- MemoizedLambdaExpr names <$> desugar expr+ IMemoizedLambdaExpr names <$> desugar expr desugar (CambdaExpr name expr) =- CambdaExpr name <$> desugar expr+ ICambdaExpr name <$> desugar expr desugar (PatternFunctionExpr names pattern) =- PatternFunctionExpr names <$> desugarPattern pattern+ IPatternFunctionExpr names <$> desugarPattern pattern desugar (IfExpr expr0 expr1 expr2) =- IfExpr <$> desugar expr0 <*> desugar expr1 <*> desugar expr2--desugar (LetRecExpr binds expr) =- LetRecExpr <$> desugarBindings binds <*> desugar expr+ IIfExpr <$> desugar expr0 <*> desugar expr1 <*> desugar expr2 desugar (LetExpr binds expr) =- LetExpr <$> desugarBindings binds <*> desugar expr+ ILetExpr <$> desugarBindings binds <*> desugar expr -desugar (LetStarExpr binds expr) = do- binds' <- desugarBindings binds- expr' <- desugar expr- return $ foldr (\bind ret -> LetExpr [bind] ret) expr' binds'+desugar (LetRecExpr binds expr) =+ ILetRecExpr <$> desugarBindings binds <*> desugar expr desugar (WithSymbolsExpr vars expr) =- WithSymbolsExpr vars <$> desugar expr+ IWithSymbolsExpr vars <$> desugar expr desugar (MatchExpr pmmode expr0 expr1 clauses) =- MatchExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses+ IMatchExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses desugar (MatchAllExpr pmmode expr0 expr1 clauses) =- MatchAllExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses+ IMatchAllExpr pmmode <$> desugar expr0 <*> desugar expr1 <*> desugarMatchClauses clauses desugar (DoExpr binds expr) =- DoExpr <$> desugarBindings binds <*> desugar expr--desugar (IoExpr expr) =- IoExpr <$> desugar expr+ IDoExpr <$> desugarBindings binds <*> desugar expr -desugar (PrefixExpr "-" expr) =- desugar (InfixExpr mult (IntegerExpr (-1)) expr)- where mult = findOpFrom "*" reservedExprInfix-desugar (PrefixExpr "!" (ApplyExpr expr1 expr2)) =- WedgeApplyExpr <$> desugar expr1 <*> desugar expr2-desugar (PrefixExpr "'" expr) = QuoteExpr <$> desugar expr-desugar (PrefixExpr "`" expr) = QuoteSymbolExpr <$> desugar expr+desugar (PrefixExpr "-" expr) = do+ expr' <- desugar expr+ return $ makeIApply "*" [IConstantExpr (IntegerExpr (-1)), expr']+desugar (PrefixExpr "!" (ApplyExpr expr args)) =+ IWedgeApplyExpr <$> desugar expr <*> mapM desugar args+desugar (PrefixExpr "'" expr) = IQuoteExpr <$> desugar expr+desugar (PrefixExpr "`" expr) = IQuoteSymbolExpr <$> desugar expr+desugar (PrefixExpr op _) = fail ("Unknown prefix " ++ op) desugar (InfixExpr op expr1 expr2) | isWedge op =- (\x y -> WedgeApplyExpr (stringToVarExpr (func op)) (TupleExpr [x, y]))+ (\x y -> IWedgeApplyExpr (IVarExpr (repr op)) [x, y]) <$> desugar expr1 <*> desugar expr2 desugar (InfixExpr op expr1 expr2) | repr op == "::" =- (\x y -> CollectionExpr [ElementExpr x, SubCollectionExpr y]) <$> desugar expr1 <*> desugar expr2+ IConsExpr <$> desugar expr1 <*> desugar expr2 desugar (InfixExpr op expr1 expr2) | repr op == "++" =- (\x y -> CollectionExpr [SubCollectionExpr x, SubCollectionExpr y]) <$> desugar expr1 <*> desugar expr2+ IJoinExpr <$> desugar expr1 <*> desugar expr2 desugar (InfixExpr op expr1 expr2) =- (\x y -> makeApply (func op) [x, y]) <$> desugar expr1 <*> desugar expr2+ (\x y -> makeIApply (repr op) [x, y]) <$> desugar expr1 <*> desugar expr2 -- section -- -- If `op` is not a cambda, simply desugar it into the function-desugar (SectionExpr op Nothing Nothing) | not (isWedge op) =- desugar (stringToVarExpr (func op))+desugar (SectionExpr op Nothing Nothing)+ | not (isWedge op || repr op `elem` ["::", "++"]) =+ desugar (VarExpr (repr op)) desugar (SectionExpr op Nothing Nothing) = do x <- fresh y <- fresh- desugar $ LambdaExpr [TensorArg x, TensorArg y]- (InfixExpr op (stringToVarExpr x) (stringToVarExpr y))+ ILambdaExpr Nothing [x, y] <$> desugar (InfixExpr op (VarExpr x) (VarExpr y)) desugar (SectionExpr op Nothing (Just expr2)) = do x <- fresh- desugar $ LambdaExpr [TensorArg x]- (InfixExpr op (stringToVarExpr x) expr2)+ ILambdaExpr Nothing [x] <$> desugar (InfixExpr op (VarExpr x) expr2) desugar (SectionExpr op (Just expr1) Nothing) = do y <- fresh- desugar $ LambdaExpr [TensorArg y]- (InfixExpr op expr1 (stringToVarExpr y))+ ILambdaExpr Nothing [y] <$> desugar (InfixExpr op expr1 (VarExpr y)) desugar SectionExpr{} = throwError $ Default "Cannot reach here: section with both arguments" desugar (SeqExpr expr0 expr1) =- SeqExpr <$> desugar expr0 <*> desugar expr1+ ISeqExpr <$> desugar expr0 <*> desugar expr1 desugar (GenerateTensorExpr fnExpr sizeExpr) =- GenerateTensorExpr <$> desugar fnExpr <*> desugar sizeExpr+ IGenerateTensorExpr <$> desugar fnExpr <*> desugar sizeExpr desugar (TensorContractExpr tExpr) =- TensorContractExpr <$> desugar tExpr+ ITensorContractExpr <$> desugar tExpr +desugar (TensorMapExpr (LambdaExpr' [x] (TensorMapExpr (LambdaExpr' [y] expr) b)) a) =+ desugar (TensorMap2Expr (LambdaExpr' [x, y] expr) a b) desugar (TensorMapExpr (LambdaExpr [x] (TensorMapExpr (LambdaExpr [y] expr) b)) a) = desugar (TensorMap2Expr (LambdaExpr [x, y] expr) a b) desugar (TensorMapExpr fnExpr tExpr) =- TensorMapExpr <$> desugar fnExpr <*> desugar tExpr+ ITensorMapExpr <$> desugar fnExpr <*> desugar tExpr desugar (TensorMap2Expr fnExpr t1Expr t2Expr) =- TensorMap2Expr <$> desugar fnExpr <*> desugar t1Expr <*> desugar t2Expr+ ITensorMap2Expr <$> desugar fnExpr <*> desugar t1Expr <*> desugar t2Expr desugar (TransposeExpr vars expr) =- TransposeExpr <$> desugar vars <*> desugar expr+ ITransposeExpr <$> desugar vars <*> desugar expr desugar (FlipIndicesExpr expr) =- FlipIndicesExpr <$> desugar expr+ IFlipIndicesExpr <$> desugar expr -desugar (ApplyExpr expr0 expr1) =- ApplyExpr <$> desugar expr0 <*> desugar expr1+desugar (ApplyExpr expr args) =+ IApplyExpr <$> desugar expr <*> mapM desugar args desugar (CApplyExpr expr0 expr1) =- CApplyExpr <$> desugar expr0 <*> desugar expr1+ ICApplyExpr <$> desugar expr0 <*> desugar expr1 desugar FreshVarExpr = do id <- fresh- return $ stringToVarExpr (":::" ++ id)+ return $ IVarExpr (":::" ++ id) desugar (MatcherExpr patternDefs) =- MatcherExpr <$> mapM desugarPatternDef patternDefs+ IMatcherExpr <$> mapM desugarPatternDef patternDefs -desugar (AnonParamExpr n) = return $ AnonParamExpr n+desugar (AnonParamExpr n) = return $ IVarExpr ('%' : show n) desugar (AnonParamFuncExpr n expr) = do expr' <- desugar expr- return $ LetRecExpr [([stringToVar "::0"], AnonParamFuncExpr n expr')] (stringToVarExpr "::0")+ let lambda = ILambdaExpr Nothing (map (\n -> '%' : show n) [1..n]) expr'+ return $ ILetRecExpr [(PDPatVar (stringToVar "%0"), lambda)] (IVarExpr "%0") desugar (QuoteExpr expr) =- QuoteExpr <$> desugar expr+ IQuoteExpr <$> desugar expr desugar (QuoteSymbolExpr expr) =- QuoteSymbolExpr <$> desugar expr+ IQuoteSymbolExpr <$> desugar expr -desugar (WedgeApplyExpr expr0 expr1) =- WedgeApplyExpr <$> desugar expr0 <*> desugar expr1+desugar (WedgeApplyExpr expr args) =+ IWedgeApplyExpr <$> desugar expr <*> mapM desugar args -desugar expr = return expr+desugar (FunctionExpr args) = return $ IFunctionExpr args -desugarIndex :: Index EgisonExpr -> EvalM (Index EgisonExpr)-desugarIndex index = traverse desugar index+desugarIndex :: IndexExpr Expr -> EvalM (Index IExpr)+desugarIndex (Subscript e) = Sub <$> desugar e+desugarIndex (Superscript e) = Sup <$> desugar e+desugarIndex (SupSubscript e) = SupSub <$> desugar e+desugarIndex (Userscript e) = User <$> desugar e+desugarIndex _ = undefined -desugarPattern :: EgisonPattern -> EvalM EgisonPattern-desugarPattern pattern = LetPat (map makeBinding $ S.elems $ collectName pattern) <$> desugarPattern' (desugarPatternInfix pattern)+desugarPattern :: Pattern -> EvalM IPattern+desugarPattern pat =+ case collectName pat of+ [] -> desugarPattern' pat+ names -> ILetPat (map makeBinding names) <$> desugarPattern' pat where- collectNames :: [EgisonPattern] -> Set String- collectNames patterns = S.unions $ map collectName patterns-- collectName :: EgisonPattern -> Set String- collectName (ForallPat pattern1 pattern2) = collectName pattern1 `S.union` collectName pattern2- collectName (InfixPat _ pattern1 pattern2) = collectName pattern1 `S.union` collectName pattern2- collectName (NotPat pattern) = collectName pattern- collectName (AndPat patterns) = collectNames patterns- collectName (OrPat patterns) = collectNames patterns- collectName (TuplePat patterns) = collectNames patterns- collectName (InductiveOrPApplyPat _ patterns) = collectNames patterns- collectName (InductivePat _ patterns) = collectNames patterns- collectName (PApplyPat _ patterns) = collectNames patterns- collectName (DApplyPat _ patterns) = collectNames patterns- collectName (LoopPat _ (LoopRange _ _ endNumPat) pattern1 pattern2) = collectName endNumPat `S.union` collectName pattern1 `S.union` collectName pattern2- collectName (LetPat _ pattern) = collectName pattern- collectName (IndexedPat (PatVar name) _) = S.singleton $ show name- collectName (DivPat pattern1 pattern2) = collectName pattern1 `S.union` collectName pattern2- collectName (PlusPat patterns) = collectNames patterns- collectName (MultPat patterns) = collectNames patterns- collectName (PowerPat pattern1 pattern2) = collectName pattern1 `S.union` collectName pattern2- collectName _ = S.empty+ collectNames :: [Pattern] -> [String]+ collectNames pats = foldl union [] (map collectName pats) - makeBinding :: String -> BindingExpr- makeBinding name = ([stringToVar name], HashExpr [])+ collectName :: Pattern -> [String]+ collectName (ForallPat pat1 pat2) = collectName pat1 `union` collectName pat2+ collectName (InfixPat _ pat1 pat2) = collectName pat1 `union` collectName pat2+ collectName (NotPat pat) = collectName pat+ collectName (AndPat pat1 pat2) = collectName pat1 `union` collectName pat2+ collectName (OrPat pat1 pat2) = collectName pat1 `union` collectName pat2+ collectName (TuplePat pats) = collectNames pats+ collectName (InductiveOrPApplyPat _ pats) = collectNames pats+ collectName (InductivePat _ pats) = collectNames pats+ collectName (PApplyPat _ pats) = collectNames pats+ collectName (DApplyPat _ pats) = collectNames pats+ collectName (LoopPat _ (LoopRange _ _ endNumPat) pat1 pat2) = collectName endNumPat `union` collectName pat1 `union` collectName pat2+ collectName (LetPat _ pat) = collectName pat+ collectName (IndexedPat (PatVar var) _) = [var]+ collectName _ = [] -desugarPatternInfix :: EgisonPattern -> EgisonPattern-desugarPatternInfix (IndexedPat pat es) = IndexedPat (desugarPatternInfix pat) es-desugarPatternInfix (LetPat bindings pat) = LetPat bindings (desugarPatternInfix pat)-desugarPatternInfix (InfixPat Infix{ repr = "&" } pat1 pat2) =- AndPat [desugarPatternInfix pat1, desugarPatternInfix pat2]-desugarPatternInfix (InfixPat Infix{ repr = "|" } pat1 pat2) =- OrPat [desugarPatternInfix pat1, desugarPatternInfix pat2]-desugarPatternInfix (InfixPat Infix{ repr = "^" } pat1 pat2) =- PowerPat (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix (InfixPat Infix{ repr = "*" } pat1 pat2) =- MultPat [desugarPatternInfix pat1, desugarPatternInfix pat2]-desugarPatternInfix (InfixPat Infix{ repr = "+" } pat1 pat2) =- PlusPat [desugarPatternInfix pat1, desugarPatternInfix pat2]-desugarPatternInfix (InfixPat Infix{ func = f } pat1 pat2) =- InductivePat f [desugarPatternInfix pat1, desugarPatternInfix pat2]-desugarPatternInfix (NotPat pat) = NotPat (desugarPatternInfix pat)-desugarPatternInfix (ForallPat pat1 pat2) =- ForallPat (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix (TuplePat pats) = TuplePat (map desugarPatternInfix pats)-desugarPatternInfix (InductivePat ctor pats) =- InductivePat ctor (map desugarPatternInfix pats)-desugarPatternInfix (LoopPat name range pat1 pat2) =- LoopPat name range (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix (PApplyPat expr pats) =- PApplyPat expr (map desugarPatternInfix pats)-desugarPatternInfix (InductiveOrPApplyPat name pats) =- InductiveOrPApplyPat name (map desugarPatternInfix pats)-desugarPatternInfix (SeqConsPat pat1 pat2) =- SeqConsPat (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix (DApplyPat pat pats) =- DApplyPat (desugarPatternInfix pat) (map desugarPatternInfix pats)-desugarPatternInfix (DivPat pat1 pat2) =- DivPat (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix (PlusPat pats) = PlusPat (map desugarPatternInfix pats)-desugarPatternInfix (MultPat pats) = MultPat (map desugarPatternInfix pats)-desugarPatternInfix (PowerPat pat1 pat2) =- PowerPat (desugarPatternInfix pat1) (desugarPatternInfix pat2)-desugarPatternInfix pat = pat+ makeBinding :: String -> IBindingExpr+ makeBinding var = (PDPatVar (stringToVar var), IHashExpr []) -desugarPattern' :: EgisonPattern -> EvalM EgisonPattern-desugarPattern' (ValuePat expr) = ValuePat <$> desugar expr-desugarPattern' (PredPat expr) = PredPat <$> desugar expr-desugarPattern' (NotPat pattern) = NotPat <$> desugarPattern' pattern-desugarPattern' (ForallPat pattern1 pattern2) = ForallPat <$> desugarPattern' pattern1 <*> desugarPattern' pattern2-desugarPattern' (AndPat patterns) = AndPat <$> mapM desugarPattern' patterns-desugarPattern' (OrPat patterns) = OrPat <$> mapM desugarPattern' patterns-desugarPattern' (TuplePat patterns) = TuplePat <$> mapM desugarPattern' patterns-desugarPattern' (InductiveOrPApplyPat name patterns) = InductiveOrPApplyPat name <$> mapM desugarPattern' patterns-desugarPattern' (InductivePat name patterns) = InductivePat name <$> mapM desugarPattern' patterns-desugarPattern' (IndexedPat pattern exprs) = IndexedPat <$> desugarPattern' pattern <*> mapM desugar exprs-desugarPattern' (PApplyPat expr patterns) = PApplyPat <$> desugar expr <*> mapM desugarPattern' patterns-desugarPattern' (DApplyPat pattern patterns) = DApplyPat <$> desugarPattern' pattern <*> mapM desugarPattern' patterns-desugarPattern' (LoopPat name range pattern1 pattern2) = LoopPat name <$> desugarLoopRange range <*> desugarPattern' pattern1 <*> desugarPattern' pattern2-desugarPattern' (LetPat binds pattern) = LetPat <$> desugarBindings binds <*> desugarPattern' pattern-desugarPattern' (SeqConsPat pattern1 pattern2) = SeqConsPat <$> desugarPattern' pattern1 <*> desugarPattern' pattern2-desugarPattern' (DivPat pattern1 pattern2) = do- pat1' <- desugarPattern' pattern1- pat2' <- desugarPattern' pattern2- return $ InductivePat "div" [pat1', pat2']-desugarPattern' (PlusPat patterns) = do- pats' <- mapM desugarPattern' (concatMap flatten patterns)- case reverse pats' of- [] -> return $ InductivePat "plus" [ValuePat (IntegerExpr 0)]- lp:hps ->- return $ InductivePat "plus" [foldr (\p acc -> InductivePat "cons" [p, acc]) lp (reverse hps)]- where- flatten (PlusPat xs) = concatMap flatten xs- flatten pat = [pat]-desugarPattern' (MultPat patterns) = do- intPat:pats' <- mapM desugarPattern' (concatMap flatten patterns)- case reverse pats' of- [] -> return $ InductivePat "mult" [intPat, ValuePat (IntegerExpr 1)]- lp:hps -> do- let mono = foldr (\p acc -> case p of- PowerPat p1 p2 -> InductivePat "ncons" [p1, p2, acc]- _ -> InductivePat "cons" [p, acc])- (case lp of- PowerPat p1 p2 -> InductivePat "ncons" [p1, p2, ValuePat (IntegerExpr 1)]- _ -> lp)- (reverse hps)- return $ InductivePat "mult" [intPat, mono]- where- flatten (MultPat xs) = concatMap flatten xs- flatten pat = [pat]-desugarPattern' (PowerPat pattern1 pattern2) = PowerPat <$> desugarPattern' pattern1 <*> desugarPattern' pattern2-desugarPattern' pattern = return pattern+desugarPattern' :: Pattern -> EvalM IPattern+desugarPattern' WildCard = return IWildCard+desugarPattern' ContPat = return IContPat+desugarPattern' SeqNilPat = return ISeqNilPat+desugarPattern' LaterPatVar = return ILaterPatVar+desugarPattern' (VarPat v) = return (IVarPat v)+desugarPattern' (PatVar var) = return (IPatVar var)+desugarPattern' (ValuePat expr) = IValuePat <$> desugar expr+desugarPattern' (PredPat expr) = IPredPat <$> desugar expr+desugarPattern' (NotPat pat) = INotPat <$> desugarPattern' pat+desugarPattern' (AndPat pat1 pat2) = IAndPat <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (OrPat pat1 pat2) = IOrPat <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (ForallPat pat1 pat2) = IForallPat <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (InfixPat Op{ repr = "&" } pat1 pat2) =+ IAndPat <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (InfixPat Op{ repr = "|" } pat1 pat2) =+ IOrPat <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (InfixPat Op{ repr = f } pat1 pat2) =+ (\x y -> IInductivePat f [x, y]) <$> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (TuplePat pats) = ITuplePat <$> mapM desugarPattern' pats+desugarPattern' (InductiveOrPApplyPat name pats) = IInductiveOrPApplyPat name <$> mapM desugarPattern' pats+desugarPattern' (InductivePat name pats) = IInductivePat name <$> mapM desugarPattern' pats+desugarPattern' (IndexedPat pat exprs) = IIndexedPat <$> desugarPattern' pat <*> mapM desugar exprs+desugarPattern' (PApplyPat expr pats) = IPApplyPat <$> desugar expr <*> mapM desugarPattern' pats+desugarPattern' (DApplyPat pat pats) = IDApplyPat <$> desugarPattern' pat <*> mapM desugarPattern' pats+desugarPattern' (LoopPat name range pat1 pat2) = ILoopPat name <$> desugarLoopRange range <*> desugarPattern' pat1 <*> desugarPattern' pat2+desugarPattern' (LetPat binds pat) = ILetPat <$> desugarBindings binds <*> desugarPattern' pat+desugarPattern' (SeqConsPat pat1 pat2) = ISeqConsPat <$> desugarPattern' pat1 <*> desugarPattern' pat2 -desugarLoopRange :: LoopRange -> EvalM LoopRange-desugarLoopRange (LoopRange sExpr eExpr pattern) =- LoopRange <$> desugar sExpr <*> desugar eExpr <*> desugarPattern' pattern+desugarLoopRange :: LoopRange -> EvalM ILoopRange+desugarLoopRange (LoopRange sExpr eExpr pat) =+ ILoopRange <$> desugar sExpr <*> desugar eExpr <*> desugarPattern' pat -desugarBindings :: [BindingExpr] -> EvalM [BindingExpr]-desugarBindings = mapM (\(name, expr) -> (name,) <$> desugar expr)+desugarBindings :: [BindingExpr] -> EvalM [IBindingExpr]+desugarBindings = mapM desugarBinding+ where+ desugarBinding (Bind name expr) = do+ let name' = fmap stringToVar name+ expr' <- desugar expr+ case (name, expr') of+ (PDPatVar var, ILambdaExpr Nothing args body) ->+ return (name', ILambdaExpr (Just var) args body)+ _ -> return (name', expr')+ desugarBinding (BindWithIndices vwi expr) = do+ (var, iexpr) <- desugarDefineWithIndices vwi expr+ return (PDPatVar var, iexpr) -desugarMatchClauses :: [MatchClause] -> EvalM [MatchClause]-desugarMatchClauses = mapM (\(pattern, expr) -> (,) <$> desugarPattern pattern <*> desugar expr)+desugarMatchClauses :: [MatchClause] -> EvalM [IMatchClause]+desugarMatchClauses = mapM (\(pat, expr) -> (,) <$> desugarPattern pat <*> desugar expr) -desugarPatternDef :: PatternDef -> EvalM PatternDef+desugarPatternDef :: PatternDef -> EvalM IPatternDef desugarPatternDef (pp, matcher, pds) = (pp,,) <$> desugar matcher <*> desugarPrimitiveDataMatchClauses pds -desugarPrimitiveDataMatchClauses :: [(PrimitiveDataPattern, EgisonExpr)] -> EvalM [(PrimitiveDataPattern, EgisonExpr)]-desugarPrimitiveDataMatchClauses = mapM (\(pd, expr) -> (pd,) <$> desugar expr)+desugarPrimitiveDataMatchClauses :: [(PrimitiveDataPattern, Expr)] -> EvalM [(IPrimitiveDataPattern, IExpr)]+desugarPrimitiveDataMatchClauses = mapM (\(pd, expr) -> (fmap stringToVar pd,) <$> desugar expr) -makeApply :: String -> [EgisonExpr] -> EgisonExpr-makeApply func args = ApplyExpr (stringToVarExpr func) (TupleExpr args)+desugarDefineWithIndices :: VarWithIndices -> Expr -> EvalM (Var, IExpr)+desugarDefineWithIndices (VarWithIndices name is) expr = do+ let (isSubs, indexNames) = unzip $ concatMap extractSubSupIndex is+ expr <- if any isExtendedIndice is+ then desugarExtendedIndices is isSubs indexNames expr+ else return expr+ body <- desugar expr+ let indexNamesCollection = ICollectionExpr (map IVarExpr indexNames)+ let is' = map (\b -> if b then Sub () else Sup ()) isSubs+ return (Var name is', IWithSymbolsExpr indexNames (ITransposeExpr indexNamesCollection body))++extractSubSupIndex :: VarIndex -> [(Bool, String)]+extractSubSupIndex (VSubscript x) = [(True, x)]+extractSubSupIndex (VSuperscript x) = [(False, x)]+extractSubSupIndex (VGroupScripts xs) = concatMap extractSubSupIndex xs+extractSubSupIndex (VSymmScripts xs) = concatMap extractSubSupIndex xs+extractSubSupIndex (VAntiSymmScripts xs) = concatMap extractSubSupIndex xs++desugarExtendedIndices :: [VarIndex] -> [Bool] -> [String] -> Expr -> EvalM Expr+desugarExtendedIndices indices isSubs indexNames tensorBody = do+ tensorName <- fresh+ tensorGenExpr <- f indices (VarExpr tensorName) [] []+ let indexFunctionExpr = LambdaExpr' (map TensorArg indexNames) tensorGenExpr+ let genTensorExpr = GenerateTensorExpr indexFunctionExpr (makeApply "tensorShape" [VarExpr tensorName])+ let tensorIndices = zipWith (\isSub name -> if isSub then Subscript (VarExpr name) else Superscript (VarExpr name)) isSubs indexNames+ return $ LetExpr [Bind (PDPatVar tensorName) tensorBody] (IndexedExpr True genTensorExpr tensorIndices)+ where+ f :: [VarIndex] -> Expr -> [String] -> [BindingExpr] -> EvalM Expr+ f [] expr [] [] = return expr+ f [] expr [] bindings = return $ LetRecExpr bindings expr+ f [] expr signs bindings =+ return $ LetRecExpr bindings (makeApply "product" [CollectionExpr (map VarExpr signs ++ [expr])])+ f (index:indices) expr signs bindings = do+ (indices', signs', bindings') <- genBindings index+ let isSubs = subOrSupScripts index+ symbols <- mapM (const fresh) isSubs+ let is = zipWith (\x isSub -> (if isSub then Subscript else Superscript) (VarExpr x)) symbols isSubs+ f indices (IndexedExpr True expr is)+ (signs ++ signs') (bindings ++ bindings' ++ [Bind (foldr PDConsPat PDEmptyPat (map PDPatVar symbols)) indices'])++ subOrSupScripts :: VarIndex -> [Bool]+ subOrSupScripts VSubscript{} = [True]+ subOrSupScripts VSuperscript{} = [False]+ subOrSupScripts (VGroupScripts xs) = concatMap subOrSupScripts xs+ subOrSupScripts (VSymmScripts xs) = concatMap subOrSupScripts xs+ subOrSupScripts (VAntiSymmScripts xs) = concatMap subOrSupScripts xs++ genBindings :: VarIndex -> EvalM (Expr, [String], [BindingExpr])+ genBindings (VSubscript x) = return (CollectionExpr [VarExpr x], [], [])+ genBindings (VSuperscript x) = return (CollectionExpr [VarExpr x], [], [])+ genBindings (VGroupScripts xs) = do+ (indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs+ let newIndices =+ -- If indices are all CollectionExpr, we can calculate the concatenated result of them+ case allCollections indices of+ Just xs -> CollectionExpr xs+ Nothing -> makeApply "concat" [CollectionExpr indices]+ return (newIndices, concat signss, concat bindingss)+ where+ allCollections [] = Just []+ allCollections (CollectionExpr xs : exprs) = (xs ++) <$> allCollections exprs+ allCollections _ = Nothing+ genBindings (VSymmScripts xs) = do+ (indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs+ let signs = concat signss+ let bindings = concat bindingss+ sortedCollectionName <- fresh+ let newBindings = bindings ++ [Bind (PDTuplePat [PDWildCard, PDPatVar sortedCollectionName]) (makeApply "sortWithSign" [CollectionExpr indices])]+ return (VarExpr sortedCollectionName, signs, newBindings)+ genBindings (VAntiSymmScripts xs) = do+ (indices, signss, bindingss) <- unzip3 <$> mapM genBindings xs+ let signs = concat signss+ let bindings = concat bindingss+ sortedCollectionName <- fresh+ signName <- fresh+ let newBindings = bindings ++ [Bind (PDTuplePat [PDPatVar signName, PDPatVar sortedCollectionName]) (makeApply "sortWithSign" [CollectionExpr indices])]+ return (VarExpr sortedCollectionName, signName : signs, newBindings)++--+-- Utils+--++extractIndexExpr :: IndexExpr a -> a+extractIndexExpr (Subscript x) = x+extractIndexExpr (Superscript x) = x+extractIndexExpr (SupSubscript x) = x+extractIndexExpr (Userscript x) = x+extractIndexExpr _ = error "extractIndexExpr: Not supported"++isExtendedIndice :: VarIndex -> Bool+isExtendedIndice VSubscript{} = False+isExtendedIndice VSuperscript{} = False+isExtendedIndice (VGroupScripts xs) = isExtendedIndice (head xs)+isExtendedIndice _ = True
+ hs-src/Language/Egison/Eval.hs view
@@ -0,0 +1,169 @@+{- |+Module : Language.Egison.Eval+Licence : MIT++This module provides interface for evaluating Egison expressions.+-}++module Language.Egison.Eval+ -- * Eval Egison expressions+ ( evalExpr+ , evalTopExpr+ , evalTopExprStr+ , evalTopExprs+ , evalTopExprsNoPrint+ , runExpr+ , runTopExpr+ , runTopExprs+ -- * Load Egison files+ , loadEgisonLibrary+ , loadEgisonFile+ ) where++import Control.Monad.Except (throwError)+import Control.Monad.Reader (ask, asks)+import Control.Monad.State++import Language.Egison.AST+import Language.Egison.CmdOptions+import Language.Egison.Core+import Language.Egison.Data+import Language.Egison.Desugar+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.IExpr+import Language.Egison.MathOutput (prettyMath)+import Language.Egison.Parser+++-- | Evaluate an Egison expression.+evalExpr :: Env -> Expr -> EvalM EgisonValue+evalExpr env expr = desugarExpr expr >>= evalExprDeep env++-- | Evaluate an Egison top expression.+evalTopExpr :: Env -> TopExpr -> EvalM (Maybe EgisonValue, Env)+evalTopExpr env topExpr = do+ topExpr <- desugarTopExpr topExpr+ case topExpr of+ Nothing -> return (Nothing, env)+ Just topExpr -> evalTopExpr' env topExpr++-- | Evaluate an Egison top expression.+evalTopExprStr :: Env -> TopExpr -> EvalM (Maybe String, Env)+evalTopExprStr env topExpr = do+ (val, env') <- evalTopExpr env topExpr+ case val of+ Nothing -> return (Nothing, env')+ Just val -> do str <- valueToStr val+ return (Just str, env')++valueToStr :: EgisonValue -> EvalM String+valueToStr val = do+ mathExpr <- asks optMathExpr+ case mathExpr of+ Nothing -> return (show val)+ Just lang -> return (prettyMath lang val)++-- | Evaluate Egison top expressions.+evalTopExprs :: Env -> [TopExpr] -> EvalM Env+evalTopExprs env exprs = do+ exprs <- desugarTopExprs exprs+ opts <- ask+ (bindings, rest) <- collectDefs opts exprs+ env <- recursiveBind env bindings+ forM_ rest $ \expr -> do+ (val, _) <- evalTopExpr' env expr+ case val of+ Nothing -> return ()+ Just val -> valueToStr val >>= liftIO . putStrLn+ return env++-- | Evaluate Egison top expressions.+evalTopExprsNoPrint :: Env -> [TopExpr] -> EvalM Env+evalTopExprsNoPrint env exprs = do+ exprs <- desugarTopExprs exprs+ opts <- ask+ (bindings, rest) <- collectDefs opts exprs+ env <- recursiveBind env bindings+ forM_ rest $ evalTopExpr' env+ return env++-- | Evaluate an Egison expression. Input is a Haskell string.+runExpr :: Env -> String -> EvalM EgisonValue+runExpr env input =+ readExpr input >>= evalExpr env++-- | Evaluate an Egison top expression. Input is a Haskell string.+runTopExpr :: Env -> String -> EvalM (Maybe EgisonValue, Env)+runTopExpr env input =+ readTopExpr input >>= evalTopExpr env++-- | Evaluate Egison top expressions. Input is a Haskell string.+runTopExprs :: Env -> String -> EvalM Env+runTopExprs env input =+ readTopExprs input >>= evalTopExprs env++-- | Load an Egison file.+loadEgisonFile :: Env -> FilePath -> EvalM Env+loadEgisonFile env path = do+ (_, env') <- evalTopExpr env (LoadFile path)+ return env'++-- | Load an Egison library.+loadEgisonLibrary :: Env -> FilePath -> EvalM Env+loadEgisonLibrary env path = do+ (_, env') <- evalTopExpr env (Load path)+ return env'+++--+-- Helper functions+--++collectDefs :: EgisonOpts -> [ITopExpr] -> EvalM ([(Var, IExpr)], [ITopExpr])+collectDefs opts exprs = collectDefs' opts exprs [] []+ where+ collectDefs' :: EgisonOpts -> [ITopExpr] -> [(Var, IExpr)] -> [ITopExpr] -> EvalM ([(Var, IExpr)], [ITopExpr])+ collectDefs' opts (expr:exprs) bindings rest =+ case expr of+ IDefine name expr -> collectDefs' opts exprs ((name, expr) : bindings) rest+ ITest{} -> collectDefs' opts exprs bindings (expr : rest)+ IExecute{} -> collectDefs' opts exprs bindings (expr : rest)+ ILoadFile _ | optNoIO opts -> throwError (Default "No IO support")+ ILoadFile file -> do+ exprs' <- loadFile file >>= desugarTopExprs+ collectDefs' opts (exprs' ++ exprs) bindings rest+ ILoad _ | optNoIO opts -> throwError (Default "No IO support")+ ILoad file -> do+ exprs' <- loadLibraryFile file >>= desugarTopExprs+ collectDefs' opts (exprs' ++ exprs) bindings rest+ collectDefs' _ [] bindings rest = return (bindings, reverse rest)++evalTopExpr' :: Env -> ITopExpr -> EvalM (Maybe EgisonValue, Env)+evalTopExpr' env (IDefine name expr) = do+ env' <- recursiveBind env [(name, expr)]+ return (Nothing, env')+evalTopExpr' env (ITest expr) = do+ pushFuncName "<stdin>"+ val <- evalExprDeep env expr+ popFuncName+ return (Just val, env)+evalTopExpr' env (IExecute expr) = do+ pushFuncName "<stdin>"+ io <- evalExprShallow env expr+ case io of+ Value (IOFunc m) -> m >> popFuncName >> return (Nothing, env)+ _ -> throwError =<< TypeMismatch "io" io <$> getFuncNameStack+evalTopExpr' env (ILoad file) = do+ opts <- ask+ when (optNoIO opts) $ throwError (Default "No IO support")+ exprs <- loadLibraryFile file >>= desugarTopExprs+ (bindings, _) <- collectDefs opts exprs+ env' <- recursiveBind env bindings+ return (Nothing, env')+evalTopExpr' env (ILoadFile file) = do+ opts <- ask+ when (optNoIO opts) $ throwError (Default "No IO support")+ exprs <- loadFile file >>= desugarTopExprs+ (bindings, _) <- collectDefs opts exprs+ env' <- recursiveBind env bindings+ return (Nothing, env')
+ hs-src/Language/Egison/EvalState.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE FlexibleInstances #-}++{- |+Module : Language.Egison.EvalState+Licence : MIT++This module defines the state during the evaluation.+-}++module Language.Egison.EvalState+ ( EvalState(..)+ , initialEvalState+ , MonadEval(..)+ , mLabelFuncName+ ) where++import Control.Monad.Except+import Control.Monad.Trans.State.Strict+++newtype EvalState = EvalState+ -- Names of called functions for improved error message+ { funcNameStack :: [String]+ }++initialEvalState :: EvalState+initialEvalState = EvalState { funcNameStack = [] }++class (Applicative m, Monad m) => MonadEval m where+ pushFuncName :: String -> m ()+ topFuncName :: m String+ popFuncName :: m ()+ getFuncNameStack :: m [String]++instance Monad m => MonadEval (StateT EvalState m) where+ pushFuncName name = do+ st <- get+ put $ st { funcNameStack = name : funcNameStack st }+ return ()+ topFuncName = head . funcNameStack <$> get+ popFuncName = do+ st <- get+ put $ st { funcNameStack = tail $ funcNameStack st }+ return ()+ getFuncNameStack = funcNameStack <$> get++instance (MonadEval m) => MonadEval (ExceptT e m) where+ pushFuncName name = lift $ pushFuncName name+ topFuncName = lift topFuncName+ popFuncName = lift popFuncName+ getFuncNameStack = lift getFuncNameStack++mLabelFuncName :: MonadEval m => Maybe String -> m a -> m a+mLabelFuncName Nothing m = m+mLabelFuncName (Just name) m = do+ pushFuncName name+ v <- m+ popFuncName+ return v
+ hs-src/Language/Egison/IExpr.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE FlexibleInstances #-}++{- |+Module : Language.Egison.IExpr+Licence : MIT++This module defines internal representation of Egison language.+-}++module Language.Egison.IExpr+ ( ITopExpr (..)+ , IExpr (..)+ , IPattern (..)+ , ILoopRange (..)+ , IBindingExpr+ , IMatchClause+ , IPatternDef+ , IPrimitiveDataPattern+ , Var (..)+ , stringToVar+ , Index (..)+ , extractSupOrSubIndex+ , extractIndex+ , makeIApply+ -- Re-export from AST+ , ConstantExpr (..)+ , PMMode (..)+ , PrimitivePatPattern (..)+ , PDPatternBase (..)+ ) where++import Data.Hashable (Hashable)+import GHC.Generics (Generic)++import Language.Egison.AST ( ConstantExpr (..)+ , PMMode (..)+ , PrimitivePatPattern (..)+ , PDPatternBase (..)+ )++data ITopExpr+ = IDefine Var IExpr+ | ITest IExpr+ | IExecute IExpr+ | ILoadFile String+ | ILoad String+ deriving Show++data IExpr+ = IConstantExpr ConstantExpr+ | IVarExpr String+ | IIndexedExpr Bool IExpr [Index IExpr]+ | ISubrefsExpr Bool IExpr IExpr+ | ISuprefsExpr Bool IExpr IExpr+ | IUserrefsExpr Bool IExpr IExpr+ | IInductiveDataExpr String [IExpr]+ | ITupleExpr [IExpr]+ | ICollectionExpr [IExpr]+ | IConsExpr IExpr IExpr+ | IJoinExpr IExpr IExpr+ | IHashExpr [(IExpr, IExpr)]+ | IVectorExpr [IExpr]+ | ILambdaExpr (Maybe String) [String] IExpr+ | IMemoizedLambdaExpr [String] IExpr+ | ICambdaExpr String IExpr+ | IPatternFunctionExpr [String] IPattern+ | IIfExpr IExpr IExpr IExpr+ | ILetRecExpr [IBindingExpr] IExpr+ | ILetExpr [IBindingExpr] IExpr+ | IWithSymbolsExpr [String] IExpr+ | IMatchExpr PMMode IExpr IExpr [IMatchClause]+ | IMatchAllExpr PMMode IExpr IExpr [IMatchClause]+ | IMatcherExpr [IPatternDef]+ | IQuoteExpr IExpr+ | IQuoteSymbolExpr IExpr+ | IWedgeApplyExpr IExpr [IExpr]+ | IDoExpr [IBindingExpr] IExpr+ | ISeqExpr IExpr IExpr+ | IApplyExpr IExpr [IExpr]+ | ICApplyExpr IExpr IExpr+ | IGenerateTensorExpr IExpr IExpr+ | ITensorExpr IExpr IExpr+ | ITensorContractExpr IExpr+ | ITensorMapExpr IExpr IExpr+ | ITensorMap2Expr IExpr IExpr IExpr+ | ITransposeExpr IExpr IExpr+ | IFlipIndicesExpr IExpr+ | IFunctionExpr [String]+ deriving Show++type IBindingExpr = (IPrimitiveDataPattern, IExpr)+type IMatchClause = (IPattern, IExpr)+type IPatternDef = (PrimitivePatPattern, IExpr, [(IPrimitiveDataPattern, IExpr)])+type IPrimitiveDataPattern = PDPatternBase Var++data IPattern+ = IWildCard+ | IPatVar String+ | IValuePat IExpr+ | IPredPat IExpr+ | IIndexedPat IPattern [IExpr]+ | ILetPat [IBindingExpr] IPattern+ | INotPat IPattern+ | IAndPat IPattern IPattern+ | IOrPat IPattern IPattern+ | IForallPat IPattern IPattern+ | ITuplePat [IPattern]+ | IInductivePat String [IPattern]+ | ILoopPat String ILoopRange IPattern IPattern+ | IContPat+ | IPApplyPat IExpr [IPattern]+ | IVarPat String+ | IInductiveOrPApplyPat String [IPattern]+ | ISeqNilPat+ | ISeqConsPat IPattern IPattern+ | ILaterPatVar+ -- For symbolic computing+ | IDApplyPat IPattern [IPattern]+ deriving Show++data ILoopRange = ILoopRange IExpr IExpr IPattern+ deriving Show++data Index a+ = Sub a+ | Sup a+ | SupSub a+ | User a+ | DF Integer Integer+ deriving (Show, Eq, Functor, Foldable, Generic, Traversable)++extractSupOrSubIndex :: Index a -> Maybe a+extractSupOrSubIndex (Sub x) = Just x+extractSupOrSubIndex (Sup x) = Just x+extractSupOrSubIndex (SupSub x) = Just x+extractSupOrSubIndex _ = Nothing++extractIndex :: Index a -> a+extractIndex (Sub x) = x+extractIndex (Sup x) = x+extractIndex (SupSub x) = x+extractIndex (User x) = x+extractIndex DF{} = undefined++data Var = Var String [Index ()]+ deriving (Eq, Generic, Show)++instance Hashable (Index ())+instance Hashable Var++stringToVar :: String -> Var+stringToVar name = Var name []++makeIApply :: String -> [IExpr] -> IExpr+makeIApply func args = IApplyExpr (IVarExpr func) args++instance {-# OVERLAPPING #-} Show (Index String) where+ show (Sup s) = "~" ++ s+ show (Sub s) = "_" ++ s+ show (SupSub s) = "~_" ++ s+ show (User s) = "|" ++ s+ show (DF _ _) = ""
− hs-src/Language/Egison/IState.hs
@@ -1,66 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}--{- |-Module : Language.Egison.IState-Licence : MIT--This module defines the internal state of Egison runtime.--}--module Language.Egison.IState- ( IState(..)- , MonadEval(..)- , modifyCounter- ) where--import Control.Monad.Except-import Control.Monad.State-import Data.IORef--import System.IO.Unsafe (unsafePerformIO)--import Language.Egison.AST---data IState = IState- -- Index counter for generating fresh variable- { indexCounter :: Int- -- Names of called functions for improved error message- , funcNameStack :: [String]- }--class (Applicative m, Monad m) => MonadEval m where- fresh :: m String- freshV :: m Var- pushFuncName :: String -> m ()- topFuncName :: m String- popFuncName :: m ()- getFuncNameStack :: m [String]--instance (MonadEval m) => MonadEval (ExceptT e m) where- fresh = lift fresh- freshV = lift freshV- pushFuncName name = lift $ pushFuncName name- topFuncName = lift topFuncName- popFuncName = lift popFuncName- getFuncNameStack = lift getFuncNameStack--{-# NOINLINE counter #-}-counter :: IORef Int-counter = unsafePerformIO $ newIORef 0--readCounter :: IO Int-readCounter = readIORef counter--updateCounter :: Int -> IO ()-updateCounter = writeIORef counter--modifyCounter :: MonadIO m => StateT IState m a -> m a-modifyCounter m = do- x <- liftIO $ readCounter- (result, st) <- runStateT m (IState { indexCounter = x, funcNameStack = [] })- liftIO $ updateCounter $ indexCounter st- return result
+ hs-src/Language/Egison/Match.hs view
@@ -0,0 +1,67 @@+{- |+Module : Language.Egison.Match+Licence : MIT++This module defines some data types Egison pattern matching.+-}++module Language.Egison.Match+ ( Match+ , MatchingTree (..)+ , MatchingState (..)+ , PatternBinding+ , LoopPatContext (..)+ , SeqPatContext (..)+ , nullMState+ , MatchM+ , matchFail+ ) where++import Control.Monad.Trans.Maybe++import Language.Egison.Data+import Language.Egison.IExpr++--+-- Pattern Matching+--++type Match = [Binding]++data MatchingState+ = MState { mStateEnv :: Env+ , loopPatCtx :: [LoopPatContext]+ , seqPatCtx :: [SeqPatContext]+ , mStateBindings :: [Binding]+ , mTrees :: [MatchingTree]+ }++instance Show MatchingState where+ show ms = "(MState " ++ unwords ["_", "_", "_", show (mStateBindings ms), show (mTrees ms)] ++ ")" ++data MatchingTree+ = MAtom IPattern WHNFData Matcher+ | MNode [PatternBinding] MatchingState+ deriving Show++type PatternBinding = (String, IPattern)++data LoopPatContext = LoopPatContext (String, ObjectRef) ObjectRef IPattern IPattern IPattern++data SeqPatContext+ = SeqPatContext [MatchingTree] IPattern [Matcher] [WHNFData]+ | ForallPatContext [Matcher] [WHNFData]++nullMState :: MatchingState -> Bool+nullMState MState{ mTrees = [] } = True+nullMState MState{ mTrees = MNode _ state : _ } = nullMState state+nullMState _ = False++--+-- Monads+--++type MatchM = MaybeT EvalM++matchFail :: MatchM a+matchFail = MaybeT $ return Nothing
+ hs-src/Language/Egison/Math.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE PatternSynonyms #-}++{- |+Module : Language.Egison.Math+Licence : MIT++This module provides the interface of Egison's computer algebra system.+-}++module Language.Egison.Math+ ( ScalarData (..)+ , PolyExpr (..)+ , TermExpr (..)+ , Monomial+ , SymbolExpr (..)+ , Printable (..)+ , pattern ZeroExpr+ , pattern SingleSymbol+ , pattern SingleTerm+ , mathNormalize'+ , rewriteSymbol+ , mathPlus+ , mathMult+ , mathDiv+ , mathNumerator+ , mathDenominator+ , mathNegate+ ) where++import Language.Egison.Math.Expr+import Language.Egison.Math.Arith+import Language.Egison.Math.Normalize+import Language.Egison.Math.Rewrite
+ hs-src/Language/Egison/Math/Arith.hs view
@@ -0,0 +1,51 @@+{- |+Module : Language.Egison.Math.Arith+Licence : MIT++This module defines some basic arithmetic operations for Egison's computer+algebra system.+-}++module Language.Egison.Math.Arith+ ( mathPlus+ , mathMinus+ , mathMult+ , mathDiv+ , mathPower+ , mathNumerator+ , mathDenominator+ ) where++import Language.Egison.Math.Expr+import Language.Egison.Math.Normalize++mathPlus :: ScalarData -> ScalarData -> ScalarData+mathPlus (Div m1 n1) (Div m2 n2) = mathNormalize' $ Div (mathPlusPoly (mathMultPoly m1 n2) (mathMultPoly m2 n1)) (mathMultPoly n1 n2)++mathPlusPoly :: PolyExpr -> PolyExpr -> PolyExpr+mathPlusPoly (Plus ts1) (Plus ts2) = Plus (ts1 ++ ts2)++mathMinus :: ScalarData -> ScalarData -> ScalarData+mathMinus s1 s2 = mathPlus s1 (mathNegate s2)++mathMult :: ScalarData -> ScalarData -> ScalarData+mathMult (Div m1 n1) (Div m2 n2) = mathNormalize' $ Div (mathMultPoly m1 m2) (mathMultPoly n1 n2)++mathMultPoly :: PolyExpr -> PolyExpr -> PolyExpr+mathMultPoly (Plus []) (Plus _) = Plus []+mathMultPoly (Plus _) (Plus []) = Plus []+mathMultPoly (Plus ts1) (Plus ts2) = foldl mathPlusPoly (Plus []) (map (\(Term a xs) -> Plus (map (\(Term b ys) -> Term (a * b) (xs ++ ys)) ts2)) ts1)++mathDiv :: ScalarData -> ScalarData -> ScalarData+mathDiv s (Div p1 p2) = mathMult s (Div p2 p1)++mathPower :: ScalarData -> Integer -> ScalarData+mathPower _ 0 = SingleTerm 1 []+mathPower s 1 = s+mathPower s n | n >= 2 = mathMult s (mathPower s (n - 1))++mathNumerator :: ScalarData -> ScalarData+mathNumerator (Div m _) = Div m (Plus [Term 1 []])++mathDenominator :: ScalarData -> ScalarData+mathDenominator (Div _ n) = Div n (Plus [Term 1 []])
+ hs-src/Language/Egison/Math/Expr.hs view
@@ -0,0 +1,281 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE QuasiQuotes #-}++{- |+Module : Language.Egison.Math.Expr+Licence : MIT++This module defines the internal representation of mathematic objects such as+polynominals, and some useful patterns.+-}++module Language.Egison.Math.Expr+ ( ScalarData (..)+ , PolyExpr (..)+ , TermExpr (..)+ , Monomial+ , SymbolExpr (..)+ , Printable (..)+ , pattern ZeroExpr+ , pattern SingleSymbol+ , pattern SingleTerm+ , ScalarM (..)+ , TermM (..)+ , SymbolM (..)+ , term+ , termM+ , symbol+ , symbolM+ , func+ , funcM+ , apply+ , applyM+ , quote+ , negQuote+ , negQuoteM+ , equalMonomial+ , equalMonomialM+ , zero+ , zeroM+ , singleTerm+ , singleTermM+ , mathScalarMult+ , mathNegate+ ) where++import Prelude hiding (foldr, mappend, mconcat)+import Data.List (intercalate)++import Control.Monad ( MonadPlus(..) )+import Control.Egison++import Language.Egison.IExpr (Index(..))++--+-- Data+--+++data ScalarData+ = Div PolyExpr PolyExpr+ deriving Eq++newtype PolyExpr+ = Plus [TermExpr]++data TermExpr+ = Term Integer Monomial++-- We choose the definition 'monomials' without its coefficients.+-- ex. 2 x^2 y^3 is *not* a monomial. x^2 t^3 is a monomial.+type Monomial = [(SymbolExpr, Integer)]++data SymbolExpr+ = Symbol Id String [Index ScalarData]+ | Apply ScalarData [ScalarData]+ | Quote ScalarData+ | FunctionData ScalarData [ScalarData] [ScalarData] [Index ScalarData] -- fnname argnames args indices+ deriving Eq++type Id = String++-- Matchers++data ScalarM = ScalarM+instance Matcher ScalarM ScalarData++data TermM = TermM+instance Matcher TermM TermExpr++data SymbolM = SymbolM+instance Matcher SymbolM SymbolExpr++term :: Pattern (PP Integer, PP Monomial) TermM TermExpr (Integer, Monomial)+term _ _ (Term a mono) = pure (a, mono)+termM :: TermM -> TermExpr -> (Eql, Multiset (Pair SymbolM Eql))+termM TermM _ = (Eql, Multiset (Pair SymbolM Eql))++symbol :: Pattern (PP String) SymbolM SymbolExpr String+symbol _ _ (Symbol _ name []) = pure name+symbol _ _ _ = mzero+symbolM :: SymbolM -> p -> Eql+symbolM SymbolM _ = Eql++func :: Pattern (PP ScalarData, PP [ScalarData], PP [Index ScalarData])+ SymbolM SymbolExpr (ScalarData, [ScalarData], [Index ScalarData])+func _ _ (FunctionData name _ args js) = pure (name, args, js)+func _ _ _ = mzero+funcM :: SymbolM -> SymbolExpr -> (ScalarM, List ScalarM, Multiset Eql)+funcM SymbolM _ = (ScalarM, List ScalarM, Multiset Eql)++apply :: Pattern (PP String, PP [ScalarData]) SymbolM SymbolExpr (String, [ScalarData])+apply _ _ (Apply (SingleSymbol (Symbol _ fn _)) args) = pure (fn, args)+apply _ _ _ = mzero+applyM :: SymbolM -> p -> (Eql, List ScalarM)+applyM SymbolM _ = (Eql, List ScalarM)++quote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData+quote _ _ (Quote m) = pure m+quote _ _ _ = mzero++negQuote :: Pattern (PP ScalarData) SymbolM SymbolExpr ScalarData+negQuote _ _ (Quote m) = pure (mathNegate m)+negQuote _ _ _ = mzero+negQuoteM :: SymbolM -> p -> ScalarM+negQuoteM SymbolM _ = ScalarM++equalMonomial :: Pattern (PP Integer, PP Monomial) (Multiset (Pair SymbolM Eql)) Monomial (Integer, Monomial)+equalMonomial (_, VP xs) _ ys = case isEqualMonomial xs ys of+ Just sgn -> pure (sgn, xs)+ Nothing -> mzero+equalMonomial _ _ _ = mzero+equalMonomialM :: Multiset (Pair SymbolM Eql) -> p -> (Eql, Multiset (Pair SymbolM Eql))+equalMonomialM (Multiset (Pair SymbolM Eql)) _ = (Eql, Multiset (Pair SymbolM Eql))++zero :: Pattern () ScalarM ScalarData ()+zero _ _ (Div (Plus []) _) = pure ()+zero _ _ _ = mzero+zeroM :: ScalarM -> p -> ()+zeroM ScalarM _ = ()++singleTerm :: Pattern (PP Integer, PP Integer, PP Monomial) ScalarM ScalarData (Integer, Integer, Monomial)+singleTerm _ _ (Div (Plus [Term c mono]) (Plus [Term c2 []])) = pure (c, c2, mono)+singleTerm _ _ _ = mzero+singleTermM :: ScalarM -> p -> (Eql, Eql, Multiset (Pair SymbolM Eql))+singleTermM ScalarM _ = (Eql, Eql, Multiset (Pair SymbolM Eql))+++instance ValuePattern ScalarM ScalarData where+ value e () ScalarM v = if e == v then pure () else mzero++instance ValuePattern SymbolM SymbolExpr where+ value e () SymbolM v = if e == v then pure () else mzero+++pattern ZeroExpr :: ScalarData+pattern ZeroExpr = (Div (Plus []) (Plus [Term 1 []]))++pattern SingleSymbol :: SymbolExpr -> ScalarData+pattern SingleSymbol sym = Div (Plus [Term 1 [(sym, 1)]]) (Plus [Term 1 []])++-- Product of a coefficient and a monomial+pattern SingleTerm :: Integer -> Monomial -> ScalarData+pattern SingleTerm coeff mono = Div (Plus [Term coeff mono]) (Plus [Term 1 []])++instance Eq PolyExpr where+ Plus xs == Plus ys =+ match dfs ys (Multiset Eql)+ [ [mc| #xs -> True |]+ , [mc| _ -> False |] ]++instance Eq TermExpr where+ Term a xs == Term b ys+ | a == b = isEqualMonomial xs ys == Just 1+ | a == -b = isEqualMonomial xs ys == Just (-1)+ | otherwise = False++isEqualMonomial :: Monomial -> Monomial -> Maybe Integer+isEqualMonomial xs ys =+ match dfs (xs, ys) (Pair (Multiset (Pair SymbolM Eql)) (Multiset (Pair SymbolM Eql)))+ [ [mc| ((quote $s, $n) : $xss, (negQuote #s, #n) : $yss) ->+ case isEqualMonomial xss yss of+ Nothing -> Nothing+ Just sgn -> return (if even n then sgn else - sgn) |]+ , [mc| (($x, $n) : $xss, (#x, #n) : $yss) -> isEqualMonomial xss yss |]+ , [mc| ([], []) -> return 1 |]+ , [mc| _ -> Nothing |]+ ]++--+-- Arithmetic operations+--++mathScalarMult :: Integer -> ScalarData -> ScalarData+mathScalarMult c (Div m n) = Div (f c m) n+ where+ f c (Plus ts) = Plus (map (\(Term a xs) -> Term (c * a) xs) ts)++mathNegate :: ScalarData -> ScalarData+mathNegate = mathScalarMult (-1)++--+-- Pretty printing+--++class Printable a where+ isAtom :: a -> Bool+ pretty :: a -> String++pretty' :: Printable a => a -> String+pretty' e | isAtom e = pretty e+pretty' e = "(" ++ pretty e ++ ")"++instance Printable ScalarData where+ isAtom (Div p (Plus [Term 1 []])) = isAtom p+ isAtom _ = False++ pretty (Div p1 (Plus [Term 1 []])) = pretty p1+ pretty (Div p1 p2) = pretty'' p1 ++ " / " ++ pretty' p2+ where+ pretty'' :: PolyExpr -> String+ pretty'' p@(Plus [_]) = pretty p+ pretty'' p = "(" ++ pretty p ++ ")"++instance Printable PolyExpr where+ isAtom (Plus []) = True+ isAtom (Plus [Term _ []]) = True+ isAtom (Plus [Term 1 [_]]) = True+ isAtom _ = False++ pretty (Plus []) = "0"+ pretty (Plus (t:ts)) = pretty t ++ concatMap withSign ts+ where+ withSign (Term a xs) | a < 0 = " - " ++ pretty (Term (- a) xs)+ withSign t = " + " ++ pretty t++instance Printable SymbolExpr where+ isAtom Symbol{} = True+ isAtom (Apply _ []) = True+ isAtom _ = False++ pretty (Symbol _ (':':':':':':_) []) = "#"+ pretty (Symbol _ s []) = s+ pretty (Symbol _ s js) = s ++ concatMap show js+ pretty (Apply fn mExprs) = unwords (map pretty' (fn : mExprs))+ pretty (Quote mExprs) = "'" ++ pretty' mExprs+ pretty (FunctionData name _ _ js) = pretty name ++ concatMap show js++instance Printable TermExpr where+ isAtom (Term _ []) = True+ isAtom (Term 1 [_]) = True+ isAtom _ = False++ pretty (Term a []) = show a+ pretty (Term 1 xs) = intercalate " * " (map prettyPoweredSymbol xs)+ pretty (Term (-1) xs) = "- " ++ intercalate " * " (map prettyPoweredSymbol xs)+ pretty (Term a xs) = intercalate " * " (show a : map prettyPoweredSymbol xs)++prettyPoweredSymbol :: (SymbolExpr, Integer) -> String+prettyPoweredSymbol (x, 1) = show x+prettyPoweredSymbol (x, n) = pretty' x ++ "^" ++ show n++instance Show ScalarData where+ show = pretty++instance Show PolyExpr where+ show = pretty++instance Show TermExpr where+ show = pretty++instance Show SymbolExpr where+ show = pretty++instance {-# OVERLAPPING #-} Show (Index ScalarData) where+ show (Sup i) = "~" ++ pretty' i+ show (Sub i) = "_" ++ pretty' i+ show (SupSub i) = "~_" ++ pretty' i+ show (DF _ _) = ""+ show (User i) = "|" ++ pretty' i
+ hs-src/Language/Egison/Math/Normalize.hs view
@@ -0,0 +1,128 @@+{-# LANGUAGE QuasiQuotes #-}++{- |+Module : Language.Egison.Math.Expr+Licence : MIT++This module implements the normalization of polynomials. Normalization rules+for particular mathematical functions (such as sqrt and sin/cos) are defined+in Rewrite.hs.+-}++module Language.Egison.Math.Normalize+ ( mathNormalize'+ , termsGcd+ , mathDivideTerm+ ) where++import Control.Egison++import Language.Egison.Math.Expr+++mathNormalize' :: ScalarData -> ScalarData+mathNormalize' = mathDivide . mathRemoveZero . mathFold . mathRemoveZeroSymbol++termsGcd :: [TermExpr] -> TermExpr+termsGcd ts@(_:_) =+ foldl1 (\(Term a xs) (Term b ys) -> Term (gcd a b) (monoGcd xs ys)) ts+ where+ monoGcd :: Monomial -> Monomial -> Monomial+ monoGcd [] _ = []+ monoGcd ((x, n):xs) ys =+ case f (x, n) ys of+ (_, 0) -> monoGcd xs ys+ (z, m) -> (z, m) : monoGcd xs ys++ f :: (SymbolExpr, Integer) -> Monomial -> (SymbolExpr, Integer)+ f (x, _) [] = (x, 0)+ f (Quote x, n) ((Quote y, m):ys)+ | x == y = (Quote x, min n m)+ | x == mathNegate y = (Quote x, min n m)+ | otherwise = f (Quote x, n) ys+ f (x, n) ((y, m):ys)+ | x == y = (x, min n m)+ | otherwise = f (x, n) ys++mathDivide :: ScalarData -> ScalarData+mathDivide mExpr@(Div (Plus _) (Plus [])) = mExpr+mathDivide mExpr@(Div (Plus []) (Plus _)) = mExpr+mathDivide (Div (Plus ts1) (Plus ts2)) =+ let z@(Term c zs) = termsGcd (ts1 ++ ts2) in+ case ts2 of+ [Term a _] | a < 0 -> Div (Plus (map (`mathDivideTerm` Term (-c) zs) ts1))+ (Plus (map (`mathDivideTerm` Term (-c) zs) ts2))+ _ -> Div (Plus (map (`mathDivideTerm` z) ts1))+ (Plus (map (`mathDivideTerm` z) ts2))++mathDivideTerm :: TermExpr -> TermExpr -> TermExpr+mathDivideTerm (Term a xs) (Term b ys) =+ let (sgn, zs) = divMonomial xs ys in+ Term (sgn * div a b) zs+ where+ divMonomial :: Monomial -> Monomial -> (Integer, Monomial)+ divMonomial xs [] = (1, xs)+ divMonomial xs ((y, m):ys) =+ match dfs (y, xs) (Pair SymbolM (Multiset (Pair SymbolM Eql)))+ -- Because we've applied |mathFold|, we can only divide the first matching monomial+ [ [mc| (quote $s, ($x & negQuote #s, $n) : $xss) ->+ let (sgn, xs') = divMonomial xss ys in+ let sgn' = if even m then 1 else -1 in+ if n == m then (sgn * sgn', xs')+ else (sgn * sgn', (x, n - m) : xs') |]+ , [mc| (_, (#y, $n) : $xss) ->+ let (sgn, xs') = divMonomial xss ys in+ if n == m then (sgn, xs') else (sgn, (y, n - m) : xs') |]+ , [mc| _ -> divMonomial xs ys |]+ ]++mathRemoveZeroSymbol :: ScalarData -> ScalarData+mathRemoveZeroSymbol (Div (Plus ts1) (Plus ts2)) =+ let ts1' = map (\(Term a xs) -> Term a (filter p xs)) ts1+ ts2' = map (\(Term a xs) -> Term a (filter p xs)) ts2+ in Div (Plus ts1') (Plus ts2')+ where+ p (_, 0) = False+ p _ = True++mathRemoveZero :: ScalarData -> ScalarData+mathRemoveZero (Div (Plus ts1) (Plus ts2)) =+ let ts1' = filter (\(Term a _) -> a /= 0) ts1 in+ let ts2' = filter (\(Term a _) -> a /= 0) ts2 in+ case ts1' of+ [] -> Div (Plus []) (Plus [Term 1 []])+ _ -> Div (Plus ts1') (Plus ts2')++mathFold :: ScalarData -> ScalarData+mathFold = mathTermFold . mathSymbolFold++-- x^2 y x -> x^3 y+mathSymbolFold :: ScalarData -> ScalarData+mathSymbolFold (Div (Plus ts1) (Plus ts2)) = Div (Plus (map f ts1)) (Plus (map f ts2))+ where+ f :: TermExpr -> TermExpr+ f (Term a xs) =+ let (sgn, ys) = g xs in Term (sgn * a) ys+ g :: Monomial -> (Integer, Monomial)+ g [] = (1, [])+ g ((x, m):xs) =+ match dfs (x, xs) (Pair SymbolM (Multiset (Pair SymbolM Eql)))+ [ [mc| (quote $s, (negQuote #s, $n) : $xs) ->+ let (sgn, ys) = g ((x, m + n) : xs) in+ if even n then (sgn, ys) else (- sgn, ys) |]+ , [mc| (_, (#x, $n) : $xs) -> g ((x, m + n) : xs) |]+ , [mc| _ -> let (sgn', ys) = g xs in (sgn', (x, m):ys) |]+ ]++-- x^2 y + x^2 y -> 2 x^2 y+mathTermFold :: ScalarData -> ScalarData+mathTermFold (Div (Plus ts1) (Plus ts2)) = Div (Plus (f ts1)) (Plus (f ts2))+ where+ f :: [TermExpr] -> [TermExpr]+ f [] = []+ f (t:ts) =+ match dfs (t, ts) (Pair TermM (Multiset TermM))+ [ [mc| (term $a $xs, term $b ($ys & equalMonomial $sgn #xs) : $tss) ->+ f (Term (sgn * a + b) ys : tss) |]+ , [mc| _ -> t : f ts |]+ ]
+ hs-src/Language/Egison/Math/Rewrite.hs view
@@ -0,0 +1,208 @@+{-# LANGUAGE QuasiQuotes #-}++{- |+Module : Language.Egison.Math.Rewrite+Licence : MIT++This module implements rewrite rules for common mathematical functions.+-}++module Language.Egison.Math.Rewrite+ ( rewriteSymbol+ ) where++import Control.Egison++import Language.Egison.Math.Arith+import Language.Egison.Math.Expr+import Language.Egison.Math.Normalize+++rewriteSymbol :: ScalarData -> ScalarData+rewriteSymbol =+ foldl1 (\acc f -> f . acc)+ [ rewriteI+ , rewriteW+ , rewriteLog+ , rewriteSinCos+ , rewriteExp+ , rewritePower+ , rewriteSqrt+ , rewriteRt+ , rewriteRtu+ , rewriteDd+ ]++mapTerms :: (TermExpr -> TermExpr) -> ScalarData -> ScalarData+mapTerms f (Div (Plus ts1) (Plus ts2)) =+ Div (Plus (map f ts1)) (Plus (map f ts2))++mapTerms' :: (TermExpr -> ScalarData) -> ScalarData -> ScalarData+mapTerms' f (Div (Plus ts1) (Plus ts2)) =+ mathDiv (foldl1 mathPlus (map f ts1)) (foldl1 mathPlus (map f ts2))++mapPolys :: (PolyExpr -> PolyExpr) -> ScalarData -> ScalarData+mapPolys f (Div p1 p2) = Div (f p1) (f p2)++rewriteI :: ScalarData -> ScalarData+rewriteI = mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (symbol #"i", $k) : $xss ->+ if even k+ then Term (a * (-1) ^ (quot k 2)) xss+ else Term (a * (-1) ^ (quot k 2)) ((Symbol "" "i" [], 1) : xss) |]+ , [mc| _ -> term |]+ ]++rewriteW :: ScalarData -> ScalarData+rewriteW = mapPolys g . mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (symbol #"w", $k & ?(>= 3)) : $xss ->+ Term a ((Symbol "" "w" [], k `mod` 3) : xss) |]+ , [mc| _ -> term |]+ ]+ g poly@(Plus ts) =+ match dfs ts (Multiset TermM)+ [ [mc| term $a ((symbol #"w", #2) : $mr) :+ term $b ((symbol #"w", #1) : #mr) : $pr ->+ g (Plus (Term (-a) mr :+ Term (b - a) ((Symbol "" "w" [], 1) : mr) : pr)) |]+ , [mc| _ -> poly |]+ ]++rewriteLog :: ScalarData -> ScalarData+rewriteLog = mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"log" [zero], _) : _ -> Term 0 [] |]+ , [mc| (apply #"log" [singleTerm _ #1 [(symbol #"e", $n)]], _) : $xss ->+ Term (n * a) xss |]+ , [mc| _ -> term |]+ ]++makeApply :: String -> [ScalarData] -> SymbolExpr+makeApply f args =+ Apply (SingleSymbol (Symbol "" f [])) args++rewriteExp :: ScalarData -> ScalarData+rewriteExp = mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"exp" [zero], _) : $xss ->+ f (Term a xss) |]+ , [mc| (apply #"exp" [singleTerm #1 #1 []], _) : $xss ->+ f (Term a ((Symbol "" "e" [], 1) : xss)) |]+ , [mc| (apply #"exp" [singleTerm $n #1 [(symbol #"i", #1), (symbol #"π", #1)]], _) : $xss ->+ f (Term ((-1) ^ n * a) xss) |]+ , [mc| (apply #"exp" [$x], $n & ?(>= 2)) : $xss ->+ f (Term a ((makeApply "exp" [mathScalarMult n x], 1) : xss)) |]+ , [mc| (apply #"exp" [$x], #1) : (apply #"exp" [$y], #1) : $xss ->+ f (Term a ((makeApply "exp" [mathPlus x y], 1) : xss)) |]+ , [mc| _ -> term |]+ ]++rewritePower :: ScalarData -> ScalarData+rewritePower = mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"^" [singleTerm #1 #1 [], _], _) : $xss -> f (Term a xss) |]+ , [mc| (apply #"^" [$x, $y], $n & ?(>= 2)) : $xss ->+ f (Term a ((makeApply "^" [x, mathScalarMult n y], 1) : xss)) |]+ , [mc| (apply #"^" [$x, $y], #1) : (apply #"^" [#x, $z], #1) : $xss ->+ f (Term a ((makeApply "^" [x, mathPlus y z], 1) : xss)) |]+ , [mc| _ -> term |]+ ]++rewriteSinCos :: ScalarData -> ScalarData+rewriteSinCos = mapTerms' h . mapTerms (g . f)+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"sin" [zero], _) : _ -> Term 0 [] |]+ , [mc| (apply #"sin" [singleTerm _ #1 [(symbol #"π", #1)]], _) : _ ->+ Term 0 [] |]+ , [mc| (apply #"sin" [singleTerm $n #2 [(symbol #"π", #1)]], $m) : $xss ->+ Term (a * (-1) ^ (div (abs n - 1) 2) * m) xss |]+ , [mc| _ -> term |]+ ]+ g term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"cos" [zero], _) : $xss -> Term a xss |]+ , [mc| (apply #"cos" [singleTerm _ #2 [(symbol #"π", #1)]], _) : _ ->+ Term 0 [] |]+ , [mc| (apply #"cos" [singleTerm $n #1 [(symbol #"π", #1)]], $m) : $xss ->+ Term (a * (-1) ^ (abs n * m)) xss |]+ , [mc| _ -> term |]+ ]+ h (Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"cos" [$x], #2) : $mr ->+ mathMult+ (mathMinus (SingleTerm 1 []) (SingleTerm 1 [(makeApply "sin" [x], 2)]))+ (h (Term a mr)) |]+ , [mc| _ -> SingleTerm a xs |]+ ]++rewriteSqrt :: ScalarData -> ScalarData+rewriteSqrt = mapTerms' f+ where+ f (Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"sqrt" [$x], ?(> 1) & $k) : $xss ->+ rewriteSqrt+ (mathMult (SingleTerm a ((makeApply "sqrt" [x], k `mod` 2) : xss))+ (mathPower x (div k 2))) |]+ , [mc| (apply #"sqrt" [singleTerm $n #1 $x], #1) :+ (apply #"sqrt" [singleTerm $m #1 $y], #1) : $xss ->+ let d@(Term c z) = termsGcd [Term n x, Term m y]+ Term n' x' = mathDivideTerm (Term n x) d+ Term m' y' = mathDivideTerm (Term m y) d+ sqrtxy = (if x' == [] then [] else [(makeApply "sqrt" [SingleTerm 1 x'], 1)]) ++ + (if y' == [] then [] else [(makeApply "sqrt" [SingleTerm 1 y'], 1)])+ in mathMult+ (SingleTerm c z)+ (SingleTerm+ a+ ((makeApply "sqrt" [SingleTerm (n' * m') []], 1) : sqrtxy ++ xss)) |]+ , [mc| _ -> SingleTerm a xs |]+ ]++rewriteRt :: ScalarData -> ScalarData+rewriteRt = mapTerms' f+ where+ f (Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"rt" [singleTerm $n #1 [], $x] & $rtnx, ?(>= n) & $k) : $xss ->+ mathMult (SingleTerm a ((rtnx, k `mod` n) : xss))+ (mathPower x (div k n)) |]+ , [mc| _ -> SingleTerm a xs |]+ ]++rewriteRtu :: ScalarData -> ScalarData+rewriteRtu = mapTerms f+ where+ f term@(Term a xs) =+ match dfs xs (Multiset (Pair SymbolM Eql))+ [ [mc| (apply #"rtu" [singleTerm $n #1 []] & $rtun, ?(>= n) & $k) : $r ->+ Term a ((rtun, k `mod` n) : r) |]+ , [mc| _ -> term |]+ ]++rewriteDd :: ScalarData -> ScalarData+rewriteDd (Div (Plus p1) (Plus p2)) =+ Div (Plus (rewriteDdPoly p1)) (Plus (rewriteDdPoly p2))+ where+ rewriteDdPoly poly =+ match dfs poly (Multiset TermM)+ [ [mc| term $a (($f & func $g $arg $js, $n) : $mr) :+ term $b ((func #g #arg #js, #n) : #mr) : $pr ->+ rewriteDdPoly (Term (a + b) ((f, n) : mr) : pr) |]+ , [mc| _ -> poly |]+ ]
− hs-src/Language/Egison/MathExpr.hs
@@ -1,351 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE PatternSynonyms #-}--{- |-Module : Language.Egison.MathExpr-Licence : MIT--This module contains functions for mathematical expressions.--}--module Language.Egison.MathExpr- (- -- * MathExpr Data- ScalarData (..)- , PolyExpr (..)- , TermExpr (..)- , SymbolExpr (..)- , Printable (..)- , pattern ZeroExpr- , pattern SingleSymbol- , pattern SingleTerm- -- * Scalar- , mathNormalize'- , mathFold- , mathSymbolFold- , mathTermFold- , mathRemoveZero- , mathDivide- , mathPlus- , mathMult- , mathNegate- , mathNumerator- , mathDenominator- ) where--import Prelude hiding (foldr, mappend, mconcat)-import Data.List (elemIndex, intercalate)--import Language.Egison.AST------- Data------data ScalarData- = Div PolyExpr PolyExpr- deriving (Eq)--newtype PolyExpr- = Plus [TermExpr]--data TermExpr- = Term Integer Monomial---- We choose the definition 'monomials' without its coefficients.--- ex. 2 x^2 y^3 is *not* a monomial. x^2 t^3 is a monomial.-type Monomial = [(SymbolExpr, Integer)]--data SymbolExpr- = Symbol Id String [Index ScalarData]- | Apply ScalarData [ScalarData]- | Quote ScalarData- | FunctionData ScalarData [ScalarData] [ScalarData] [Index ScalarData] -- fnname argnames args indices- deriving (Eq)--type Id = String--pattern ZeroExpr :: ScalarData-pattern ZeroExpr = (Div (Plus []) (Plus [Term 1 []]))--pattern SingleSymbol :: SymbolExpr -> ScalarData-pattern SingleSymbol sym = Div (Plus [Term 1 [(sym, 1)]]) (Plus [Term 1 []])---- Product of a coefficient and a monomial-pattern SingleTerm :: Integer -> Monomial -> ScalarData-pattern SingleTerm coeff mono = Div (Plus [Term coeff mono]) (Plus [Term 1 []])--instance Eq PolyExpr where- (Plus []) == (Plus []) = True- (Plus (x:xs)) == (Plus ys) =- case elemIndex x ys of- Just i -> let (hs, _:ts) = splitAt i ys in- Plus xs == Plus (hs ++ ts)- Nothing -> False- _ == _ = False--instance Eq TermExpr where- (Term a []) == (Term b []) = a == b- (Term a ((Quote x, n):xs)) == (Term b ys)- | (a /= b) && (a /= -b) = False- | otherwise = case elemIndex (Quote x, n) ys of- Just i -> let (hs, _:ts) = splitAt i ys in- Term a xs == Term b (hs ++ ts)- Nothing -> case elemIndex (Quote (mathNegate x), n) ys of- Just i -> let (hs, _:ts) = splitAt i ys in- if even n- then Term a xs == Term b (hs ++ ts)- else Term (-a) xs == Term b (hs ++ ts)- Nothing -> False- (Term a (x:xs)) == (Term b ys)- | (a /= b) && (a /= -b) = False- | otherwise = case elemIndex x ys of- Just i -> let (hs, _:ts) = splitAt i ys in- Term a xs == Term b (hs ++ ts)- Nothing -> False- _ == _ = False--class Printable a where- isAtom :: a -> Bool- pretty :: a -> String--pretty' :: Printable a => a -> String-pretty' e | isAtom e = pretty e-pretty' e = "(" ++ pretty e ++ ")"--instance Printable ScalarData where- isAtom (Div p (Plus [Term 1 []])) = isAtom p- isAtom _ = False-- pretty (Div p1 (Plus [Term 1 []])) = pretty p1- pretty (Div p1 p2) = pretty'' p1 ++ " / " ++ pretty' p2- where- pretty'' :: PolyExpr -> String- pretty'' p@(Plus [_]) = pretty p- pretty'' p = "(" ++ pretty p ++ ")"--instance Printable PolyExpr where- isAtom (Plus []) = True- isAtom (Plus [Term _ []]) = True- isAtom (Plus [Term 1 [_]]) = True- isAtom _ = False-- pretty (Plus []) = "0"- pretty (Plus (t:ts)) = pretty t ++ concatMap withSign ts- where- withSign (Term a xs) | a < 0 = " - " ++ pretty (Term (- a) xs)- withSign t = " + " ++ pretty t--instance Printable SymbolExpr where- isAtom Symbol{} = True- isAtom (Apply _ []) = True- isAtom _ = False-- pretty (Symbol _ (':':':':':':_) []) = "#"- pretty (Symbol _ s []) = s- pretty (Symbol _ s js) = s ++ concatMap show js- pretty (Apply fn mExprs) = unwords (map pretty' (fn : mExprs))- pretty (Quote mExprs) = "'" ++ pretty' mExprs- pretty (FunctionData name _ _ js) = pretty name ++ concatMap show js--instance Printable TermExpr where- isAtom (Term _ []) = True- isAtom (Term 1 [_]) = True- isAtom _ = False-- pretty (Term a []) = show a- pretty (Term 1 xs) = intercalate " * " (map prettyPoweredSymbol xs)- pretty (Term (-1) xs) = "- " ++ intercalate " * " (map prettyPoweredSymbol xs)- pretty (Term a xs) = intercalate " * " (show a : map prettyPoweredSymbol xs)--prettyPoweredSymbol :: (SymbolExpr, Integer) -> String-prettyPoweredSymbol (x, 1) = show x-prettyPoweredSymbol (x, n) = pretty' x ++ "^" ++ show n--instance Show ScalarData where- show = pretty--instance Show PolyExpr where- show = pretty--instance Show TermExpr where- show = pretty--instance Show SymbolExpr where- show = pretty--instance Show (Index ScalarData) where- show (Superscript i) = "~" ++ pretty' i- show (Subscript i) = "_" ++ pretty' i- show (SupSubscript i) = "~_" ++ pretty' i- show (DFscript _ _) = ""- show (Userscript i) = "|" ++ pretty' i------- Scalars-----mathNormalize' :: ScalarData -> ScalarData-mathNormalize' = mathDivide . mathRemoveZero . mathFold . mathRemoveZeroSymbol--termsGcd :: [TermExpr] -> TermExpr-termsGcd ts@(_:_) =- foldl1 (\(Term a xs) (Term b ys) -> Term (gcd a b) (monoGcd xs ys)) ts- where- monoGcd :: Monomial -> Monomial -> Monomial- monoGcd [] _ = []- monoGcd ((x, n):xs) ys =- case f (x, n) ys of- (_, 0) -> monoGcd xs ys- (z, m) -> (z, m) : monoGcd xs ys-- f :: (SymbolExpr, Integer) -> Monomial -> (SymbolExpr, Integer)- f (x, _) [] = (x, 0)- f (Quote x, n) ((Quote y, m):ys)- | x == y = (Quote x, min n m)- | x == mathNegate y = (Quote x, min n m)- | otherwise = f (Quote x, n) ys- f (x, n) ((y, m):ys)- | x == y = (x, min n m)- | otherwise = f (x, n) ys--mathDivide :: ScalarData -> ScalarData-mathDivide mExpr@(Div (Plus _) (Plus [])) = mExpr-mathDivide mExpr@(Div (Plus []) (Plus _)) = mExpr-mathDivide (Div (Plus ts1) (Plus ts2)) =- let z@(Term c zs) = termsGcd (ts1 ++ ts2) in- case ts2 of- [Term a _] | a < 0 -> Div (Plus (map (`mathDivideTerm` Term (-c) zs) ts1))- (Plus (map (`mathDivideTerm` Term (-c) zs) ts2))- _ -> Div (Plus (map (`mathDivideTerm` z) ts1))- (Plus (map (`mathDivideTerm` z) ts2))--mathDivideTerm :: TermExpr -> TermExpr -> TermExpr-mathDivideTerm (Term a xs) (Term b ys) =- let (sgn, zs) = f 1 xs ys in- Term (sgn * div a b) zs- where- f :: Integer -> [(SymbolExpr, Integer)] -> [(SymbolExpr, Integer)] -> (Integer, [(SymbolExpr, Integer)])- f sgn xs [] = (sgn, xs)- f sgn xs ((y, n):ys) =- let (sgns, zs) = unzip (map (\(x, m) -> g (x, m) (y, n)) xs) in- f (sgn * product sgns) zs ys- g :: (SymbolExpr, Integer) -> (SymbolExpr, Integer) -> (Integer, (SymbolExpr, Integer))- g (Quote x, n) (Quote y, m)- | x == y = (1, (Quote x, n - m))- | x == mathNegate y = if even m then (1, (Quote x, n - m)) else (-1, (Quote x, n - m))- | otherwise = (1, (Quote x, n))- g (x, n) (y, m)- | x == y = (1, (x, n - m))- | otherwise = (1, (x, n))--mathRemoveZeroSymbol :: ScalarData -> ScalarData-mathRemoveZeroSymbol (Div (Plus ts1) (Plus ts2)) =- let ts1' = map (\(Term a xs) -> Term a (filter p xs)) ts1- ts2' = map (\(Term a xs) -> Term a (filter p xs)) ts2- in Div (Plus ts1') (Plus ts2')- where- p (_, 0) = False- p _ = True--mathRemoveZero :: ScalarData -> ScalarData-mathRemoveZero (Div (Plus ts1) (Plus ts2)) =- let ts1' = filter (\(Term a _) -> a /= 0) ts1 in- let ts2' = filter (\(Term a _) -> a /= 0) ts2 in- case ts1' of- [] -> Div (Plus []) (Plus [Term 1 []])- _ -> Div (Plus ts1') (Plus ts2')--mathFold :: ScalarData -> ScalarData-mathFold = mathTermFold . mathSymbolFold . mathTermFold---- x^2 y x -> x^3 y-mathSymbolFold :: ScalarData -> ScalarData-mathSymbolFold (Div (Plus ts1) (Plus ts2)) = Div (Plus (map f ts1)) (Plus (map f ts2))- where- f :: TermExpr -> TermExpr- f (Term a xs) = let (ys, sgns) = unzip $ g [] xs- in Term (product sgns * a) ys- g :: [((SymbolExpr, Integer),Integer)] -> [(SymbolExpr, Integer)] -> [((SymbolExpr, Integer),Integer)]- g ret [] = ret- g ret ((x, n):xs)- | any (p (x, n)) ret = g (map (h (x, n)) ret) xs- | otherwise = g (ret ++ [((x, n), 1)]) xs- p :: (SymbolExpr, Integer) -> ((SymbolExpr, Integer), Integer) -> Bool- p (Quote x, _) ((Quote y, _),_) = (x == y) || (mathNegate x == y)- p (x, _) ((y, _),_) = x == y- h :: (SymbolExpr, Integer) -> ((SymbolExpr, Integer), Integer) -> ((SymbolExpr, Integer), Integer)- h (Quote x, n) ((Quote y, m), sgn)- | x == y = ((Quote y, m + n), sgn)- | x == mathNegate y = if even n then ((Quote y, m + n), sgn) else ((Quote y, m + n), -1 * sgn)- | otherwise = ((Quote y, m), sgn)- h (x, n) ((y, m), sgn) = if x == y- then ((y, m + n), sgn)- else ((y, m), sgn)---- x^2 y + x^2 y -> 2 x^2 y-mathTermFold :: ScalarData -> ScalarData-mathTermFold (Div (Plus ts1) (Plus ts2)) = Div (Plus (f ts1)) (Plus (f ts2))- where- f :: [TermExpr] -> [TermExpr]- f = f' []- f' :: [TermExpr] -> [TermExpr] -> [TermExpr]- f' ret [] = ret- f' ret (Term a xs:ts) =- if any (\(Term _ ys) -> fst (p 1 xs ys)) ret- then f' (map (g (Term a xs)) ret) ts- else f' (ret ++ [Term a xs]) ts- g :: TermExpr -> TermExpr -> TermExpr- g (Term a xs) (Term b ys) = let (c, sgn) = p 1 xs ys in- if c- then Term ((sgn * a) + b) ys- else Term b ys- p :: Integer -> [(SymbolExpr, Integer)] -> [(SymbolExpr, Integer)] -> (Bool, Integer)- p sgn [] [] = (True, sgn)- p _ [] _ = (False, 0)- p sgn ((x, n):xs) ys =- let (b, ys', sgn2) = q (x, n) [] ys in- if b- then p (sgn * sgn2) xs ys'- else (False, 0)- q :: (SymbolExpr, Integer) -> [(SymbolExpr, Integer)] -> [(SymbolExpr, Integer)] -> (Bool, [(SymbolExpr, Integer)], Integer)- q _ _ [] = (False, [], 1)- q (Quote x, n) ret ((Quote y, m):ys)- | (x == y) && (n == m) = (True, ret ++ ys, 1)- | (mathNegate x == y) && (n == m) = if even n then (True, ret ++ ys, 1) else (True, ret ++ ys, -1)- | otherwise = q (Quote x, n) (ret ++ [(Quote y, m)]) ys- q (Quote x, n) ret ((y,m):ys) = q (Quote x, n) (ret ++ [(y, m)]) ys- q (x, n) ret ((y, m):ys) = if (x == y) && (n == m)- then (True, ret ++ ys, 1)- else q (x, n) (ret ++ [(y, m)]) ys------- Arithmetic operations-----mathPlus :: ScalarData -> ScalarData -> ScalarData-mathPlus (Div m1 n1) (Div m2 n2) = mathNormalize' $ Div (mathPlusPoly (mathMultPoly m1 n2) (mathMultPoly m2 n1)) (mathMultPoly n1 n2)--mathPlusPoly :: PolyExpr -> PolyExpr -> PolyExpr-mathPlusPoly (Plus ts1) (Plus ts2) = Plus (ts1 ++ ts2)--mathMult :: ScalarData -> ScalarData -> ScalarData-mathMult (Div m1 n1) (Div m2 n2) = mathNormalize' $ Div (mathMultPoly m1 m2) (mathMultPoly n1 n2)--mathMultPoly :: PolyExpr -> PolyExpr -> PolyExpr-mathMultPoly (Plus []) (Plus _) = Plus []-mathMultPoly (Plus _) (Plus []) = Plus []-mathMultPoly (Plus ts1) (Plus ts2) = foldl mathPlusPoly (Plus []) (map (\(Term a xs) -> Plus (map (\(Term b ys) -> Term (a * b) (xs ++ ys)) ts2)) ts1)--mathNegate :: ScalarData -> ScalarData-mathNegate (Div m n) = Div (mathNegate' m) n--mathNegate' :: PolyExpr -> PolyExpr-mathNegate' (Plus ts) = Plus (map (\(Term a xs) -> Term (-a) xs) ts)--mathNumerator :: ScalarData -> ScalarData-mathNumerator (Div m _) = Div m (Plus [Term 1 []])--mathDenominator :: ScalarData -> ScalarData-mathDenominator (Div _ n) = Div n (Plus [Term 1 []])
hs-src/Language/Egison/MathOutput.hs view
@@ -7,26 +7,23 @@ -} module Language.Egison.MathOutput- ( changeOutputInLang+ ( prettyMath ) where -import Text.ParserCombinators.Parsec (parse)-+import Language.Egison.Data import Language.Egison.PrettyMath.AST import qualified Language.Egison.PrettyMath.AsciiMath as AsciiMath import qualified Language.Egison.PrettyMath.Latex as Latex import qualified Language.Egison.PrettyMath.Mathematica as Mathematica import qualified Language.Egison.PrettyMath.Maxima as Maxima -changeOutputInLang :: String -> String -> String-changeOutputInLang lang input =+prettyMath :: String -> EgisonValue -> String+prettyMath lang val = -- 'lang' is either "asciimath", "latex", "mathematica" or "maxima" -- Other invalid options are rejected in Interpreter/egison.hs- case parse parseExpr "math-expr" input of- Left _ -> input- Right val -> case showMathExpr lang val of- "undefined" -> "undefined"- output -> "#" ++ lang ++ "|" ++ output ++ "|#"+ case showMathExpr lang (toMathExpr val) of+ "undefined" -> "undefined"+ output -> "#" ++ lang ++ "|" ++ output ++ "|#" showMathExpr :: String -> MathExpr -> String showMathExpr "asciimath" = AsciiMath.showMathExpr
hs-src/Language/Egison/Parser.hs view
@@ -7,12 +7,13 @@ module Language.Egison.Parser (- -- * Parse and desugar+ -- * Parse readTopExprs , readTopExpr , readExprs , readExpr- -- * Parse and desugar a file+ , parseTopExpr+ -- * Parse a file , loadLibraryFile , loadFile -- * Parser utils (for translator)@@ -20,46 +21,62 @@ , readUTF8File ) where -import Control.Monad.Except (liftIO, throwError)+import Control.Monad.Except (lift, liftIO, throwError) import Control.Monad.State (unless)+import Control.Monad.Reader (asks, local) import System.Directory (doesFileExist, getHomeDirectory) import System.IO import Language.Egison.AST-import Language.Egison.Desugar+import Language.Egison.CmdOptions import Language.Egison.Data+import Language.Egison.RState import qualified Language.Egison.Parser.SExpr as SExpr import qualified Language.Egison.Parser.NonS as NonS import Paths_egison (getDataFileName) -readTopExprs :: Bool -> String -> EvalM [EgisonTopExpr]-readTopExprs useSExpr =- either throwError (mapM desugarTopExpr) . parseTopExprs- where parseTopExprs | useSExpr = SExpr.parseTopExprs- | otherwise = NonS.parseTopExprs+readTopExprs :: String -> EvalM [TopExpr]+readTopExprs expr = do+ isSExpr <- asks optSExpr+ if isSExpr+ then either (throwError . Parser) return (SExpr.parseTopExprs expr)+ else do r <- lift . lift $ NonS.parseTopExprs expr+ either (throwError . Parser) return r --- TODO(momohatt): Parse from the last state-readTopExpr :: Bool -> String -> EvalM EgisonTopExpr-readTopExpr useSExpr =- either throwError desugarTopExpr . parseTopExpr- where parseTopExpr | useSExpr = SExpr.parseTopExpr- | otherwise = NonS.parseTopExpr+parseTopExpr :: String -> RuntimeM (Either String TopExpr)+parseTopExpr expr = do+ isSExpr <- asks optSExpr+ if isSExpr+ then return (SExpr.parseTopExpr expr)+ else NonS.parseTopExpr expr -readExprs :: Bool -> String -> EvalM [EgisonExpr]-readExprs useSExpr =- either throwError (mapM desugarExpr) . parseExprs- where parseExprs | useSExpr = SExpr.parseExprs- | otherwise = NonS.parseExprs+readTopExpr :: String -> EvalM TopExpr+readTopExpr expr = do+ isSExpr <- asks optSExpr+ if isSExpr+ then either (throwError . Parser) return (SExpr.parseTopExpr expr)+ else do r <- lift . lift $ NonS.parseTopExpr expr+ either (throwError . Parser) return r -readExpr :: Bool -> String -> EvalM EgisonExpr-readExpr useSExpr =- either throwError desugarExpr . parseExpr- where parseExpr | useSExpr = SExpr.parseExpr- | otherwise = NonS.parseExpr+readExprs :: String -> EvalM [Expr]+readExprs expr = do+ isSExpr <- asks optSExpr+ if isSExpr+ then either (throwError . Parser) return (SExpr.parseExprs expr)+ else do r <- lift . lift $ NonS.parseExprs expr+ either (throwError . Parser) return r +readExpr :: String -> EvalM Expr+readExpr expr = do+ isSExpr <- asks optSExpr+ if isSExpr+ then either (throwError . Parser) return (SExpr.parseExpr expr)+ else do r <- lift . lift $ NonS.parseExpr expr+ either (throwError . Parser) return r+ -- |Load a libary file-loadLibraryFile :: FilePath -> EvalM [EgisonTopExpr]+loadLibraryFile :: FilePath -> EvalM [TopExpr] loadLibraryFile file = do homeDir <- liftIO getHomeDirectory doesExist <- liftIO $ doesFileExist $ homeDir ++ "/.egison/" ++ file@@ -68,13 +85,14 @@ else liftIO (getDataFileName file) >>= loadFile -- |Load a file-loadFile :: FilePath -> EvalM [EgisonTopExpr]+loadFile :: FilePath -> EvalM [TopExpr] loadFile file = do doesExist <- liftIO $ doesFileExist file unless doesExist $ throwError $ Default ("file does not exist: " ++ file) input <- liftIO $ readUTF8File file- useSExpr <- checkIfUseSExpr file- exprs <- readTopExprs useSExpr $ removeShebang useSExpr input+ let useSExpr = checkIfUseSExpr file+ exprs <- local (\opt -> opt { optSExpr = useSExpr })+ (readTopExprs (removeShebang useSExpr input)) concat <$> mapM recursiveLoad exprs where recursiveLoad (Load file) = loadLibraryFile file@@ -91,14 +109,5 @@ hSetEncoding h utf8 hGetContents h -hasDotEgiExtension :: String -> Bool-hasDotEgiExtension file = drop (length file - 4) file == ".egi"--hasDotSEgiExtension :: String -> Bool-hasDotSEgiExtension file = drop (length file - 5) file == ".segi"--checkIfUseSExpr :: String -> EvalM Bool-checkIfUseSExpr file- | hasDotEgiExtension file = return False- | hasDotSEgiExtension file = return True- | otherwise = throwError (UnknownFileExtension file)+checkIfUseSExpr :: String -> Bool+checkIfUseSExpr file = drop (length file - 5) file == ".segi"
hs-src/Language/Egison/Parser/NonS.hs view
@@ -5,7 +5,7 @@ Module : Language.Egison.Parser.NonS Licence : MIT -This module provides the new parser of Egison.+This module provides the parser for the new syntax. -} module Language.Egison.Parser.NonS@@ -15,10 +15,11 @@ , parseTopExpr , parseExprs , parseExpr+ , upperReservedWords+ , lowerReservedWords ) where -import Control.Monad.Except (throwError)-import Control.Monad.State (evalStateT, get, put, StateT)+import Control.Monad.State (get, gets, put) import Data.Char (isAsciiUpper, isLetter) import Data.Either (isRight)@@ -32,40 +33,31 @@ import Text.Megaparsec.Char import qualified Text.Megaparsec.Char.Lexer as L -import Language.Egison.AST-import Language.Egison.Data+import Language.Egison.AST hiding (Assoc(..))+import qualified Language.Egison.AST as E+import Language.Egison.RState -parseTopExprs :: String -> Either EgisonError [EgisonTopExpr]++parseTopExprs :: String -> RuntimeM (Either String [TopExpr]) parseTopExprs = doParse $ many (L.nonIndented sc topExpr) <* eof -parseTopExpr :: String -> Either EgisonError EgisonTopExpr+parseTopExpr :: String -> RuntimeM (Either String TopExpr) parseTopExpr = doParse $ sc >> topExpr <* eof -parseExprs :: String -> Either EgisonError [EgisonExpr]+parseExprs :: String -> RuntimeM (Either String [Expr]) parseExprs = doParse $ many (L.nonIndented sc expr) <* eof -parseExpr :: String -> Either EgisonError EgisonExpr+parseExpr :: String -> RuntimeM (Either String Expr) parseExpr = doParse $ sc >> expr <* eof -- -- Parser -- -type Parser = StateT PState (Parsec CustomError String)---- Parser state-data PState- = PState { exprInfix :: [Infix]- , patternInfix :: [Infix]- }--initialPState :: PState-initialPState = PState { exprInfix = reservedExprInfix- , patternInfix = reservedPatternInfix- }+type Parser = ParsecT CustomError String RuntimeM data CustomError- = IllFormedSection Infix Infix+ = IllFormedSection Op Op | IllFormedDefine | LastStmtInDoBlock deriving (Eq, Ord)@@ -82,53 +74,50 @@ "The last statement in a 'do' block must be an expression." -doParse :: Parser a -> String -> Either EgisonError a-doParse p input =- case parse (evalStateT p initialPState) "egison" input of- Left e -> throwError (Parser (errorBundlePretty e))- Right r -> return r+doParse :: Parser a -> String -> RuntimeM (Either String a)+doParse p input = do+ result <- runParserT p "egison" input+ case result of+ Left e -> return $ Left (errorBundlePretty e)+ Right r -> return $ Right r -- -- Expressions -- -topExpr :: Parser EgisonTopExpr+topExpr :: Parser TopExpr topExpr = Load <$> (reserved "load" >> stringLiteral) <|> LoadFile <$> (reserved "loadFile" >> stringLiteral) <|> Execute <$> (reserved "execute" >> expr)+ <|> (reserved "def" >> defineExpr) <|> infixExpr- <|> defineOrTestExpr+ <|> Test <$> expr <?> "toplevel expression" --- Return type of |convertToDefine|.-data ConversionResult- = Variable Var -- Definition of a variable with no arguments on lhs.- | Function Var [Arg] -- Definition of a function with some arguments on lhs.- | IndexedVar VarWithIndices- -- Sort binaryop table on the insertion-addNewOp :: Infix -> Bool -> Parser ()-addNewOp newop isPattern = do+addNewOp :: Op -> Bool -> Parser ()+addNewOp newop isPattern | isPattern = do pstate <- get- put $! if isPattern- then pstate { patternInfix = insertBy- (\x y -> compare (priority y) (priority x))- newop- (patternInfix pstate) }- else pstate { exprInfix = insertBy- (\x y -> compare (priority y) (priority x))- newop- (exprInfix pstate) }+ put $! pstate { patternOps = insertBy+ (\x y -> compare (priority y) (priority x))+ newop+ (patternOps pstate) }+addNewOp newop _ = do+ pstate <- get+ put $! pstate { exprOps = insertBy+ (\x y -> compare (priority y) (priority x))+ newop+ (exprOps pstate) } -infixExpr :: Parser EgisonTopExpr+infixExpr :: Parser TopExpr infixExpr = do- assoc <- (reserved "infixl" $> LeftAssoc)- <|> (reserved "infixr" $> RightAssoc)- <|> (reserved "infix" $> NonAssoc)+ assoc <- (reserved "infixl" $> E.InfixL)+ <|> (reserved "infixr" $> E.InfixR)+ <|> (reserved "infix" $> E.InfixN) isPattern <- isRight <$> eitherP (reserved "expression") (reserved "pattern") priority <- fromInteger <$> positiveIntegerLiteral sym <- if isPattern then newPatOp >>= checkP else some opChar >>= check- let newop = Infix { repr = sym, func = sym, priority, assoc, isWedge = False }+ let newop = Op { repr = sym, priority, assoc, isWedge = False } addNewOp newop isPattern return (InfixDecl isPattern newop) where@@ -145,78 +134,19 @@ reservedOp = [":", ":=", "->"] reservedPOp = ["&", "|", ":=", "->"] -defineOrTestExpr :: Parser EgisonTopExpr-defineOrTestExpr = do- e <- expr- defineExpr e <|> return (Test e)- where- defineExpr :: EgisonExpr -> Parser EgisonTopExpr- defineExpr e = do- _ <- symbol ":="- -- When ":=" is observed and the current expression turns out to be a- -- definition, we do not start over from scratch but re-interpret- -- what's parsed so far as the lhs of definition.- case convertToDefine e of- Nothing -> customFailure IllFormedDefine- Just (Variable var) -> Define var <$> expr- Just (Function var args) -> Define var . LambdaExpr args <$> expr- Just (IndexedVar var) -> DefineWithIndices var <$> expr-- convertToDefine :: EgisonExpr -> Maybe ConversionResult- convertToDefine (VarExpr var) = return $ Variable var- convertToDefine (SectionExpr op Nothing Nothing) =- return $ Variable (stringToVar (func op))- convertToDefine (ApplyExpr (VarExpr var) (TupleExpr [TupleExpr args])) = do- args' <- mapM ((TensorArg <$>) . exprToStr) args- return $ Function var args'- convertToDefine (ApplyExpr (VarExpr var) (TupleExpr args)) = do- args' <- mapM ((TensorArg <$>) . exprToStr) args- return $ Function var args'- convertToDefine (ApplyExpr (SectionExpr op Nothing Nothing) (TupleExpr [x, y])) = do- args <- mapM ((TensorArg <$>) . exprToStr) [x, y]- return $ Function (stringToVar (repr op)) args- convertToDefine e@(InfixExpr op _ _)- | repr op == "*" || repr op == "%" || repr op == "$" = do- args <- exprToArgs e- case args of- TensorArg var : args -> return $ Function (stringToVar var) args- _ -> Nothing- convertToDefine (IndexedExpr True (VarExpr (Var var [])) indices) = do- -- [Index EgisonExpr] -> Maybe [Index String]- indices' <- mapM (traverse exprToStr) indices- return $ IndexedVar (VarWithIndices var indices')- convertToDefine _ = Nothing-- exprToStr :: EgisonExpr -> Maybe String- exprToStr (VarExpr v) = Just (show v)- exprToStr _ = Nothing-- exprToArgs :: EgisonExpr -> Maybe [Arg]- exprToArgs (VarExpr v) = return [TensorArg (show v)]- exprToArgs (ApplyExpr func (TupleExpr args)) =- (++) <$> exprToArgs func <*> mapM ((TensorArg <$>) . exprToStr) args- exprToArgs (SectionExpr op Nothing Nothing) = return [TensorArg (func op)]- exprToArgs (InfixExpr op lhs rhs) | repr op == "*" = do- lhs' <- exprToArgs lhs- rhs' <- exprToArgs rhs- case rhs' of- TensorArg x : xs -> return (lhs' ++ InvertedScalarArg x : xs)- _ -> Nothing- exprToArgs (InfixExpr op lhs rhs) | repr op == "$" = do- lhs' <- exprToArgs lhs- rhs' <- exprToArgs rhs- case rhs' of- TensorArg x : xs -> return (lhs' ++ ScalarArg x : xs)- _ -> Nothing- exprToArgs (InfixExpr op lhs rhs) | repr op == "%" = do- lhs' <- exprToArgs lhs- rhs' <- exprToArgs rhs- case rhs' of- TensorArg _ : _ -> return (lhs' ++ rhs')- _ -> Nothing- exprToArgs _ = Nothing+defineExpr :: Parser TopExpr+defineExpr = do+ ops <- gets exprOps+ f <- parens (stringToVarWithIndices . repr <$> choice (map (infixLiteral . repr) ops))+ <|> varWithIndicesLiteral+ args <- many arg+ _ <- symbol ":="+ body <- expr+ case args of+ [] -> return (Define f body)+ _ -> return (Define f (LambdaExpr args body)) -expr :: Parser EgisonExpr+expr :: Parser Expr expr = do body <- exprWithoutWhere bindings <- optional (reserved "where" >> alignSome binding)@@ -224,8 +154,12 @@ Nothing -> body Just bindings -> LetRecExpr bindings body -exprWithoutWhere :: Parser EgisonExpr-exprWithoutWhere =+exprWithoutWhere :: Parser Expr+exprWithoutWhere = opExpr++-- Expressions that can be the arguments for the operators.+exprInOp :: Parser Expr+exprInOp = ifExpr <|> patternMatchExpr <|> lambdaExpr@@ -233,7 +167,6 @@ <|> letExpr <|> withSymbolsExpr <|> doExpr- <|> ioExpr <|> seqExpr <|> capplyExpr <|> matcherExpr@@ -241,44 +174,43 @@ <|> tensorExpr <|> functionExpr <|> refsExpr- <|> opExpr+ <|> atomOrApplyExpr <?> "expression" --- Also parses atomExpr-opExpr :: Parser EgisonExpr+-- Also parses exprInOp+opExpr :: Parser Expr opExpr = do- infixes <- exprInfix <$> get- makeExprParser atomOrApplyExpr (makeExprTable infixes)+ ops <- gets exprOps+ makeExprParser exprInOp (makeExprTable ops) -makeExprTable :: [Infix] -> [[Operator Parser EgisonExpr]]-makeExprTable infixes =- -- prefixes have top priority- let prefixes = [ [ Prefix (unary "-")- , Prefix (unary "!") ] ]- -- Generate binary operator table from |infixes|- infixes' = map (map toOperator)- (groupBy (\x y -> priority x == priority y) infixes)- in prefixes ++ infixes'+makeExprTable :: [Op] -> [[Operator Parser Expr]]+makeExprTable ops =+ -- Generate binary operator table from |ops|+ map (map toOperator) (groupBy (\x y -> priority x == priority y) ops) where -- notFollowedBy (in unary and binary) is necessary for section expression.- unary :: String -> Parser (EgisonExpr -> EgisonExpr)+ unary :: String -> Parser (Expr -> Expr) unary sym = PrefixExpr <$> try (operator sym <* notFollowedBy (symbol ")")) - binary :: Infix -> Parser (EgisonExpr -> EgisonExpr -> EgisonExpr)+ binary :: Op -> Parser (Expr -> Expr -> Expr) binary op = do -- Operators should be indented than pos1 in order to avoid -- "1\n-2" (2 topExprs, 1 and -2) to be parsed as "1 - 2". op <- try (indented >> infixLiteral (repr op) <* notFollowedBy (symbol ")")) return $ InfixExpr op - toOperator :: Infix -> Operator Parser EgisonExpr- toOperator = infixToOperator binary-+ toOperator :: Op -> Operator Parser Expr+ toOperator op =+ case assoc op of+ E.InfixL -> InfixL (binary op)+ E.InfixR -> InfixR (binary op)+ E.InfixN -> InfixN (binary op)+ E.Prefix -> Prefix (unary (repr op)) -ifExpr :: Parser EgisonExpr+ifExpr :: Parser Expr ifExpr = reserved "if" >> IfExpr <$> expr <* reserved "then" <*> expr <* reserved "else" <*> expr -patternMatchExpr :: Parser EgisonExpr+patternMatchExpr :: Parser Expr patternMatchExpr = makeMatchExpr (reserved "match") (MatchExpr BFSMode) <|> makeMatchExpr (reserved "matchDFS") (MatchExpr DFSMode) <|> makeMatchExpr (reserved "matchAll") (MatchAllExpr BFSMode)@@ -301,11 +233,11 @@ matchClause :: Parser MatchClause matchClause = (,) <$> (symbol "|" >> pattern) <*> (symbol "->" >> expr) -lambdaExpr :: Parser EgisonExpr+lambdaExpr :: Parser Expr lambdaExpr = symbol "\\" >> ( makeMatchLambdaExpr (reserved "match") MatchLambdaExpr <|> makeMatchLambdaExpr (reserved "matchAll") MatchAllLambdaExpr- <|> try (LambdaExpr <$> tupleOrSome arg <* symbol "->") <*> expr+ <|> try (LambdaExpr <$> some arg <* symbol "->") <*> expr <|> PatternFunctionExpr <$> tupleOrSome lowerId <*> (symbol "=>" >> pattern)) <?> "lambda or pattern function expression" where@@ -314,19 +246,29 @@ clauses <- reserved "with" >> matchClauses1 return $ ctor matcher clauses -lambdaLikeExpr :: Parser EgisonExpr+lambdaLikeExpr :: Parser Expr lambdaLikeExpr = (reserved "memoizedLambda" >> MemoizedLambdaExpr <$> tupleOrSome lowerId <*> (symbol "->" >> expr)) <|> (reserved "cambda" >> CambdaExpr <$> lowerId <*> (symbol "->" >> expr)) -arg :: Parser Arg-arg = InvertedScalarArg <$> (char '*' >> ident)- <|> TensorArg <$> (char '%' >> ident)- <|> ScalarArg <$> (char '$' >> ident)- <|> TensorArg <$> ident+arg :: Parser (Arg ArgPattern)+arg = InvertedScalarArg <$> (string "*$" >> argPatternAtom)+ <|> TensorArg <$> (char '%' >> argPatternAtom)+ <|> ScalarArg <$> (char '$' >> argPatternAtom)+ <|> TensorArg <$> argPattern <?> "argument" -letExpr :: Parser EgisonExpr+argPattern :: Parser ArgPattern+argPattern =+ argPatternAtom++argPatternAtom :: Parser ArgPattern+argPatternAtom+ = APWildCard <$ symbol "_"+ <|> APTuplePat <$> parens (sepBy arg comma)+ <|> APPatVar <$> ident++letExpr :: Parser Expr letExpr = do binds <- reserved "let" >> oneLiner <|> alignSome binding body <- reserved "in" >> expr@@ -337,42 +279,39 @@ binding :: Parser BindingExpr binding = do- (vars, args) <- (,[]) <$> parens (sepBy varLiteral comma)- <|> do var <- varLiteral- args <- many arg- return ([var], args)+ id <- Left <$> try varWithIndicesLiteral' <|> Right <$> pdAtom+ args <- many arg body <- symbol ":=" >> expr- return $ case args of- [] -> (vars, body)- _ -> (vars, LambdaExpr args body)+ case (id, args) of+ (Left var, []) -> return $ BindWithIndices var body+ (Right pdp, []) -> return $ Bind pdp body+ (Right pdp, _) -> return $ Bind pdp (LambdaExpr args body)+ _ -> error "unreachable" -withSymbolsExpr :: Parser EgisonExpr+withSymbolsExpr :: Parser Expr withSymbolsExpr = WithSymbolsExpr <$> (reserved "withSymbols" >> brackets (sepBy ident comma)) <*> expr -doExpr :: Parser EgisonExpr+doExpr :: Parser Expr doExpr = do stmts <- reserved "do" >> oneLiner <|> alignSome statement case reverse stmts of- [] -> return $ DoExpr [] (makeApply' "return" [])- ([], expr):_ -> return $ DoExpr (init stmts) expr- _:_ -> customFailure LastStmtInDoBlock+ [] -> return $ DoExpr [] (makeApply "return" [])+ Bind (PDTuplePat []) expr:_ -> return $ DoExpr (init stmts) expr+ _:_ -> customFailure LastStmtInDoBlock where statement :: Parser BindingExpr- statement = (reserved "let" >> binding) <|> ([],) <$> expr+ statement = (reserved "let" >> binding) <|> Bind (PDTuplePat []) <$> expr oneLiner :: Parser [BindingExpr] oneLiner = braces $ sepBy statement (symbol ";") -ioExpr :: Parser EgisonExpr-ioExpr = IoExpr <$> (reserved "io" >> expr)--seqExpr :: Parser EgisonExpr+seqExpr :: Parser Expr seqExpr = SeqExpr <$> (reserved "seq" >> atomExpr) <*> atomExpr -capplyExpr :: Parser EgisonExpr+capplyExpr :: Parser Expr capplyExpr = CApplyExpr <$> (reserved "capply" >> atomExpr) <*> atomExpr -matcherExpr :: Parser EgisonExpr+matcherExpr :: Parser Expr matcherExpr = do reserved "matcher" -- Assuming it is unlikely that users want to write matchers with only 1@@ -380,24 +319,24 @@ -- expression. MatcherExpr <$> alignSome (symbol "|" >> patternDef) where- patternDef :: Parser (PrimitivePatPattern, EgisonExpr, [(PrimitiveDataPattern, EgisonExpr)])+ patternDef :: Parser (PrimitivePatPattern, Expr, [(PrimitiveDataPattern, Expr)]) patternDef = do pp <- ppPattern returnMatcher <- reserved "as" >> expr <* reserved "with" datapat <- alignSome (symbol "|" >> dataCases) return (pp, returnMatcher, datapat) - dataCases :: Parser (PrimitiveDataPattern, EgisonExpr)+ dataCases :: Parser (PrimitiveDataPattern, Expr) dataCases = (,) <$> pdPattern <*> (symbol "->" >> expr) -algebraicDataMatcherExpr :: Parser EgisonExpr+algebraicDataMatcherExpr :: Parser Expr algebraicDataMatcherExpr = do reserved "algebraicDataMatcher" AlgebraicDataMatcherExpr <$> alignSome (symbol "|" >> patternDef) where patternDef = indentBlock lowerId atomExpr -tensorExpr :: Parser EgisonExpr+tensorExpr :: Parser Expr tensorExpr = (reserved "tensor" >> TensorExpr <$> atomExpr <*> atomExpr) <|> (reserved "generateTensor" >> GenerateTensorExpr <$> atomExpr <*> atomExpr)@@ -406,10 +345,10 @@ <|> (reserved "tensorMap2" >> TensorMap2Expr <$> atomExpr <*> atomExpr <*> atomExpr) <|> (reserved "transpose" >> TransposeExpr <$> atomExpr <*> atomExpr) -functionExpr :: Parser EgisonExpr-functionExpr = FunctionExpr <$> (reserved "function" >> parens (sepBy expr comma))+functionExpr :: Parser Expr+functionExpr = FunctionExpr <$> (reserved "function" >> parens (sepBy ident comma)) -refsExpr :: Parser EgisonExpr+refsExpr :: Parser Expr refsExpr = (reserved "subrefs" >> SubrefsExpr False <$> atomExpr <*> atomExpr) <|> (reserved "subrefs!" >> SubrefsExpr True <$> atomExpr <*> atomExpr)@@ -418,109 +357,110 @@ <|> (reserved "userRefs" >> UserrefsExpr False <$> atomExpr <*> atomExpr) <|> (reserved "userRefs!" >> UserrefsExpr True <$> atomExpr <*> atomExpr) -collectionExpr :: Parser EgisonExpr+collectionExpr :: Parser Expr collectionExpr = symbol "[" >> betweenOrFromExpr <|> elementsExpr where betweenOrFromExpr = do start <- try (expr <* symbol "..") end <- optional expr <* symbol "]" case end of- Just end' -> return $ makeApply' "between" [start, end']- Nothing -> return $ makeApply' "from" [start]+ Just end' -> return $ makeApply "between" [start, end']+ Nothing -> return $ makeApply "from" [start] - elementsExpr = CollectionExpr <$> (sepBy (ElementExpr <$> expr) comma <* symbol "]")+ elementsExpr = CollectionExpr <$> (sepBy expr comma <* symbol "]") -- Parse an atomic expression starting with '(', which can be: -- * a tuple -- * an arbitrary expression wrapped with parenthesis -- * section-tupleOrParenExpr :: Parser EgisonExpr+tupleOrParenExpr :: Parser Expr tupleOrParenExpr = do elems <- symbol "(" >> try (sepBy expr comma <* symbol ")") <|> (section <* symbol ")") case elems of [x] -> return x -- expression wrapped in parenthesis _ -> return $ TupleExpr elems -- tuple where- section :: Parser [EgisonExpr]+ section :: Parser [Expr] -- Start from right, in order to parse expressions like (-1 +) correctly section = (:[]) <$> (rightSection <|> leftSection) -- Sections without the left operand: eg. (+), (+ 1)- leftSection :: Parser EgisonExpr+ leftSection :: Parser Expr leftSection = do- infixes <- exprInfix <$> get- op <- choice $ map (infixLiteral . repr) infixes- rarg <- optional expr+ ops <- gets exprOps+ op <- choice $ map (infixLiteral . repr) ops+ rarg <- optional expr case rarg of- Just (InfixExpr op' _ _)- | assoc op' /= RightAssoc && priority op >= priority op' ->- customFailure (IllFormedSection op op')+ -- Disabling for now... (See issue 159)+ -- Just (InfixExpr op' _ _)+ -- | assoc op' /= InfixR && priority op >= priority op' ->+ -- customFailure (IllFormedSection op op') _ -> return (SectionExpr op Nothing rarg) -- Sections with the left operand but lacks the right operand: eg. (1 +)- rightSection :: Parser EgisonExpr+ rightSection :: Parser Expr rightSection = do- infixes <- exprInfix <$> get- larg <- opExpr- op <- choice $ map (infixLiteral . repr) infixes+ ops <- gets exprOps+ larg <- opExpr+ op <- choice $ map (infixLiteral . repr) ops case larg of- InfixExpr op' _ _- | assoc op' /= LeftAssoc && priority op >= priority op' ->- customFailure (IllFormedSection op op')+ -- InfixExpr op' _ _+ -- | assoc op' /= InfixL && priority op >= priority op' ->+ -- customFailure (IllFormedSection op op') _ -> return (SectionExpr op (Just larg) Nothing) -vectorExpr :: Parser EgisonExpr+vectorExpr :: Parser Expr vectorExpr = VectorExpr <$> between (symbol "[|") (symbol "|]") (sepEndBy expr comma) -hashExpr :: Parser EgisonExpr+hashExpr :: Parser Expr hashExpr = HashExpr <$> hashBraces (sepEndBy hashElem comma) where hashBraces = between (symbol "{|") (symbol "|}") hashElem = parens $ (,) <$> expr <*> (comma >> expr) -index :: Parser (Index EgisonExpr)-index = SupSubscript <$> (string "~_" >> atomExpr')+index :: Parser a -> Parser (IndexExpr a)+index p = SupSubscript <$> (string "~_" >> p) <|> try (char '_' >> subscript) <|> try (char '~' >> superscript)- <|> try (Userscript <$> (char '|' >> atomExpr'))+ <|> try (Userscript <$> (char '|' >> p)) <?> "index" where subscript = do- e1 <- atomExpr'- e2 <- optional (string "..._" >> atomExpr')+ e1 <- p+ e2 <- optional (string "..._" >> p) case e2 of Nothing -> return $ Subscript e1 Just e2' -> return $ MultiSubscript e1 e2' superscript = do- e1 <- atomExpr'- e2 <- optional (string "...~" >> atomExpr')+ e1 <- p+ e2 <- optional (string "...~" >> p) case e2 of Nothing -> return $ Superscript e1 Just e2' -> return $ MultiSuperscript e1 e2' -atomOrApplyExpr :: Parser EgisonExpr+atomOrApplyExpr :: Parser Expr atomOrApplyExpr = do (func, args) <- indentBlock atomExpr atomExpr return $ case args of [] -> func- _ -> makeApply func args+ _ -> ApplyExpr func args -- (Possibly indexed) atomic expressions-atomExpr :: Parser EgisonExpr+atomExpr :: Parser Expr atomExpr = do e <- atomExpr'- override <- isNothing <$> optional (try (string "..." <* lookAhead index))- indices <- many index+ override <- isNothing <$> optional (try (string "..." <* lookAhead (index atomExpr')))+ indices <- many (index atomExpr') return $ case indices of [] -> e _ -> IndexedExpr override e indices -- Atomic expressions without index-atomExpr' :: Parser EgisonExpr+atomExpr' :: Parser Expr atomExpr' = anonParamFuncExpr -- must come before |constantExpr|- <|> constantExpr+ <|> ConstantExpr <$> constantExpr <|> FreshVarExpr <$ symbol "#"- <|> VarExpr <$> varLiteral+ <|> VarExpr <$> ident <|> vectorExpr -- must come before |collectionExpr| <|> collectionExpr <|> tupleOrParenExpr@@ -530,13 +470,13 @@ <|> AnonParamExpr <$> try (char '%' >> positiveIntegerLiteral) <?> "atomic expression" -anonParamFuncExpr :: Parser EgisonExpr+anonParamFuncExpr :: Parser Expr anonParamFuncExpr = do n <- try (L.decimal <* char '#') -- No space after the index body <- atomExpr -- No space after '#' return $ AnonParamFuncExpr n body -constantExpr :: Parser EgisonExpr+constantExpr :: Parser ConstantExpr constantExpr = numericExpr <|> BoolExpr <$> boolLiteral <|> CharExpr <$> try charLiteral -- try for quoteExpr@@ -544,7 +484,7 @@ <|> SomethingExpr <$ reserved "something" <|> UndefinedExpr <$ reserved "undefined" -numericExpr :: Parser EgisonExpr+numericExpr :: Parser ConstantExpr numericExpr = FloatExpr <$> try positiveFloatLiteral <|> IntegerExpr <$> positiveIntegerLiteral <?> "numeric expression"@@ -552,24 +492,24 @@ -- Pattern -- -pattern :: Parser EgisonPattern+pattern :: Parser Pattern pattern = letPattern <|> forallPattern <|> loopPattern <|> opPattern <?> "pattern" -letPattern :: Parser EgisonPattern+letPattern :: Parser Pattern letPattern = reserved "let" >> LetPat <$> alignSome binding <*> (reserved "in" >> pattern) -forallPattern :: Parser EgisonPattern+forallPattern :: Parser Pattern forallPattern = reserved "forall" >> ForallPat <$> atomPattern <*> atomPattern -loopPattern :: Parser EgisonPattern+loopPattern :: Parser Pattern loopPattern =- LoopPat <$> (reserved "loop" >> patVarLiteral) <*> loopRange+ LoopPat <$> (reserved "loop" >> char '$' >> ident) <*> loopRange <*> atomPattern <*> atomPattern where loopRange :: Parser LoopRange@@ -580,33 +520,33 @@ return $ LoopRange start ends as defaultEnds s =- ApplyExpr (stringToVarExpr "from")- (makeApply (stringToVarExpr "-'") [s, IntegerExpr 1])+ makeApply "from"+ [makeApply "-'" [s, ConstantExpr (IntegerExpr 1)]] -seqPattern :: Parser EgisonPattern+seqPattern :: Parser Pattern seqPattern = do pats <- braces $ sepBy pattern comma return $ foldr SeqConsPat SeqNilPat pats -opPattern :: Parser EgisonPattern+opPattern :: Parser Pattern opPattern = do- ops <- patternInfix <$> get+ ops <- gets patternOps makeExprParser applyOrAtomPattern (makePatternTable ops) -makePatternTable :: [Infix] -> [[Operator Parser EgisonPattern]]+makePatternTable :: [Op] -> [[Operator Parser Pattern]] makePatternTable ops =- let infixes = map toOperator ops- in map (map snd) (groupBy (\x y -> fst x == fst y) infixes)+ let ops' = map toOperator ops+ in map (map snd) (groupBy (\x y -> fst x == fst y) ops') where- toOperator :: Infix -> (Int, Operator Parser EgisonPattern)+ toOperator :: Op -> (Int, Operator Parser Pattern) toOperator op = (priority op, infixToOperator binary op) - binary :: Infix -> Parser (EgisonPattern -> EgisonPattern -> EgisonPattern)+ binary :: Op -> Parser (Pattern -> Pattern -> Pattern) binary op = do op <- try (indented >> patInfixLiteral (repr op)) return $ InfixPat op -applyOrAtomPattern :: Parser EgisonPattern+applyOrAtomPattern :: Parser Pattern applyOrAtomPattern = (do (func, args) <- indentBlock (try atomPattern) atomPattern case (func, args) of@@ -617,16 +557,16 @@ (func, args) <- indentBlock atomExpr atomPattern return $ PApplyPat func args) -collectionPattern :: Parser EgisonPattern+collectionPattern :: Parser Pattern collectionPattern = brackets $ do elems <- sepBy pattern comma return $ foldr (InfixPat consOp) nilPat elems where nilPat = InductivePat "nil" []- consOp = findOpFrom "::" reservedPatternInfix+ consOp = findOpFrom "::" reservedPatternOp -- (Possibly indexed) atomic pattern-atomPattern :: Parser EgisonPattern+atomPattern :: Parser Pattern atomPattern = do pat <- atomPattern' indices <- many . try $ char '_' >> atomExpr'@@ -635,7 +575,7 @@ _ -> IndexedPat pat indices -- Atomic pattern without index-atomPattern' :: Parser EgisonPattern+atomPattern' :: Parser Pattern atomPattern' = WildCard <$ symbol "_" <|> PatVar <$> patVarLiteral <|> NotPat <$> (symbol "!" >> atomPattern)@@ -652,18 +592,18 @@ ppPattern :: Parser PrimitivePatPattern ppPattern = PPInductivePat <$> lowerId <*> many ppAtom- <|> do ops <- patternInfix <$> get+ <|> do ops <- gets patternOps makeExprParser ppAtom (makeTable ops) <?> "primitive pattern pattern" where- makeTable :: [Infix] -> [[Operator Parser PrimitivePatPattern]]+ makeTable :: [Op] -> [[Operator Parser PrimitivePatPattern]] makeTable ops = map (map toOperator) (groupBy (\x y -> priority x == priority y) ops) - toOperator :: Infix -> Operator Parser PrimitivePatPattern+ toOperator :: Op -> Operator Parser PrimitivePatPattern toOperator = infixToOperator inductive2 - inductive2 op = (\x y -> PPInductivePat (func op) [x, y]) <$ operator (repr op)+ inductive2 op = (\x y -> PPInductivePat (repr op) [x, y]) <$ operator (repr op) ppAtom :: Parser PrimitivePatPattern ppAtom = PPWildCard <$ symbol "_"@@ -686,18 +626,19 @@ <|> PDSnocPat <$> (symbol "snoc" >> pdAtom) <*> pdAtom <|> pdAtom +pdAtom :: Parser PrimitiveDataPattern+pdAtom = PDWildCard <$ symbol "_"+ <|> PDPatVar <$> patVarLiteral+ <|> PDPatVar <$> ident+ <|> PDConstantPat <$> constantExpr+ <|> pdCollection+ <|> makeTupleOrParen pdPattern PDTuplePat+ where pdCollection :: Parser PrimitiveDataPattern pdCollection = do elts <- brackets (sepBy pdPattern comma) return (foldr PDConsPat PDEmptyPat elts) - pdAtom :: Parser PrimitiveDataPattern- pdAtom = PDWildCard <$ symbol "_"- <|> PDPatVar <$> (char '$' >> ident)- <|> PDConstantPat <$> constantExpr- <|> pdCollection- <|> makeTupleOrParen pdPattern PDTuplePat- -- -- Tokens --@@ -733,20 +674,32 @@ positiveFloatLiteral = lexeme L.float <?> "unsigned float" -varLiteral :: Parser Var-varLiteral = stringToVar <$> ident+varWithIndicesLiteral :: Parser VarWithIndices+varWithIndicesLiteral =+ lexeme (VarWithIndices <$> ident' <*> many varIndex) -patVarLiteral :: Parser Var-patVarLiteral = stringToVar <$> (char '$' >> ident)+varWithIndicesLiteral' :: Parser VarWithIndices+varWithIndicesLiteral' =+ lexeme (VarWithIndices <$> ident' <*> some varIndex) +varIndex :: Parser VarIndex+varIndex = (char '_' >> VSubscript <$> ident')+ <|> (char '~' >> VSuperscript <$> ident')+ <|> parens (VGroupScripts <$> some varIndex)+ <|> braces (VSymmScripts <$> some varIndex)+ <|> brackets (VAntiSymmScripts <$> some varIndex)++patVarLiteral :: Parser String+patVarLiteral = char '$' >> ident+ -- Parse infix (binary operator) literal. -- If the operator is prefixed with '!', |isWedge| is turned to true.-infixLiteral :: String -> Parser Infix+infixLiteral :: String -> Parser Op infixLiteral sym =- try (do wedge <- optional (char '!')- opSym <- operator' sym- infixes <- exprInfix <$> get- let opInfo = findOpFrom opSym infixes+ try (do wedge <- optional (char '!')+ opSym <- operator' sym+ ops <- gets exprOps+ let opInfo = findOpFrom opSym ops return $ opInfo { isWedge = isJust wedge }) <?> "infix" where@@ -764,11 +717,11 @@ operator sym = try $ string sym <* notFollowedBy opChar <* sc -- |infixLiteral| for pattern infixes.-patInfixLiteral :: String -> Parser Infix+patInfixLiteral :: String -> Parser Op patInfixLiteral sym = try (do opSym <- string sym <* notFollowedBy patOpChar <* sc- infixes <- patternInfix <$> get- let opInfo = findOpFrom opSym infixes+ ops <- gets patternOps+ let opInfo = findOpFrom opSym ops return opInfo) -- Characters that can consist expression operators.@@ -847,6 +800,16 @@ then fail $ "keyword " ++ show x ++ " cannot be an identifier" else return x +-- |ident| not followed by a space+ident' :: Parser String+ident' = try (p >>= check)+ where+ p = (:) <$> satisfy checkHead <*> identString+ checkHead c = c `elem` mathSymbols || isLetter c+ check x = if x `elem` (lowerReservedWords ++ upperReservedWords)+ then fail $ "keyword " ++ show x ++ " cannot be an identifier"+ else return x+ upperReservedWords :: [String] upperReservedWords = [ "True"@@ -857,6 +820,7 @@ lowerReservedWords = [ "loadFile" , "load"+ , "def" , "if" , "then" , "else"@@ -878,7 +842,6 @@ , "with" , "matcher" , "do"- , "io" , "something" , "undefined" , "algebraicDataMatcher"@@ -911,13 +874,6 @@ [elem] -> return elem _ -> return $ tupleCtor elems -makeApply :: EgisonExpr -> [EgisonExpr] -> EgisonExpr-makeApply (InductiveDataExpr x []) xs = InductiveDataExpr x xs-makeApply func xs = ApplyExpr func (TupleExpr xs)--makeApply' :: String -> [EgisonExpr] -> EgisonExpr-makeApply' func xs = ApplyExpr (stringToVarExpr func) (TupleExpr xs)- indentGuardEQ :: Pos -> Parser Pos indentGuardEQ pos = L.indentGuard sc EQ pos @@ -942,12 +898,12 @@ indented :: Parser Pos indented = indentGuardGT pos1 -infixToOperator :: (Infix -> Parser (a -> a -> a)) -> Infix -> Operator Parser a+infixToOperator :: (Op -> Parser (a -> a -> a)) -> Op -> Operator Parser a infixToOperator opToParser op = case assoc op of- LeftAssoc -> InfixL (opToParser op)- RightAssoc -> InfixR (opToParser op)- NonAssoc -> InfixN (opToParser op)+ E.InfixL -> InfixL (opToParser op)+ E.InfixR -> InfixR (opToParser op)+ E.InfixN -> InfixN (opToParser op) tupleOrSome :: Parser a -> Parser [a] tupleOrSome p = parens (sepBy p comma) <|> some p
hs-src/Language/Egison/Parser/SExpr.hs view
@@ -1,13 +1,12 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE ViewPatterns #-}-{-# OPTIONS_GHC -Wno-all #-} -- Since we will soon deprecate this parser+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-all #-} -- Since we will soon deprecate this parser {- | Module : Language.Egison.Parser.SExpr Licence : MIT -This module provides Egison parser.+This module implements the parser for the old S-expression syntax. -} module Language.Egison.Parser.SExpr@@ -36,27 +35,26 @@ import qualified Text.Parsec.Token as P import Language.Egison.AST-import Language.Egison.Data -parseTopExprs :: String -> Either EgisonError [EgisonTopExpr]+parseTopExprs :: String -> Either String [TopExpr] parseTopExprs = doParse $ do ret <- whiteSpace >> endBy topExpr whiteSpace eof return ret -parseTopExpr :: String -> Either EgisonError EgisonTopExpr+parseTopExpr :: String -> Either String TopExpr parseTopExpr = doParse $ do ret <- whiteSpace >> topExpr whiteSpace >> eof return ret -parseExprs :: String -> Either EgisonError [EgisonExpr]+parseExprs :: String -> Either String [Expr] parseExprs = doParse $ do ret <- whiteSpace >> endBy expr whiteSpace eof return ret -parseExpr :: String -> Either EgisonError EgisonExpr+parseExpr :: String -> Either String Expr parseExpr = doParse $ do ret <- whiteSpace >> expr whiteSpace >> eof@@ -66,11 +64,8 @@ -- Parser -- -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+doParse :: Parser a -> String -> Either String a+doParse p input = either (throwError . show) return $ parse p "egison" input doParse' :: Parser a -> String -> a doParse' p input = case doParse p input of@@ -79,41 +74,36 @@ -- -- Expressions ---topExpr :: Parser EgisonTopExpr+topExpr :: Parser TopExpr topExpr = try (Test <$> expr) <|> try defineExpr- <|> try (parens (redefineExpr- <|> testExpr+ <|> try (parens (testExpr <|> executeExpr <|> loadFileExpr <|> loadExpr)) <?> "top-level expression" -defineExpr :: Parser EgisonTopExpr-defineExpr = try (parens (keywordDefine >> Define <$> (char '$' >> identVar) <*> expr))- <|> try (parens (keywordDefine >> DefineWithIndices <$> (char '$' >> identVarWithIndices) <*> expr))--redefineExpr :: Parser EgisonTopExpr-redefineExpr = (keywordRedefine <|> keywordSet) >> Redefine <$> (char '$' >> identVar) <*> expr+defineExpr :: Parser TopExpr+defineExpr = parens (keywordDefine >> Define <$> (char '$' >> identVarWithIndices) <*> expr) -testExpr :: Parser EgisonTopExpr+testExpr :: Parser TopExpr testExpr = keywordTest >> Test <$> expr -executeExpr :: Parser EgisonTopExpr+executeExpr :: Parser TopExpr executeExpr = keywordExecute >> Execute <$> expr -loadFileExpr :: Parser EgisonTopExpr+loadFileExpr :: Parser TopExpr loadFileExpr = keywordLoadFile >> LoadFile <$> stringLiteral -loadExpr :: Parser EgisonTopExpr+loadExpr :: Parser TopExpr loadExpr = keywordLoad >> Load <$> stringLiteral -expr :: Parser EgisonExpr+expr :: Parser Expr expr = P.lexeme lexer (do expr0 <- expr' <|> quoteExpr expr1 <- option expr0 $ try (string "..." >> IndexedExpr False expr0 <$> parseindex) <|> IndexedExpr True expr0 <$> parseindex- option expr1 $ PowerExpr expr1 <$> try (char '^' >> expr'))- where parseindex :: Parser [Index EgisonExpr]+ option expr1 $ (\x -> makeApply "**" [expr1, x]) <$> try (char '^' >> expr'))+ where parseindex :: Parser [IndexExpr Expr] parseindex = many1 (try (MultiSubscript <$> (char '_' >> expr') <*> (string "..._" >> expr')) <|> try (MultiSuperscript <$> (char '~' >> expr') <*> (string "...~" >> expr')) <|> try (Subscript <$> (char '_' >> expr'))@@ -122,12 +112,12 @@ <|> try (Userscript <$> (char '|' >> expr'))) -quoteExpr :: Parser EgisonExpr+quoteExpr :: Parser Expr quoteExpr = char '\'' >> QuoteExpr <$> expr' -expr' :: Parser EgisonExpr+expr' :: Parser Expr expr' = try anonParamFuncExpr- <|> try constantExpr+ <|> try (ConstantExpr <$> constantExpr) <|> try anonParamExpr <|> try freshVarExpr <|> try varExpr@@ -148,7 +138,6 @@ <|> letStarExpr <|> withSymbolsExpr <|> doExpr- <|> ioExpr <|> matchAllExpr <|> matchAllDFSExpr <|> matchExpr@@ -173,70 +162,95 @@ ) <?> "expression" -varExpr :: Parser EgisonExpr-varExpr = VarExpr <$> identVarWithoutIndex+varExpr :: Parser Expr+varExpr = VarExpr <$> ident -freshVarExpr :: Parser EgisonExpr+freshVarExpr :: Parser Expr freshVarExpr = char '#' >> return FreshVarExpr -inductiveDataExpr :: Parser EgisonExpr-inductiveDataExpr = angles $ InductiveDataExpr <$> upperName <*> sepEndBy expr whiteSpace+inductiveDataExpr :: Parser Expr+inductiveDataExpr = angles $ do+ name <- upperName+ args <- sepEndBy expr whiteSpace+ return $ makeApply name args -tupleExpr :: Parser EgisonExpr+tupleExpr :: Parser Expr tupleExpr = brackets $ TupleExpr <$> sepEndBy expr whiteSpace -collectionExpr :: Parser EgisonExpr-collectionExpr = braces $ CollectionExpr <$> sepEndBy innerExpr whiteSpace+data InnerExpr+ = ElementExpr Expr+ | SubCollectionExpr Expr++collectionExpr :: Parser Expr+collectionExpr = do+ inners <- braces $ sepEndBy innerExpr whiteSpace+ return $ f [] inners where innerExpr :: Parser InnerExpr innerExpr = (char '@' >> SubCollectionExpr <$> expr) <|> ElementExpr <$> expr -vectorExpr :: Parser EgisonExpr+ isElementExpr :: InnerExpr -> Bool+ isElementExpr ElementExpr{} = True+ isElementExpr _ = False++ f :: [Expr] -> [InnerExpr] -> Expr+ f xs [] = CollectionExpr xs+ f xs [ElementExpr y] = CollectionExpr (xs ++ [y])+ f [] [SubCollectionExpr y] = y+ f [x] [SubCollectionExpr y] = ConsExpr x y+ f xs [SubCollectionExpr y] = JoinExpr (CollectionExpr xs) y+ f xs (ElementExpr y : ys) = f (xs ++ [y]) ys+ f [] (SubCollectionExpr y : ys) = JoinExpr y (f [] ys)+ f [x] (SubCollectionExpr y : ys) = ConsExpr x (JoinExpr y (f [] ys))+ f xs (SubCollectionExpr y : ys) = JoinExpr (CollectionExpr xs) (JoinExpr y (f [] ys))+++vectorExpr :: Parser Expr vectorExpr = between lp rp $ VectorExpr <$> sepEndBy expr whiteSpace where lp = P.lexeme lexer (string "[|") rp = string "|]" -hashExpr :: Parser EgisonExpr+hashExpr :: Parser Expr hashExpr = between lp rp $ HashExpr <$> sepEndBy pairExpr whiteSpace where lp = P.lexeme lexer (string "{|") rp = string "|}"- pairExpr :: Parser (EgisonExpr, EgisonExpr)+ pairExpr :: Parser (Expr, Expr) pairExpr = brackets $ (,) <$> expr <*> expr -wedgeExpr :: Parser EgisonExpr+wedgeExpr :: Parser Expr wedgeExpr = do e <- char '!' >> expr case e of ApplyExpr e1 e2 -> return $ WedgeApplyExpr e1 e2 -functionWithArgExpr :: Parser EgisonExpr-functionWithArgExpr = keywordFunction >> FunctionExpr <$> between lp rp (sepEndBy expr whiteSpace)+functionWithArgExpr :: Parser Expr+functionWithArgExpr = keywordFunction >> FunctionExpr <$> between lp rp (sepEndBy ident whiteSpace) where lp = P.lexeme lexer (char '[') rp = char ']' -quoteSymbolExpr :: Parser EgisonExpr+quoteSymbolExpr :: Parser Expr quoteSymbolExpr = char '`' >> QuoteSymbolExpr <$> expr -matchAllExpr :: Parser EgisonExpr+matchAllExpr :: Parser Expr matchAllExpr = keywordMatchAll >> MatchAllExpr BFSMode <$> expr <*> expr <*> (((:[]) <$> matchClause) <|> matchClauses) -matchAllDFSExpr :: Parser EgisonExpr+matchAllDFSExpr :: Parser Expr matchAllDFSExpr = keywordMatchAllDFS >> MatchAllExpr DFSMode <$> expr <*> expr <*> (((:[]) <$> matchClause) <|> matchClauses) -matchExpr :: Parser EgisonExpr+matchExpr :: Parser Expr matchExpr = keywordMatch >> MatchExpr BFSMode <$> expr <*> expr <*> matchClauses -matchDFSExpr :: Parser EgisonExpr+matchDFSExpr :: Parser Expr matchDFSExpr = keywordMatchDFS >> MatchExpr DFSMode <$> expr <*> expr <*> matchClauses -matchAllLambdaExpr :: Parser EgisonExpr+matchAllLambdaExpr :: Parser Expr matchAllLambdaExpr = keywordMatchAllLambda >> MatchAllLambdaExpr <$> expr <*> (((:[]) <$> matchClause) <|> matchClauses) -matchLambdaExpr :: Parser EgisonExpr+matchLambdaExpr :: Parser Expr matchLambdaExpr = keywordMatchLambda >> MatchLambdaExpr <$> expr <*> matchClauses matchClauses :: Parser [MatchClause]@@ -245,7 +259,7 @@ matchClause :: Parser MatchClause matchClause = brackets $ (,) <$> pattern <*> expr -matcherExpr :: Parser EgisonExpr+matcherExpr :: Parser Expr matcherExpr = keywordMatcher >> MatcherExpr <$> ppMatchClauses ppMatchClauses :: Parser [PatternDef]@@ -254,10 +268,10 @@ ppMatchClause :: Parser PatternDef ppMatchClause = brackets $ (,,) <$> ppPattern <*> expr <*> pdMatchClauses -pdMatchClauses :: Parser [(PrimitiveDataPattern, EgisonExpr)]+pdMatchClauses :: Parser [(PrimitiveDataPattern, Expr)] pdMatchClauses = braces $ sepEndBy pdMatchClause whiteSpace -pdMatchClause :: Parser (PrimitiveDataPattern, EgisonExpr)+pdMatchClause :: Parser (PrimitiveDataPattern, Expr) pdMatchClause = brackets $ (,) <$> pdPattern <*> expr ppPattern :: Parser PrimitivePatPattern@@ -297,100 +311,106 @@ <|> PDConstantPat <$> constantExpr <?> "primitive-data-pattern" -ifExpr :: Parser EgisonExpr+ifExpr :: Parser Expr ifExpr = keywordIf >> IfExpr <$> expr <*> expr <*> expr -lambdaExpr :: Parser EgisonExpr+lambdaExpr :: Parser Expr lambdaExpr = keywordLambda >> LambdaExpr <$> argNames <*> expr -memoizedLambdaExpr :: Parser EgisonExpr+memoizedLambdaExpr :: Parser Expr memoizedLambdaExpr = keywordMemoizedLambda >> MemoizedLambdaExpr <$> varNames <*> expr -memoizeFrame :: Parser [(EgisonExpr, EgisonExpr, EgisonExpr)]+memoizeFrame :: Parser [(Expr, Expr, Expr)] memoizeFrame = braces $ sepEndBy memoizeBinding whiteSpace -memoizeBinding :: Parser (EgisonExpr, EgisonExpr, EgisonExpr)+memoizeBinding :: Parser (Expr, Expr, Expr) memoizeBinding = brackets $ (,,) <$> expr <*> expr <*> expr -cambdaExpr :: Parser EgisonExpr+cambdaExpr :: Parser Expr cambdaExpr = keywordCambda >> char '$' >> CambdaExpr <$> ident <*> expr -patternFunctionExpr :: Parser EgisonExpr+patternFunctionExpr :: Parser Expr patternFunctionExpr = keywordPatternFunction >> PatternFunctionExpr <$> varNames <*> pattern -letRecExpr :: Parser EgisonExpr+letRecExpr :: Parser Expr letRecExpr = keywordLetRec >> LetRecExpr <$> bindings <*> expr -letExpr :: Parser EgisonExpr-letExpr = keywordLet >> LetExpr <$> bindings <*> expr+letExpr :: Parser Expr+letExpr = keywordLet >> LetRecExpr <$> bindings <*> expr -letStarExpr :: Parser EgisonExpr-letStarExpr = keywordLetStar >> LetStarExpr <$> bindings <*> expr+letStarExpr :: Parser Expr+letStarExpr = keywordLetStar >> LetRecExpr <$> bindings <*> expr -withSymbolsExpr :: Parser EgisonExpr+withSymbolsExpr :: Parser Expr withSymbolsExpr = keywordWithSymbols >> WithSymbolsExpr <$> braces (sepEndBy ident whiteSpace) <*> expr -doExpr :: Parser EgisonExpr-doExpr = keywordDo >> DoExpr <$> statements <*> option (ApplyExpr (stringToVarExpr "return") (TupleExpr [])) expr+doExpr :: Parser Expr+doExpr = keywordDo >> DoExpr <$> statements <*> option (makeApply "return" []) expr statements :: Parser [BindingExpr] statements = braces $ sepEndBy statement whiteSpace statement :: Parser BindingExpr statement = try binding- <|> try (brackets (([],) <$> expr))- <|> (([],) <$> expr)+ <|> try (brackets (Bind (PDTuplePat []) <$> expr))+ <|> (Bind (PDTuplePat []) <$> expr) +bindings' :: Parser [(PrimitiveDataPattern, Expr)]+bindings' = braces $ sepEndBy binding' whiteSpace++binding' :: Parser (PrimitiveDataPattern, Expr)+binding' = brackets $ (,) <$> varNames' <*> expr+ bindings :: Parser [BindingExpr] bindings = braces $ sepEndBy binding whiteSpace binding :: Parser BindingExpr-binding = brackets $ (,) <$> varNames' <*> expr+binding = brackets $ Bind <$> varNames' <*> expr varNames :: Parser [String] varNames = return <$> (char '$' >> ident) <|> brackets (sepEndBy (char '$' >> ident) whiteSpace) -varNames' :: Parser [Var]-varNames' = return <$> (char '$' >> identVar)- <|> brackets (sepEndBy (char '$' >> identVar) whiteSpace)+varNames' :: Parser PrimitiveDataPattern+varNames' = PDPatVar <$> (char '$' >> ident)+ <|> PDTuplePat <$> brackets (sepEndBy (PDPatVar <$> (char '$' >> ident)) whiteSpace) -argNames :: Parser [Arg]+argNames :: Parser [Arg ArgPattern] argNames = return <$> argName <|> brackets (sepEndBy argName whiteSpace) -argName :: Parser Arg-argName = try (ScalarArg <$> (char '$' >> ident))- <|> try (InvertedScalarArg <$> (string "*$" >> ident))- <|> try (TensorArg <$> (char '%' >> ident))+argName :: Parser (Arg ArgPattern)+argName = try (ScalarArg <$> (char '$' >> argPattern))+ <|> try (InvertedScalarArg <$> (string "*$" >> argPattern))+ <|> try (TensorArg <$> (char '%' >> argPattern)) -ioExpr :: Parser EgisonExpr-ioExpr = keywordIo >> IoExpr <$> expr+argPattern :: Parser ArgPattern+argPattern = APPatVar <$> ident -seqExpr :: Parser EgisonExpr+seqExpr :: Parser Expr seqExpr = keywordSeq >> SeqExpr <$> expr <*> expr -cApplyExpr :: Parser EgisonExpr+cApplyExpr :: Parser Expr cApplyExpr = keywordCApply >> CApplyExpr <$> expr <*> expr -applyExpr :: Parser EgisonExpr+applyExpr :: Parser Expr applyExpr = do func <- expr args <- sepEndBy arg whiteSpace let vars = lefts args case vars of- [] -> return . ApplyExpr func . TupleExpr $ rights args+ [] -> return $ ApplyExpr func (rights args) _ | all null vars -> let n = toInteger (length vars) args' = f args 1- in return $ AnonParamFuncExpr n $ ApplyExpr func (TupleExpr args')+ in return $ AnonParamFuncExpr n $ ApplyExpr func args' | all (not . null) vars -> let ns = Set.fromList $ map read vars n = Set.size ns in if Set.findMin ns == 1 && Set.findMax ns == n then let args' = map g args- in return $ AnonParamFuncExpr (toInteger n) $ ApplyExpr func (TupleExpr args')+ in return $ AnonParamFuncExpr (toInteger n) $ ApplyExpr func args' else fail "invalid anonymous parameter function" | otherwise -> fail "invalid anonymous parameter function" where@@ -403,59 +423,58 @@ g (Left arg) = AnonParamExpr (read arg) g (Right expr) = expr -anonParamFuncExpr :: Parser EgisonExpr+anonParamFuncExpr :: Parser Expr anonParamFuncExpr = (AnonParamFuncExpr . read <$> index) <*> (char '#' >> expr) where index = (:) <$> satisfy (\c -> '1' <= c && c <= '9') <*> many digit -anonParamExpr :: Parser EgisonExpr+anonParamExpr :: Parser Expr anonParamExpr = char '%' >> AnonParamExpr <$> integerLiteral -algebraicDataMatcherExpr :: Parser EgisonExpr+algebraicDataMatcherExpr :: Parser Expr algebraicDataMatcherExpr = keywordAlgebraicDataMatcher >> braces (AlgebraicDataMatcherExpr <$> sepEndBy1 inductivePat' whiteSpace) where- inductivePat' :: Parser (String, [EgisonExpr])+ inductivePat' :: Parser (String, [Expr]) inductivePat' = angles $ (,) <$> lowerName <*> sepEndBy expr whiteSpace -generateTensorExpr :: Parser EgisonExpr+generateTensorExpr :: Parser Expr generateTensorExpr = keywordGenerateTensor >> GenerateTensorExpr <$> expr <*> expr -tensorExpr :: Parser EgisonExpr+tensorExpr :: Parser Expr tensorExpr = keywordTensor >> TensorExpr <$> expr <*> expr -tensorContractExpr :: Parser EgisonExpr+tensorContractExpr :: Parser Expr tensorContractExpr = keywordTensorContract >> TensorContractExpr <$> expr---tensorContractExpr = keywordTensorContract >> TensorContractExpr <$> expr <*> expr -tensorMapExpr :: Parser EgisonExpr+tensorMapExpr :: Parser Expr tensorMapExpr = keywordTensorMap >> TensorMapExpr <$> expr <*> expr -tensorMap2Expr :: Parser EgisonExpr+tensorMap2Expr :: Parser Expr tensorMap2Expr = keywordTensorMap2 >> TensorMap2Expr <$> expr <*> expr <*> expr -transposeExpr :: Parser EgisonExpr+transposeExpr :: Parser Expr transposeExpr = keywordTranspose >> TransposeExpr <$> expr <*> expr -subrefsExpr :: Parser EgisonExpr+subrefsExpr :: Parser Expr subrefsExpr = (keywordSubrefs >> SubrefsExpr False <$> expr <*> expr) <|> (keywordSubrefsNew >> SubrefsExpr True <$> expr <*> expr) -suprefsExpr :: Parser EgisonExpr+suprefsExpr :: Parser Expr suprefsExpr = (keywordSuprefs >> SuprefsExpr False <$> expr <*> expr) <|> (keywordSuprefsNew >> SuprefsExpr True <$> expr <*> expr) -userrefsExpr :: Parser EgisonExpr+userrefsExpr :: Parser Expr userrefsExpr = (keywordUserrefs >> UserrefsExpr False <$> expr <*> expr) <|> (keywordUserrefsNew >> UserrefsExpr True <$> expr <*> expr) -- Patterns -pattern :: Parser EgisonPattern+pattern :: Parser Pattern pattern = P.lexeme lexer (do pattern <- pattern' option pattern $ IndexedPat pattern <$> many1 (try $ char '_' >> expr')) -pattern' :: Parser EgisonPattern+pattern' :: Parser Pattern pattern' = wildCard <|> contPat <|> patVar@@ -474,127 +493,104 @@ <|> orPat <|> loopPat <|> letPat- <|> try divPat- <|> try plusPat- <|> try multPat <|> try dApplyPat <|> try pApplyPat ) -pattern'' :: Parser EgisonPattern+pattern'' :: Parser Pattern pattern'' = wildCard <|> patVar <|> valuePat -wildCard :: Parser EgisonPattern+wildCard :: Parser Pattern wildCard = reservedOp "_" >> pure WildCard -patVar :: Parser EgisonPattern-patVar = char '$' >> PatVar <$> identVarWithoutIndex+patVar :: Parser Pattern+patVar = char '$' >> PatVar <$> ident -varPat :: Parser EgisonPattern+varPat :: Parser Pattern varPat = VarPat <$> ident -valuePat :: Parser EgisonPattern+valuePat :: Parser Pattern valuePat = char ',' >> ValuePat <$> expr -predPat :: Parser EgisonPattern+predPat :: Parser Pattern predPat = char '?' >> PredPat <$> expr -letPat :: Parser EgisonPattern+letPat :: Parser Pattern letPat = keywordLet >> LetPat <$> bindings <*> pattern -notPat :: Parser EgisonPattern+notPat :: Parser Pattern notPat = char '!' >> NotPat <$> pattern -notPat' :: Parser EgisonPattern+notPat' :: Parser Pattern notPat' = keywordNot >> NotPat <$> pattern -tuplePat :: Parser EgisonPattern+tuplePat :: Parser Pattern tuplePat = brackets $ TuplePat <$> sepEndBy pattern whiteSpace -inductivePat :: Parser EgisonPattern+inductivePat :: Parser Pattern inductivePat = angles $ InductivePat <$> lowerName <*> sepEndBy pattern whiteSpace -contPat :: Parser EgisonPattern+contPat :: Parser Pattern contPat = keywordCont >> pure ContPat -andPat :: Parser EgisonPattern-andPat = (reservedOp "&" <|> keywordAnd) >> AndPat <$> sepEndBy pattern whiteSpace+andPat :: Parser Pattern+andPat = do+ pats <- (reservedOp "&" <|> keywordAnd) >> sepEndBy pattern whiteSpace+ case pats of+ [] -> return WildCard+ _ -> return $ foldr1 AndPat pats -orPat :: Parser EgisonPattern-orPat = (reservedOp "|" <|> keywordOr) >> OrPat <$> sepEndBy pattern whiteSpace+orPat :: Parser Pattern+orPat = do+ pats <- (reservedOp "|" <|> keywordOr) >> sepEndBy pattern whiteSpace+ case pats of+ [] -> return (NotPat WildCard)+ _ -> return $ foldr1 OrPat pats -pApplyPat :: Parser EgisonPattern+pApplyPat :: Parser Pattern pApplyPat = PApplyPat <$> expr <*> sepEndBy pattern whiteSpace -dApplyPat :: Parser EgisonPattern+dApplyPat :: Parser Pattern dApplyPat = DApplyPat <$> pattern'' <*> sepEndBy pattern whiteSpace -loopPat :: Parser EgisonPattern-loopPat = keywordLoop >> char '$' >> LoopPat <$> identVarWithoutIndex <*> loopRange <*> pattern <*> option (NotPat WildCard) pattern+loopPat :: Parser Pattern+loopPat = keywordLoop >> char '$' >> LoopPat <$> ident <*> loopRange <*> pattern <*> option (NotPat WildCard) pattern loopRange :: Parser LoopRange loopRange = brackets (try (LoopRange <$> expr <*> expr <*> option WildCard pattern) <|> (do s <- expr ep <- option WildCard pattern- return (LoopRange s (ApplyExpr (stringToVarExpr "from") (ApplyExpr (stringToVarExpr "-'") (TupleExpr [s, IntegerExpr 1]))) ep)))+ return (LoopRange s (makeApply "from" [makeApply "-'" [s, ConstantExpr (IntegerExpr 1)]]) ep))) -seqNilPat :: Parser EgisonPattern+seqNilPat :: Parser Pattern seqNilPat = braces $ pure SeqNilPat -seqConsPat :: Parser EgisonPattern+seqConsPat :: Parser Pattern seqConsPat = braces $ SeqConsPat <$> pattern <*> (char '@' >> pattern) -seqPat :: Parser EgisonPattern+seqPat :: Parser Pattern seqPat = braces $ do pats <- sepEndBy pattern whiteSpace tailPat <- option SeqNilPat (char '@' >> pattern) return $ foldr SeqConsPat tailPat pats -laterPatVar :: Parser EgisonPattern+laterPatVar :: Parser Pattern laterPatVar = char '#' >> pure LaterPatVar -divPat :: Parser EgisonPattern-divPat = reservedOp "/" >> DivPat <$> pattern <*> pattern--plusPat :: Parser EgisonPattern-plusPat = reservedOp "+" >> PlusPat <$> sepEndBy pattern whiteSpace--multPat :: Parser EgisonPattern-multPat = reservedOp "*" >> MultPat <$> sepEndBy powerPat whiteSpace--powerPat :: Parser EgisonPattern-powerPat = try (PowerPat <$> pattern <* char '^' <*> pattern)- <|> pattern- -- Constants -constantExpr :: Parser EgisonExpr-constantExpr = stringExpr- <|> boolExpr- <|> try charExpr- <|> try floatExpr- <|> try integerExpr+constantExpr :: Parser ConstantExpr+constantExpr = StringExpr . T.pack <$> stringLiteral+ <|> BoolExpr <$> boolLiteral+ <|> try (CharExpr <$> oneChar)+ <|> try (FloatExpr <$> positiveFloatLiteral)+ <|> try (IntegerExpr <$> integerLiteral) <|> (keywordSomething $> SomethingExpr) <|> (keywordUndefined $> UndefinedExpr) <?> "constant" -charExpr :: Parser EgisonExpr-charExpr = CharExpr <$> oneChar--stringExpr :: Parser EgisonExpr-stringExpr = StringExpr . T.pack <$> stringLiteral--boolExpr :: Parser EgisonExpr-boolExpr = BoolExpr <$> boolLiteral--floatExpr :: Parser EgisonExpr-floatExpr = FloatExpr <$> positiveFloatLiteral--integerExpr :: Parser EgisonExpr-integerExpr = IntegerExpr <$> integerLiteral- positiveFloatLiteral :: Parser Double positiveFloatLiteral = do n <- integerLiteral@@ -634,7 +630,6 @@ reservedKeywords :: [String] reservedKeywords = [ "define"- , "redefine" , "set!" , "test" , "execute"@@ -664,7 +659,6 @@ , "match-lambda" , "matcher" , "do"- , "io" , "algebraic-data-matcher" , "generate-tensor" , "tensor"@@ -704,7 +698,6 @@ reservedOp = P.reservedOp lexer keywordDefine = reserved "define"-keywordRedefine = reserved "redefine" keywordSet = reserved "set!" keywordTest = reserved "test" keywordExecute = reserved "execute"@@ -794,26 +787,17 @@ ident :: Parser String ident = toCamelCase <$> P.identifier lexer -identVar :: Parser Var-identVar = P.lexeme lexer (do- name <- ident- is <- many indexType- return $ Var (splitOn "." name) is)--identVarWithoutIndex :: Parser Var-identVarWithoutIndex = stringToVar <$> ident- identVarWithIndices :: Parser VarWithIndices identVarWithIndices = P.lexeme lexer (do name <- ident is <- many indexForVar- return $ VarWithIndices (splitOn "." name) is)+ return $ VarWithIndices name is) -indexForVar :: Parser (Index String)-indexForVar = try (char '~' >> Superscript <$> ident)- <|> try (char '_' >> Subscript <$> ident)+indexForVar :: Parser VarIndex+indexForVar = try (char '~' >> VSuperscript <$> ident)+ <|> try (char '_' >> VSubscript <$> ident) -indexType :: Parser (Index ())+indexType :: Parser (IndexExpr ()) indexType = try (char '~' >> return (Superscript ())) <|> try (char '_' >> return (Subscript ()))
hs-src/Language/Egison/Pretty.hs view
@@ -1,5 +1,9 @@-{-# LANGUAGE FlexibleInstances #-}-{-# OPTIONS_GHC -Wno-orphans #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -Wno-orphans #-} {- | Module : Language.Egison.PrettyPrint@@ -10,47 +14,49 @@ module Language.Egison.Pretty ( prettyTopExprs- , PrettyS(..) , prettyStr- , prettyStr' , showTSV ) where import Data.Foldable (toList)-import qualified Data.HashMap.Strict as HashMap import Data.List (intercalate) import Data.Text.Prettyprint.Doc import Data.Text.Prettyprint.Doc.Render.String (renderString)-import qualified Data.Vector as V+import Text.Show.Unicode (ushow) import Language.Egison.AST-import Language.Egison.MathExpr hiding (Printable(..)) import Language.Egison.Data+import Language.Egison.IExpr -- -- Pretty printing for Non-S syntax -- -prettyTopExprs :: [EgisonTopExpr] -> Doc [EgisonTopExpr]+prettyTopExprs :: [TopExpr] -> Doc [TopExpr] prettyTopExprs exprs = vsep $ punctuate line (map pretty exprs) -instance Pretty EgisonTopExpr where+instance Pretty TopExpr where pretty (Define x (LambdaExpr args body)) =- hsep (pretty x : map pretty args) <+> indentBlock (pretty ":=") [pretty body]+ hsep (pretty "def" : pretty x : map pretty' args) <+> indentBlock (pretty ":=") [pretty body] pretty (Define x expr) =- pretty x <+> indentBlock (pretty ":=") [pretty expr]+ pretty "def" <+> pretty x <+> indentBlock (pretty ":=") [pretty expr] pretty (Test expr) = pretty expr pretty (LoadFile file) = pretty "loadFile" <+> pretty (show file) pretty (Load lib) = pretty "load" <+> pretty (show lib) pretty _ = error "Unsupported topexpr" -instance Pretty EgisonExpr where- -- Use |viaShow| to correctly handle escaped characters+instance Pretty ConstantExpr where pretty (CharExpr x) = viaShow x- pretty (StringExpr x) = viaShow x+ pretty (StringExpr x) = pretty (ushow x) pretty (BoolExpr x) = pretty x pretty (IntegerExpr x) = pretty x pretty (FloatExpr x) = pretty x+ pretty SomethingExpr = pretty "something"+ pretty UndefinedExpr = pretty "undefined"++instance Pretty Expr where+ pretty (ConstantExpr c) = pretty c+ -- Use |viaShow| to correctly handle escaped characters pretty (VarExpr x) = pretty x pretty FreshVarExpr = pretty "#" pretty (IndexedExpr True e indices) = pretty' e <> cat (map pretty indices)@@ -65,8 +71,6 @@ applyLike [pretty "userRefs" <> (if b then pretty "!" else emptyDoc), pretty' e1, pretty' e2] - pretty (InductiveDataExpr c xs) = nest 2 (sep (pretty c : map pretty' xs))- pretty (TupleExpr xs) = tupled (map pretty xs) pretty (CollectionExpr xs) | length xs < 20 = list (map pretty xs)@@ -89,8 +93,6 @@ [pretty "then" <+> pretty y, pretty "else" <+> pretty z] pretty (LetRecExpr bindings body) = hang 1 (pretty "let" <+> align (vsep (map pretty bindings)) <> hardline <> pretty "in" <+> align (pretty body))- pretty (LetExpr _ _) = error "unreachable"- pretty (LetStarExpr _ _) = error "unreachable" pretty (WithSymbolsExpr xs e) = indentBlock (pretty "withSymbols" <+> list (map pretty xs)) [pretty e] @@ -125,18 +127,18 @@ pretty (QuoteExpr e) = squote <> pretty' e pretty (QuoteSymbolExpr e) = pretty '`' <> pretty' e - pretty (PrefixExpr op x@(IntegerExpr _)) = pretty op <> pretty x+ pretty (PrefixExpr op x@(ConstantExpr (IntegerExpr _))) = pretty op <> pretty x pretty (PrefixExpr op x) | isAtomOrApp x = pretty op <+> pretty x | otherwise = pretty op <+> parens (pretty x) -- (x1 op' x2) op y pretty (InfixExpr op x@(InfixExpr op' _ _) y) =- if priority op > priority op' || priority op == priority op' && assoc op == RightAssoc+ if priority op > priority op' || priority op == priority op' && assoc op == InfixR then parens (pretty x) <+> pretty op <> infixRight (pretty'' y) else pretty x <+> pretty op <> infixRight (pretty'' y) -- x op (y1 op' y2) pretty (InfixExpr op x y@(InfixExpr op' _ _)) =- if priority op > priority op' || priority op == priority op' && assoc op == LeftAssoc+ if priority op > priority op' || priority op == priority op' && assoc op == InfixL then pretty'' x <+> pretty op <> infixRight (parens (pretty y)) else pretty'' x <+> pretty op <> infixRight (pretty y) pretty (InfixExpr op x y) =@@ -146,15 +148,12 @@ pretty (SectionExpr op Nothing (Just x)) = parens (pretty op <+> pretty x) pretty (DoExpr [] y) = pretty "do" <+> pretty y- pretty (DoExpr xs (ApplyExpr (VarExpr (Var ["return"] [])) (TupleExpr []))) =+ pretty (DoExpr xs (ApplyExpr (VarExpr "return") [])) = pretty "do" <+> align (hsepHard (map prettyDoBinds xs)) pretty (DoExpr xs y) = pretty "do" <+> align (hsepHard (map prettyDoBinds xs ++ [pretty y]))- pretty (IoExpr x) = pretty "io" <+> pretty x pretty (SeqExpr e1 e2) = applyLike [pretty "seq", pretty' e1, pretty' e2]- pretty (ApplyExpr x y@(TupleExpr [])) = applyLike (map pretty' [x, y])- pretty (ApplyExpr x (TupleExpr ys)) = applyLike (map pretty' (x : ys))- pretty (ApplyExpr x y) = applyLike [pretty' x, pretty' y]+ pretty (ApplyExpr x ys) = applyLike (map pretty' (x : ys)) pretty (CApplyExpr e1 e2) = applyLike [pretty "capply", pretty' e1, pretty' e2] pretty (AnonParamFuncExpr n e) = pretty n <> pretty '#' <> pretty' e pretty (AnonParamExpr n) = pretty '%' <> pretty n@@ -175,64 +174,57 @@ pretty (FunctionExpr xs) = pretty "function" <+> tupled (map pretty xs) - pretty SomethingExpr = pretty "something"- pretty UndefinedExpr = pretty "undefined"-- pretty _ = pretty "REPLACEME"+ pretty p = pretty (show p) -instance Pretty Arg where- pretty (ScalarArg x) = pretty x- pretty (InvertedScalarArg x) = pretty "*" <> pretty x- pretty (TensorArg x) = pretty '%' <> pretty x+instance (Pretty a, Complex a) => Pretty (Arg a) where+ pretty (ScalarArg x) = pretty "$" <> pretty' x+ pretty (InvertedScalarArg x) = pretty "*$" <> pretty' x+ pretty (TensorArg x) = pretty x -instance Pretty Var where- pretty (Var xs is) =- concatWith (surround dot) (map pretty xs) <> hcat (map pretty is)+instance Pretty ArgPattern where+ pretty APWildCard = pretty "_"+ pretty (APPatVar x) = pretty x+ pretty (APInductivePat x args) = applyLike (pretty x : map pretty' args)+ pretty (APTuplePat args) = tupled (map pretty args)+ pretty APEmptyPat = pretty "[]"+ pretty (APConsPat arg1 arg2) = pretty'' arg1 <+> pretty "::" <+> pretty'' arg2+ pretty (APSnocPat arg1 arg2) = applyLike [pretty "snoc", pretty' arg1, pretty' arg2] instance Pretty VarWithIndices where- pretty (VarWithIndices xs is) =- concatWith (surround dot) (map pretty xs) <> hcat (map pretty is)+ pretty (VarWithIndices xs is) = pretty xs <> hcat (map pretty is) -instance Pretty InnerExpr where- pretty (ElementExpr x) = pretty x- pretty (SubCollectionExpr _) = error "Not supported"+instance Pretty VarIndex where+ pretty (VSubscript x) = pretty ('_' : x)+ pretty (VSuperscript x) = pretty ('~' : x)+ pretty (VSymmScripts xs) = pretty '{' <> hcat (map pretty xs) <> pretty '}'+ pretty (VAntiSymmScripts xs) = pretty '[' <> hcat (map pretty xs) <> pretty ']' -instance {-# OVERLAPPING #-} Pretty BindingExpr where- pretty ([var], LambdaExpr args body) =- hsep (pretty var : map pretty args) <+> indentBlock (pretty ":=") [pretty body]- pretty ([var], expr) = pretty var <+> pretty ":=" <+> align (pretty expr)- pretty (vars, expr) = tupled (map pretty vars) <+> pretty ":=" <+> align (pretty expr)+instance Pretty BindingExpr where+ pretty (Bind (PDPatVar f) (LambdaExpr args body)) =+ hsep (pretty f : map pretty' args) <+> indentBlock (pretty ":=") [pretty body]+ pretty (Bind pat expr) = pretty pat <+> pretty ":=" <+> align (pretty expr)+ pretty (BindWithIndices var expr) = pretty var <+> pretty ":=" <+> align (pretty expr) instance {-# OVERLAPPING #-} Pretty MatchClause where pretty (pat, expr) = pipe <+> align (pretty pat) <+> indentBlock (pretty "->") [pretty expr] -instance {-# OVERLAPPING #-} Pretty (Index ()) where -- Used for 'Var'- pretty Subscript{} = pretty '_'- pretty Superscript{} = pretty '~'- pretty SupSubscript{} = pretty "~_"- pretty DFscript{} = pretty ""- pretty Userscript{} = pretty '|'- pretty _ = undefined--instance {-# OVERLAPPING #-} Pretty (Index String) where -- for 'VarWithIndices'+instance {-# OVERLAPPING #-} Pretty (IndexExpr String) where -- for 'VarWithIndices' pretty (Superscript s) = pretty ("~" ++ s) pretty (Subscript s) = pretty ("_" ++ s) pretty (SupSubscript s) = pretty ("~_" ++ s)- pretty (DFscript _ _) = pretty "" pretty (Userscript i) = pretty ("|" ++ show i) pretty _ = undefined -instance (Pretty a, Complex a) => Pretty (Index a) where+instance (Pretty a, Complex a) => Pretty (IndexExpr a) where pretty (Subscript i) = pretty '_' <> pretty' i pretty (Superscript i) = pretty '~' <> pretty' i pretty (SupSubscript i) = pretty "~_" <> pretty' i pretty (MultiSubscript i j) = pretty '_' <> pretty' i <> pretty "..._" <> pretty' j pretty (MultiSuperscript i j) = pretty '~' <> pretty' i <> pretty "...~" <> pretty' j- pretty (DFscript _ _) = undefined pretty (Userscript i) = pretty '|' <> pretty' i -instance Pretty EgisonPattern where+instance Pretty Pattern where pretty WildCard = pretty "_" pretty (PatVar x) = pretty "$" <> pretty x pretty (ValuePat v) = pretty "#" <> pretty' v@@ -243,19 +235,19 @@ pretty "let" <+> align (vsep (map pretty binds)) <+> pretty "in" <+> pretty pat -- (p11 op' p12) op p2 pretty (InfixPat op p1@(InfixPat op' _ _) p2) =- if priority op > priority op' || priority op == priority op' && assoc op == RightAssoc+ if priority op > priority op' || priority op == priority op' && assoc op == InfixR then parens (pretty p1) <+> pretty (repr op) <+> pretty'' p2 else pretty p1 <+> pretty (repr op) <+> pretty'' p2 -- p1 op (p21 op' p22) pretty (InfixPat op p1 p2@(InfixPat op' _ _)) =- if priority op > priority op' || priority op == priority op' && assoc op == LeftAssoc+ if priority op > priority op' || priority op == priority op' && assoc op == InfixL then pretty'' p1 <+> pretty (repr op) <+> parens (pretty p2) else pretty'' p1 <+> pretty (repr op) <+> pretty p2 pretty (InfixPat op p1 p2) = pretty'' p1 <+> pretty (repr op) <+> pretty'' p2 pretty (NotPat pat) = pretty "!" <> pretty' pat pretty (TuplePat pats) = tupled $ map pretty pats pretty (InductivePat "nil" []) = pretty "[]"- pretty (InductivePat "cons" [p, InductivePat "nil" []]) = pretty "[" <> pretty p <> pretty "]"+ pretty (InductivePat "::" [p, InductivePat "nil" []]) = pretty "[" <> pretty p <> pretty "]" pretty (InductivePat ctor xs) = hsep (pretty ctor : map pretty' xs) pretty (LoopPat i range p1 p2) = hang 2 (pretty "loop" <+> pretty '$' <> pretty i <+> pretty range <>@@ -272,11 +264,11 @@ f p1 p2 = [pretty p1, pretty p2] pretty LaterPatVar = pretty "@" pretty (DApplyPat p ps) = applyLike (map pretty' (p : ps))- pretty _ = pretty "REPLACEME"+ pretty e = pretty (show e) -instance Pretty LoopRange where- pretty (LoopRange from (ApplyExpr (VarExpr (Var ["from"] []))- (InfixExpr (Infix { repr = "-'" }) _ (IntegerExpr 1))) pat) =+instance {-# OVERLAPPING #-} Pretty LoopRange where+ pretty (LoopRange from (ApplyExpr (VarExpr "from")+ [InfixExpr Op{ repr = "-'" } _ (ConstantExpr (IntegerExpr 1))]) pat) = tupled [pretty from, pretty pat] pretty (LoopRange from to pat) = tupled [pretty from, pretty to, pretty pat] @@ -289,7 +281,7 @@ instance Pretty PrimitiveDataPattern where pretty PDWildCard = pretty "_"- pretty (PDPatVar x) = pretty ('$' : x)+ pretty (PDPatVar x) = pretty x pretty (PDInductivePat x pdpats) = applyLike (pretty x : map pretty' pdpats) pretty (PDTuplePat pdpats) = tupled (map pretty pdpats) pretty PDEmptyPat = pretty "[]"@@ -297,21 +289,28 @@ pretty (PDSnocPat pdp1 pdp2) = applyLike [pretty "snoc", pretty' pdp1, pretty' pdp2] pretty (PDConstantPat expr) = pretty expr -instance Pretty Infix where+instance Pretty Op where pretty op | isWedge op = pretty ("!" ++ repr op) | otherwise = pretty (repr op) +instance Pretty IExpr where+ pretty = undefined++instance Complex IExpr where+ isAtom = undefined+ isAtomOrApp = undefined+ isInfix = undefined+ class Complex a where isAtom :: a -> Bool isAtomOrApp :: a -> Bool isInfix :: a -> Bool -instance Complex EgisonExpr where- isAtom (IntegerExpr i) | i < 0 = False- isAtom (InductiveDataExpr _ []) = True- isAtom (InductiveDataExpr _ _) = False+instance Complex Expr where+ isAtom (ConstantExpr (IntegerExpr i)) | i < 0 = False isAtom PrefixExpr{} = False isAtom InfixExpr{} = False+ isAtom (ApplyExpr _ []) = True isAtom ApplyExpr{} = False isAtom CApplyExpr{} = False isAtom LambdaExpr{} = False@@ -340,13 +339,30 @@ isAtom _ = True isAtomOrApp ApplyExpr{} = True- isAtomOrApp InductiveDataExpr{} = True isAtomOrApp e = isAtom e isInfix InfixExpr{} = True isInfix _ = False -instance Complex EgisonPattern where+instance Complex a => Complex (Arg a) where+ isAtom (TensorArg x) = isAtom x+ isAtom _ = True++ isAtomOrApp = isAtom++ isInfix _ = False++instance Complex ArgPattern where+ isAtom (APInductivePat _ []) = True+ isAtom APInductivePat{} = False+ isAtom APConsPat{} = False+ isAtom APSnocPat{} = False+ isAtom _ = True++ isAtomOrApp = isAtom+ isInfix _ = False++instance Complex Pattern where isAtom (LetPat _ _) = False isAtom (InductivePat _ []) = True isAtom (InductivePat _ _) = False@@ -356,12 +372,12 @@ isAtom (PApplyPat _ _) = False isAtom _ = True - isAtomOrApp PApplyPat{} = True+ isAtomOrApp PApplyPat{} = True isAtomOrApp InductivePat{} = True- isAtomOrApp e = isAtom e+ isAtomOrApp e = isAtom e - isInfix (InfixPat _ _ _) = True- isInfix _ = False+ isInfix InfixPat{} = True+ isInfix _ = False instance Complex PrimitiveDataPattern where isAtom (PDInductivePat _ []) = True@@ -374,8 +390,8 @@ isAtomOrApp PDSnocPat{} = True isAtomOrApp e = isAtom e - isInfix (PDConsPat _ _) = True- isInfix _ = False+ isInfix PDConsPat{} = True+ isInfix _ = False pretty' :: (Pretty a, Complex a) => a -> Doc ann pretty' x | isAtom x = pretty x@@ -387,10 +403,10 @@ -- Display "hoge" instead of "() := hoge" prettyDoBinds :: BindingExpr -> Doc ann-prettyDoBinds ([], expr) = pretty expr-prettyDoBinds (vs, expr) = pretty "let" <+> pretty (vs, expr)+prettyDoBinds (Bind (PDTuplePat []) expr) = pretty expr+prettyDoBinds bind = pretty "let" <+> pretty bind -prettyMatch :: EgisonExpr -> [MatchClause] -> Doc ann+prettyMatch :: Expr -> [MatchClause] -> Doc ann prettyMatch matcher clauses = pretty "as" <> group (flatAlt (hardline <> pretty matcher) (space <> pretty matcher) <+> pretty "with") <> hardline <> align (vsep (map pretty clauses))@@ -431,113 +447,14 @@ infixRight :: Doc ann -> Doc ann infixRight p = group (flatAlt (hardline <> p) (space <> p)) +showTSV :: EgisonValue -> String+showTSV (Tuple (val:vals)) = foldl (\r x -> r ++ "\t" ++ x) (show val) (map show vals)+showTSV (Collection vals) = intercalate "\t" (map show (toList vals))+showTSV val = show val+ -- -- Pretty printer for error messages -- prettyStr :: Pretty a => a -> String prettyStr = renderString . layoutPretty (LayoutOptions Unbounded) . pretty--prettyStr' :: (Pretty a, Complex a) => a -> String-prettyStr' = renderString . layoutPretty (LayoutOptions Unbounded) . pretty'------- Pretty printer for S-expression-----class PrettyS a where- prettyS :: a -> String--instance PrettyS EgisonValue where- prettyS (Char c) = "c#" ++ [c]- prettyS (String str) = show str- prettyS (Bool True) = "#t"- prettyS (Bool False) = "#f"- prettyS (ScalarData mExpr) = prettyS mExpr- prettyS (TensorData (Tensor [_] xs js)) = "[| " ++ unwords (map prettyS (V.toList xs)) ++ " |]" ++ concatMap prettyS js- prettyS (TensorData (Tensor [0, 0] _ js)) = "[| [| |] |]" ++ concatMap prettyS js- prettyS (TensorData (Tensor [_, j] xs js)) = "[| " ++ f (fromIntegral j) (V.toList xs) ++ "|]" ++ concatMap prettyS js- where- f _ [] = ""- f j xs = "[| " ++ unwords (map prettyS (take j xs)) ++ " |] " ++ f j (drop j xs)- prettyS (TensorData (Tensor ns xs js)) = "(tensor {" ++ unwords (map show ns) ++ "} {" ++ unwords (map prettyS (V.toList xs)) ++ "} )" ++ concatMap prettyS js- prettyS (Float x) = show x- prettyS (InductiveData name vals) = "<" ++ name ++ concatMap ((' ':) . prettyS) vals ++ ">"- prettyS (Tuple vals) = "[" ++ unwords (map prettyS vals) ++ "]"- prettyS (Collection vals) = "{" ++ unwords (map prettyS (toList vals)) ++ "}"- prettyS (IntHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}"- prettyS (CharHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}"- prettyS (StrHash hash) = "{|" ++ unwords (map (\(key, val) -> "[" ++ show key ++ " " ++ prettyS val ++ "]") $ HashMap.toList hash) ++ "|}"- prettyS UserMatcher{} = "#<user-matcher>"- prettyS (Func Nothing _ args _) = "(lambda [" ++ unwords (map ('$':) args) ++ "] ...)"- prettyS (Func (Just name) _ _ _) = prettyS name- prettyS (AnonParamFunc _ n _) = show n ++ "#(...)"- prettyS (CFunc Nothing _ name _) = "(cambda " ++ name ++ " ...)"- prettyS (CFunc (Just name) _ _ _) = prettyS name- prettyS (MemoizedFunc Nothing _ _ _ names _) = "(memoized-lambda [" ++ unwords names ++ "] ...)"- prettyS (MemoizedFunc (Just name) _ _ _ _ _) = prettyS name- prettyS PatternFunc{} = "#<pattern-function>"- prettyS (PrimitiveFunc name _) = "#<primitive-function " ++ name ++ ">"- prettyS (IOFunc _) = "#<io-function>"- prettyS (Port _) = "#<port>"- prettyS Something = "something"- prettyS Undefined = "undefined"- prettyS World = "#<world>"- prettyS _ = "(not supported)"--instance PrettyS Var where- prettyS = show--instance PrettyS ScalarData where- prettyS (Div p1 (Plus [Term 1 []])) = prettyS p1- prettyS (Div p1 p2) = "(/ " ++ prettyS p1 ++ " " ++ prettyS p2 ++ ")"--instance PrettyS PolyExpr where- prettyS (Plus []) = "0"- prettyS (Plus [t]) = prettyS t- prettyS (Plus ts) = "(+ " ++ unwords (map prettyS ts) ++ ")"--instance PrettyS TermExpr where- prettyS (Term a []) = show a- prettyS (Term 1 [x]) = showPoweredSymbol x- prettyS (Term 1 xs) = "(* " ++ unwords (map showPoweredSymbol xs) ++ ")"- prettyS (Term a xs) = "(* " ++ show a ++ " " ++ unwords (map showPoweredSymbol xs) ++ ")"--showPoweredSymbol :: (SymbolExpr, Integer) -> String-showPoweredSymbol (x, 1) = prettyS x-showPoweredSymbol (x, n) = prettyS x ++ "^" ++ show n--instance PrettyS SymbolExpr where- prettyS (Symbol _ (':':':':':':_) []) = "#"- prettyS (Symbol _ s []) = s- prettyS (Symbol _ s js) = s ++ concatMap prettyS js- prettyS (Apply fn mExprs) = "(" ++ prettyS fn ++ " " ++ unwords (map prettyS mExprs) ++ ")"- prettyS (Quote mExprs) = "'" ++ prettyS mExprs- prettyS (FunctionData name _ _ js) = show name ++ concatMap prettyS js--showTSV :: EgisonValue -> String-showTSV (Tuple (val:vals)) = foldl (\r x -> r ++ "\t" ++ x) (prettyS val) (map prettyS vals)-showTSV (Collection vals) = intercalate "\t" (map prettyS (toList vals))-showTSV val = prettyS val--instance PrettyS a => PrettyS (Index a) where- prettyS (Subscript i) = "_" ++ prettyS i- prettyS (Superscript i) = "~" ++ prettyS i- prettyS (SupSubscript i) = "~_" ++ prettyS i- prettyS (MultiSubscript x y) = "_[" ++ prettyS x ++ "]..._[" ++ prettyS y ++ "]"- prettyS (MultiSuperscript x y) = "~[" ++ prettyS x ++ "]...~[" ++ prettyS y ++ "]"- prettyS (DFscript _ _) = ""- prettyS (Userscript i) = "|" ++ prettyS i--instance {-# OVERLAPPING #-} PrettyS (Index EgisonValue) where- prettyS (Superscript i) = case i of- ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "~[" ++ prettyS i ++ "]"- _ -> "~" ++ prettyS i- prettyS (Subscript i) = case i of- ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "_[" ++ prettyS i ++ "]"- _ -> "_" ++ prettyS i- prettyS (SupSubscript i) = "~_" ++ prettyS i- prettyS (DFscript i j) = "_d" ++ show i ++ show j- prettyS (Userscript i) = case i of- ScalarData (Div (Plus [Term 1 [(Symbol _ _ (_:_), 1)]]) (Plus [Term 1 []])) -> "_[" ++ prettyS i ++ "]"- _ -> "|" ++ prettyS i
hs-src/Language/Egison/PrettyMath/AST.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE FlexibleInstances #-}+ {- | Module : Language.Egison.PrettyMath.AST Licence : MIT@@ -6,23 +8,29 @@ module Language.Egison.PrettyMath.AST ( MathExpr(..) , MathIndex(..)+ , ToMathExpr(..) , isSub , parseExpr ) where +import Data.Foldable (toList) import Text.ParserCombinators.Parsec hiding (spaces) +import qualified Language.Egison.Data as E+import qualified Language.Egison.IExpr as E+import qualified Language.Egison.Math.Expr as E+ data MathExpr = Atom String [MathIndex] | NegativeAtom String | Plus [MathExpr] | Multiply [MathExpr]+ | Div MathExpr MathExpr | Power MathExpr MathExpr | Func MathExpr [MathExpr] | Tensor [MathExpr] [MathIndex] | Tuple [MathExpr] | Collection [MathExpr]- | Exp MathExpr | Quote MathExpr | Partial MathExpr [MathExpr] deriving (Eq, Show)@@ -36,6 +44,69 @@ isSub (Sub _) = True isSub _ = False ++class ToMathExpr a where+ toMathExpr :: a -> MathExpr++instance ToMathExpr E.EgisonValue where+ toMathExpr (E.ScalarData s) = toMathExpr s+ toMathExpr (E.Tuple es) = Tuple (map toMathExpr es)+ toMathExpr (E.Collection es) = Collection (map toMathExpr (toList es))+ toMathExpr (E.TensorData t) = toMathExpr t+ toMathExpr e = Atom (show e) []++instance ToMathExpr a => ToMathExpr (E.Tensor a) where+ toMathExpr (E.Scalar _) = undefined+ toMathExpr (E.Tensor _ xs js) = Tensor (map toMathExpr (toList xs)) (map toMathIndex js)++instance ToMathExpr E.ScalarData where+ toMathExpr (E.Div p (E.Plus [E.Term 1 []])) = toMathExpr p+ toMathExpr (E.Div p1 p2) = Div (toMathExpr p1) (toMathExpr p2)++instance ToMathExpr E.PolyExpr where+ toMathExpr (E.Plus []) = Atom "0" []+ toMathExpr (E.Plus [x]) = toMathExpr x+ toMathExpr (E.Plus xs) = Plus (map toMathExpr xs)++instance ToMathExpr E.TermExpr where+ toMathExpr (E.Term n []) = toMathExpr n+ toMathExpr (E.Term 1 [x]) = toMathExpr x+ toMathExpr (E.Term 1 xs) = Multiply (map toMathExpr xs)+ toMathExpr (E.Term n xs) = Multiply (toMathExpr n : map toMathExpr xs)++instance ToMathExpr Integer where+ toMathExpr n | n < 0 = NegativeAtom (show (-n))+ toMathExpr n = Atom (show n) []++instance {-# OVERLAPPING #-} ToMathExpr (E.SymbolExpr, Integer) where+ toMathExpr (x, 1) = toMathExpr x+ toMathExpr (x, n) = Power (toMathExpr x) (toMathExpr n)++instance ToMathExpr E.SymbolExpr where+ toMathExpr (E.Symbol _ (':':':':':':_) []) = Atom "#" []+ toMathExpr (E.Symbol _ s js) = toMathExpr' js (Atom s [])+ where+ toMathExpr' [] acc = acc+ toMathExpr' (E.User x:js) (Partial e ps) =+ toMathExpr' js (Partial e (ps ++ [toMathExpr x]))+ toMathExpr' (E.User x:js) e@Atom{} =+ toMathExpr' js (Partial e [toMathExpr x])+ toMathExpr' (j:js) (Atom e is) =+ toMathExpr' js (Atom e (is ++ [toMathIndex j]))+ toMathExpr' _ _ = undefined -- TODO++ toMathExpr (E.Apply fn mExprs) =+ case (toMathExpr fn, mExprs) of+ (Atom "^" [], [x, y]) -> Power (toMathExpr x) (toMathExpr y)+ _ -> Func (toMathExpr fn) (map toMathExpr mExprs)+ toMathExpr (E.Quote mExpr) = Quote (toMathExpr mExpr)+ toMathExpr (E.FunctionData _ _ _ _) = undefined -- TODO++toMathIndex :: ToMathExpr a => E.Index a -> MathIndex+toMathIndex (E.Sub x) = Sub (toMathExpr x)+toMathIndex (E.Sup x) = Super (toMathExpr x)+toMathIndex _ = undefined -- TODO+ -- -- Parser --@@ -69,11 +140,14 @@ <|> Super <$> (char '~' >> parseAtom') parsePlus :: Parser MathExpr-parsePlus = string "(+" >> spaces >> Plus <$> parseList <* char ')'+parsePlus = try (string "(+") >> spaces >> Plus <$> parseList <* char ')' parseMultiply :: Parser MathExpr-parseMultiply = string "(*" >> spaces >> Multiply <$> parseList <* char ')'+parseMultiply = try (string "(*") >> spaces >> Multiply <$> parseList <* char ')' +parseDiv :: Parser MathExpr+parseDiv = try (string "(/") >> spaces >> Div <$> parseExpr <*> (spaces >> parseExpr) <* char ')'+ parseFunction :: Parser MathExpr parseFunction = char '(' >> Func <$> parseAtom <* spaces <*> parseList <* char ')' @@ -86,9 +160,6 @@ parseCollection :: Parser MathExpr parseCollection = char '{' >> Collection <$> parseList <* char '}' -parseExp :: Parser MathExpr-parseExp = string "(exp" >> spaces >> Exp <$> parseExpr <* char ')'- parseQuote :: Parser MathExpr parseQuote = char '\'' >> Quote <$> parseExpr' @@ -97,9 +168,9 @@ <|> try parsePartial <|> parseAtom <|> parseQuote- <|> try parseExp- <|> try parsePlus- <|> try parseMultiply+ <|> parsePlus+ <|> parseMultiply+ <|> parseDiv <|> try parseFunction <|> try parseTensor <|> try parseTuple
hs-src/Language/Egison/PrettyMath/AsciiMath.hs view
@@ -24,13 +24,14 @@ showMathExprForPlus (Multiply (NegativeAtom a:ys):xs) = " - " ++ showMathExpr (Multiply (Atom a []:ys)) ++ " " ++ showMathExprForPlus xs showMathExprForPlus (x:xs) = " + " ++ showMathExpr x ++ showMathExprForPlus xs showMathExpr (Multiply []) = ""-showMathExpr (Multiply [a]) = showMathExpr a-showMathExpr (Multiply (NegativeAtom "1":lvs)) = "-" ++ showMathExpr (Multiply lvs)-showMathExpr (Multiply lvs) = showMathExpr' (head lvs) ++ " " ++ showMathExpr (Multiply (tail lvs))+showMathExpr (Multiply [x]) = showMathExpr x+showMathExpr (Multiply (NegativeAtom "1":xs)) = "-" ++ showMathExpr (Multiply xs)+showMathExpr (Multiply (x:xs)) = showMathExpr' x ++ " " ++ showMathExpr (Multiply xs)+showMathExpr (Div x y) = "frac{" ++ showMathExpr x ++ "}{" ++ showMathExpr y ++ "}" showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2 showMathExpr (Func (Atom "sqrt" []) [x]) = "sqrt " ++ showMathExpr x showMathExpr (Func (Atom "rt" []) [x, y]) = "root " ++ showMathExpr x ++ " " ++ showMathExpr y-showMathExpr (Func (Atom "/" []) [x, y]) = "frac{" ++ showMathExpr x ++ "}{" ++ showMathExpr y ++ "}"+showMathExpr (Func (Atom "exp" []) [x]) = "e^(" ++ showMathExpr x ++ ")" showMathExpr (Func f lvs) = showMathExpr f ++ "(" ++ showMathExprArg lvs ++ ")" showMathExpr (Tensor lvs mis) | null mis = "(" ++ showMathExprArg lvs ++ ")"@@ -39,7 +40,6 @@ | otherwise = "(" ++ showMathExprArg lvs ++ ")_(" ++ showMathExprIndices (filter isSub mis) ++ ")^(" ++ showMathExprIndices (filter (not . isSub) mis) ++ ")" showMathExpr (Tuple lvs) = "(" ++ showMathExprArg lvs ++ ")" showMathExpr (Collection lvs) = "{" ++ showMathExprArg lvs ++ "}"-showMathExpr (Exp x) = "e^(" ++ showMathExpr x ++ ")" showMathExpr' :: MathExpr -> String showMathExpr' (Plus lvs) = "(" ++ showMathExpr (Plus lvs) ++ ")"
hs-src/Language/Egison/PrettyMath/Latex.hs view
@@ -41,15 +41,15 @@ showMathExpr (Multiply (Atom "1" []:xs)) = showMathExpr (Multiply xs) showMathExpr (Multiply (NegativeAtom "1":xs)) = "-" ++ showMathExpr (Multiply xs) showMathExpr (Multiply (x:xs)) = showMathExpr' x ++ " " ++ showMathExpr (Multiply xs)+showMathExpr (Div x y) = "\\frac{" ++ showMathExpr x ++ "}{" ++ showMathExpr y ++ "}" showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2 showMathExpr (Func (Atom "sqrt" []) [x]) = "\\sqrt{" ++ showMathExpr x ++ "}" showMathExpr (Func (Atom "rt" []) [x, y]) = "\\sqrt[" ++ showMathExpr x ++ "]{" ++ showMathExpr y ++ "}"-showMathExpr (Func (Atom "/" []) [x, y]) = "\\frac{" ++ showMathExpr x ++ "}{" ++ showMathExpr y ++ "}"+showMathExpr (Func (Atom "exp" []) [x]) = "e^{" ++ showMathExpr x ++ "}" showMathExpr (Func f xs) = showMathExpr f ++ "(" ++ showMathExprArg xs ", " ++ ")" showMathExpr (Tensor xs mis) = "\\begin{pmatrix} " ++ showMathExprVectors xs ++ "\\end{pmatrix}" ++ showMathExprScript mis showMathExpr (Tuple xs) = "(" ++ showMathExprArg xs ", " ++ ")" showMathExpr (Collection xs) = "\\{" ++ showMathExprArg xs ", " ++ "\\}"-showMathExpr (Exp x) = "e^{" ++ showMathExpr x ++ "}" showMathExpr (Quote x) = "(" ++ showMathExpr x ++ ")" showMathExpr' :: MathExpr -> String
hs-src/Language/Egison/PrettyMath/Mathematica.hs view
@@ -30,13 +30,14 @@ showMathExpr (Multiply (Atom "1" []:xs)) = showMathExpr (Multiply xs) showMathExpr (Multiply (NegativeAtom "1":xs)) = "-" ++ showMathExpr (Multiply xs) showMathExpr (Multiply (x:xs)) = showMathExpr' x ++ " " ++ showMathExpr (Multiply xs)-showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2-showMathExpr (Func (Atom "sqrt" []) [x]) = "Sqrt[" ++ showMathExpr x ++ "]"-showMathExpr (Func (Atom "rt" []) [x, y]) = "Surd[" ++ showMathExpr x ++ "," ++ showMathExpr y ++ "]"-showMathExpr (Func (Atom "/" []) [x, y]) = addBracket x ++ "/" ++ addBracket y+showMathExpr (Div x y) = addBracket x ++ "/" ++ addBracket y where addBracket x@(Atom _ []) = showMathExpr x addBracket x = "(" ++ showMathExpr x ++ ")"+showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2+showMathExpr (Func (Atom "sqrt" []) [x]) = "Sqrt[" ++ showMathExpr x ++ "]"+showMathExpr (Func (Atom "rt" []) [x, y]) = "Surd[" ++ showMathExpr x ++ "," ++ showMathExpr y ++ "]"+showMathExpr (Func (Atom "exp" []) [x])= "e^(" ++ showMathExpr x ++ ")" showMathExpr (Func f xs) = showMathExpr f ++ "(" ++ showMathExprArg xs ++ ")" showMathExpr (Tensor lvs mis) | null mis = "{" ++ showMathExprArg lvs ++ "}"@@ -45,7 +46,6 @@ | otherwise = "{" ++ showMathExprArg lvs ++ "}_(" ++ showMathExprIndices (filter isSub mis) ++ ")^(" ++ showMathExprIndices (filter (not . isSub) mis) ++ ")" showMathExpr (Tuple xs) = "(" ++ showMathExprArg xs ++ ")" showMathExpr (Collection xs) = "{" ++ showMathExprArg xs ++ "}"-showMathExpr (Exp x) = "e^(" ++ showMathExpr x ++ ")" showMathExpr (Quote x) = "(" ++ showMathExpr x ++ ")" showMathExpr' :: MathExpr -> String
hs-src/Language/Egison/PrettyMath/Maxima.hs view
@@ -27,18 +27,18 @@ showMathExpr (Multiply (Atom "1" []:xs)) = showMathExpr (Multiply xs) showMathExpr (Multiply (NegativeAtom "1":xs)) = "-" ++ showMathExpr (Multiply xs) showMathExpr (Multiply (x:xs)) = showMathExpr' x ++ " * " ++ showMathExpr (Multiply xs)-showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2-showMathExpr (Func (Atom "sqrt" []) [x]) = "sqrt(" ++ showMathExpr x ++ ")"-showMathExpr (Func (Atom "rt" []) [x, y]) = showMathExpr y ++ "^(1/" ++ showMathExpr x ++ ")"-showMathExpr (Func (Atom "/" []) [x, y]) = addBracket x ++ "/" ++ addBracket y+showMathExpr (Div x y) = addBracket x ++ "/" ++ addBracket y where addBracket x@(Atom _ []) = showMathExpr x addBracket x = "(" ++ showMathExpr x ++ ")"+showMathExpr (Power lv1 lv2) = showMathExpr lv1 ++ "^" ++ showMathExpr lv2+showMathExpr (Func (Atom "sqrt" []) [x]) = "sqrt(" ++ showMathExpr x ++ ")"+showMathExpr (Func (Atom "rt" []) [x, y]) = showMathExpr y ++ "^(1/" ++ showMathExpr x ++ ")"+showMathExpr (Func (Atom "exp" []) [x]) = "exp(" ++ showMathExpr x ++ ")" showMathExpr (Func f xs) = showMathExpr f ++ "(" ++ showMathExprArg xs ++ ")" showMathExpr (Tensor _ _) = "undefined" showMathExpr (Tuple _) = "undefined" showMathExpr (Collection xs) = "[" ++ showMathExprArg xs ++ "]"-showMathExpr (Exp x) = "exp(" ++ showMathExpr x ++ ")" showMathExpr (Quote x) = "(" ++ showMathExpr x ++ ")" showMathExpr' :: MathExpr -> String
hs-src/Language/Egison/Primitives.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-} {- | Module : Language.Egison.Primitives@@ -10,660 +9,143 @@ -} module Language.Egison.Primitives- (- primitiveEnv+ ( primitiveEnv , primitiveEnvNoIO ) where import Control.Monad.Except -import Data.Foldable (toList) import Data.IORef-import Data.Ratio-import Text.Regex.TDFA ((=~~)) -import System.IO-import System.Process (readProcess)-import System.Random (getStdRandom, randomR)- import qualified Data.Sequence as Sq import qualified Data.Vector as V -import Data.Char (chr, ord)-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.IO as T- {-- -- for 'egison-sqlite' import qualified Database.SQLite3 as SQLite --} -- for 'egison-sqlite' -import Language.Egison.AST-import Language.Egison.Core import Language.Egison.Data-import Language.Egison.IState (MonadEval(..))-import Language.Egison.Parser-import Language.Egison.Pretty-import Language.Egison.MathExpr-import Language.Egison.Types-import Language.Egison.Tensor+import Language.Egison.Data.Collection (makeICollection)+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.IExpr (stringToVar, Index(..))+import Language.Egison.Primitives.Arith+import Language.Egison.Primitives.IO+import Language.Egison.Primitives.String+import Language.Egison.Primitives.Types+import Language.Egison.Primitives.Utils+import Language.Egison.Math primitiveEnv :: IO Env primitiveEnv = do- let ops = map (\(name, fn) -> (name, PrimitiveFunc name fn)) (primitives ++ ioPrimitives)- bindings <- forM (constants ++ ops) $ \(name, op) -> do+ bindings <- forM (constants ++ primitives ++ ioPrimitives) $ \(name, op) -> do ref <- newIORef . WHNF $ Value op return (stringToVar name, ref) return $ extendEnv nullEnv bindings primitiveEnvNoIO :: IO Env primitiveEnvNoIO = do- let ops = map (\(name, fn) -> (name, PrimitiveFunc name fn)) primitives- bindings <- forM (constants ++ ops) $ \(name, op) -> do+ bindings <- forM (constants ++ primitives) $ \(name, op) -> do ref <- newIORef . WHNF $ Value op return (stringToVar name, ref) return $ extendEnv nullEnv bindings -{-# INLINE noArg #-}-noArg :: EvalM EgisonValue -> PrimitiveFunc-noArg f args = do- args' <- tupleToList args- case args' of- [] -> Value <$> f- _ -> throwError =<< ArgumentsNumPrimitive 0 (length args') <$> getFuncNameStack--{-# INLINE oneArg #-}-oneArg :: (EgisonValue -> EvalM EgisonValue) -> PrimitiveFunc-oneArg f arg = do- arg' <- evalWHNF arg- case arg' of- (TensorData (Tensor ns ds js)) -> do- ds' <- V.mapM f ds- Value <$> fromTensor (Tensor ns ds' js)- _ -> Value <$> f arg'--{-# INLINE oneArg' #-}-oneArg' :: (EgisonValue -> EvalM EgisonValue) -> PrimitiveFunc-oneArg' f arg = do- arg' <- evalWHNF arg- Value <$> f arg'--{-# INLINE twoArgs #-}-twoArgs :: (EgisonValue -> EgisonValue -> EvalM EgisonValue) -> PrimitiveFunc-twoArgs f args = do- args' <- tupleToList args- case args' of- [TensorData t1@Tensor{}, TensorData t2@Tensor{}] -> Value <$> (tProduct f t1 t2 >>= fromTensor)- [TensorData(Tensor ns ds js), val] -> do- ds' <- V.mapM (`f` val) ds- Value <$> fromTensor (Tensor ns ds' js)- [val, TensorData (Tensor ns ds js)] -> do- ds' <- V.mapM (f val) ds- Value <$> fromTensor (Tensor ns ds' js)- [val, val'] -> Value <$> f val val'- _ -> throwError =<< ArgumentsNumPrimitive 2 (length args') <$> getFuncNameStack--{-# INLINE twoArgs' #-}-twoArgs' :: (EgisonValue -> EgisonValue -> EvalM EgisonValue) -> PrimitiveFunc-twoArgs' f args = do- args' <- tupleToList args- case args' of- [val, val'] -> Value <$> f val val'- _ -> throwError =<< ArgumentsNumPrimitive 2 (length args') <$> getFuncNameStack--{-# INLINE threeArgs' #-}-threeArgs' :: (EgisonValue -> EgisonValue -> EgisonValue -> EvalM EgisonValue) -> PrimitiveFunc-threeArgs' f args = do- args' <- tupleToList args- case args' of- [val, val', val''] -> Value <$> f val val' val''- _ -> throwError =<< ArgumentsNumPrimitive 3 (length args') <$> getFuncNameStack- -- -- Constants -- constants :: [(String, EgisonValue)]-constants = [- ("f.pi", Float 3.141592653589793)- ,("f.e" , Float 2.718281828459045)- ]+constants = [ ("f.pi", Float 3.141592653589793)+ , ("f.e" , Float 2.718281828459045)+ ] -- -- Primitives -- -primitives :: [(String, PrimitiveFunc)]-primitives = [ ("b.+", plus)- , ("b.-", minus)- , ("b.*", multiply)- , ("b./", divide)- , ("f.+", floatBinaryOp (+))- , ("f.-", floatBinaryOp (-))- , ("f.*", floatBinaryOp (*))- , ("f./", floatBinaryOp (/))- , ("numerator", numerator')- , ("denominator", denominator')- , ("fromMathExpr", fromScalarData)- , ("toMathExpr", toScalarData)- , ("toMathExpr'", toScalarData)-- , ("modulo", integerBinaryOp mod)- , ("quotient", integerBinaryOp quot)- , ("remainder", integerBinaryOp rem)- , ("b.abs", rationalUnaryOp abs)- , ("b.neg", rationalUnaryOp negate)-- , ("equal", eq)- , ("lt", scalarCompare (<))- , ("lte", scalarCompare (<=))- , ("gt", scalarCompare (>))- , ("gte", scalarCompare (>=))-- , ("round", floatToIntegerOp round)- , ("floor", floatToIntegerOp floor)- , ("ceiling", floatToIntegerOp ceiling)- , ("truncate", truncate')-- , ("b.sqrt", floatUnaryOp sqrt)- , ("b.sqrt'", floatUnaryOp sqrt)- , ("b.exp", floatUnaryOp exp)- , ("b.log", floatUnaryOp log)- , ("b.sin", floatUnaryOp sin)- , ("b.cos", floatUnaryOp cos)- , ("b.tan", floatUnaryOp tan)- , ("b.asin", floatUnaryOp asin)- , ("b.acos", floatUnaryOp acos)- , ("b.atan", floatUnaryOp atan)- , ("b.sinh", floatUnaryOp sinh)- , ("b.cosh", floatUnaryOp cosh)- , ("b.tanh", floatUnaryOp tanh)- , ("b.asinh", floatUnaryOp asinh)- , ("b.acosh", floatUnaryOp acosh)- , ("b.atanh", floatUnaryOp atanh)-- , ("tensorShape", tensorShape')- , ("tensorToList", tensorToList')- , ("dfOrder", dfOrder')-- , ("itof", integerToFloat)- , ("rtof", rationalToFloat)- , ("ctoi", charToInteger)- , ("itoc", integerToChar)-- , ("pack", pack)- , ("unpack", unpack)- , ("unconsString", unconsString)- , ("lengthString", lengthString)- , ("appendString", appendString)- , ("splitString", splitString)- , ("regex", regexString)- , ("regexCg", regexStringCaptureGroup)-- , ("addPrime", addPrime)- , ("addSubscript", addSubscript)- , ("addSuperscript", addSuperscript)-- , ("readProcess", readProcess')-- , ("read", read')- , ("readTsv", readTSV)- , ("show", show')- , ("showTsv", showTSV')-- , ("isBool", isBool')- , ("isInteger", isInteger')- , ("isRational", isRational')- , ("isScalar", isScalar')- , ("isFloat", isFloat')- , ("isChar", isChar')- , ("isString", isString')- , ("isCollection", isCollection')- , ("isHash", isHash')- , ("isTensor", isTensor')-- , ("assert", assert)- , ("assertEqual", assertEqual)- ]--unaryOp :: (EgisonData a, EgisonData b) => (a -> b) -> PrimitiveFunc-unaryOp op = oneArg $ \val -> do- v <- fromEgison val- return $ toEgison (op v)--binaryOp :: (EgisonData a, EgisonData b) => (a -> a -> b) -> PrimitiveFunc-binaryOp op = twoArgs $ \val val' -> do- i <- fromEgison val- i' <- fromEgison val'- return $ toEgison (op i i')--rationalUnaryOp :: (Rational -> Rational) -> PrimitiveFunc-rationalUnaryOp = unaryOp--integerBinaryOp :: (Integer -> Integer -> Integer) -> PrimitiveFunc-integerBinaryOp = binaryOp--floatUnaryOp :: (Double -> Double) -> PrimitiveFunc-floatUnaryOp = unaryOp--floatBinaryOp :: (Double -> Double -> Double) -> PrimitiveFunc-floatBinaryOp = binaryOp------- Arith-----scalarBinaryOp :: (ScalarData -> ScalarData -> ScalarData) -> PrimitiveFunc-scalarBinaryOp mOp = twoArgs $ \val val' -> scalarBinaryOp' val val'- where- scalarBinaryOp' (ScalarData m1) (ScalarData m2) = (return . ScalarData . mathNormalize') (mOp m1 m2)- scalarBinaryOp' (ScalarData _) val = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack- scalarBinaryOp' val _ = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack--plus :: PrimitiveFunc-plus = scalarBinaryOp mathPlus--minus :: PrimitiveFunc-minus = scalarBinaryOp (\m1 m2 -> mathPlus m1 (mathNegate m2))--multiply :: PrimitiveFunc-multiply = scalarBinaryOp mathMult--divide :: PrimitiveFunc-divide = scalarBinaryOp (\m1 (Div p1 p2) -> mathMult m1 (Div p2 p1))--numerator' :: PrimitiveFunc-numerator' = oneArg numerator''- where- numerator'' (ScalarData m) = return $ ScalarData (mathNumerator m)- numerator'' val = throwError =<< TypeMismatch "rational" (Value val) <$> getFuncNameStack--denominator' :: PrimitiveFunc-denominator' = oneArg denominator''- where- denominator'' (ScalarData m) = return $ ScalarData (mathDenominator m)- denominator'' val = throwError =<< TypeMismatch "rational" (Value val) <$> getFuncNameStack--fromScalarData :: PrimitiveFunc-fromScalarData = oneArg fromScalarData'- where- fromScalarData' (ScalarData m) = return $ mathExprToEgison m- fromScalarData' val = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack--toScalarData :: PrimitiveFunc-toScalarData = oneArg toScalarData'- where- toScalarData' val = ScalarData . mathNormalize' <$> egisonToScalarData val------- Pred----eq :: PrimitiveFunc-eq = twoArgs' $ \val val' ->- return $ Bool $ val == val'--scalarCompare :: (forall a. Ord a => a -> a -> Bool) -> PrimitiveFunc-scalarCompare cmp = twoArgs' $ \val1 val2 ->- case (val1, val2) of- (ScalarData _, ScalarData _) -> do- r1 <- fromEgison val1 :: EvalM Rational- r2 <- fromEgison val2 :: EvalM Rational- return $ Bool (cmp r1 r2)- (Float f1, Float f2) -> return $ Bool (cmp f1 f2)- (ScalarData _, _) -> throwError =<< TypeMismatch "number" (Value val2) <$> getFuncNameStack- (Float _, _) -> throwError =<< TypeMismatch "float" (Value val2) <$> getFuncNameStack- _ -> throwError =<< TypeMismatch "number" (Value val1) <$> getFuncNameStack+primitives :: [(String, EgisonValue)]+primitives =+ map (\(name, fn) -> (name, PrimitiveFunc (fn name))) strictPrimitives+ ++ map (\(name, fn) -> (name, LazyPrimitiveFunc (fn name))) lazyPrimitives+ ++ primitiveArithFunctions+ ++ primitiveStringFunctions+ ++ primitiveTypeFunctions+ where+ strictPrimitives =+ [ ("addSubscript", addSubscript)+ , ("addSuperscript", addSuperscript) -truncate' :: PrimitiveFunc-truncate' = oneArg $ \val -> numberUnaryOp' val- where- numberUnaryOp' (ScalarData (Div (Plus []) _)) = return $ toEgison (0 :: Integer)- numberUnaryOp' (ScalarData (Div (Plus [Term x []]) (Plus [Term y []]))) = return $ toEgison (quot x y)- numberUnaryOp' (Float x) = return $ toEgison (truncate x :: Integer)- numberUnaryOp' val = throwError =<< TypeMismatch "rational or float" (Value val) <$> getFuncNameStack+ , ("assert", assert)+ , ("assertEqual", assertEqual)+ ]+ lazyPrimitives =+ [ ("tensorShape", tensorShape')+ , ("tensorToList", tensorToList')+ , ("dfOrder", dfOrder')+ ] ----- Tensor+-- Miscellaneous primitive functions -- -tensorShape' :: PrimitiveFunc-tensorShape' = oneArg' tensorShape''+tensorShape' :: String -> LazyPrimitiveFunc+tensorShape' = lazyOneArg tensorShape'' where- tensorShape'' (TensorData (Tensor ns _ _)) = return . Collection . Sq.fromList $ map toEgison ns- tensorShape'' _ = return . Collection $ Sq.fromList []+ tensorShape'' (Value (TensorData (Tensor ns _ _))) =+ return . Value . Collection . Sq.fromList $ map toEgison ns+ tensorShape'' (ITensor (Tensor ns _ _)) =+ return . Value . Collection . Sq.fromList $ map toEgison ns+ tensorShape'' _ = return . Value . Collection $ Sq.fromList [] -tensorToList' :: PrimitiveFunc-tensorToList' = oneArg' tensorToList''+tensorToList' :: String -> LazyPrimitiveFunc+tensorToList' = lazyOneArg tensorToList'' where- tensorToList'' (TensorData (Tensor _ xs _)) = return . Collection . Sq.fromList $ V.toList xs- tensorToList'' x = return . Collection $ Sq.fromList [x]+ tensorToList'' (Value (TensorData (Tensor _ xs _))) =+ return . Value . Collection . Sq.fromList $ V.toList xs+ tensorToList'' (ITensor (Tensor _ xs _)) = do+ inners <- liftIO . newIORef $ Sq.fromList (map IElement (V.toList xs))+ return (ICollection inners)+ tensorToList'' x = makeICollection [x] -dfOrder' :: PrimitiveFunc-dfOrder' = oneArg' dfOrder''+dfOrder' :: String -> LazyPrimitiveFunc+dfOrder' = lazyOneArg dfOrder'' where- dfOrder'' (TensorData (Tensor ns _ is)) = return (toEgison (fromIntegral (length ns - length is) :: Integer))- dfOrder'' _ = return (toEgison (0 :: Integer))------- Transform----integerToFloat :: PrimitiveFunc-integerToFloat = rationalToFloat--rationalToFloat :: PrimitiveFunc-rationalToFloat = oneArg $ \val ->- case val of- (ScalarData (Div (Plus []) _)) -> return $ Float 0- (ScalarData (Div (Plus [Term x []]) (Plus [Term y []]))) -> return $ Float (fromRational (x % y))- _ -> throwError =<< TypeMismatch "integer or rational number" (Value val) <$> getFuncNameStack--charToInteger :: PrimitiveFunc-charToInteger = unaryOp ctoi- where- ctoi :: Char -> Integer- ctoi = fromIntegral . ord--integerToChar :: PrimitiveFunc-integerToChar = unaryOp itoc- where- itoc :: Integer -> Char- itoc = chr . fromIntegral--floatToIntegerOp :: (Double -> Integer) -> PrimitiveFunc-floatToIntegerOp = unaryOp------- String----pack :: PrimitiveFunc-pack = oneArg $ \val -> do- str <- packStringValue val- return $ String str- where- packStringValue :: EgisonValue -> EvalM Text- packStringValue (Collection seq) = do- let ls = toList seq- str <- mapM fromEgison ls- return $ T.pack str- packStringValue (Tuple [val]) = packStringValue val- packStringValue val = throwError =<< TypeMismatch "collection" (Value val) <$> getFuncNameStack--unpack :: PrimitiveFunc-unpack = unaryOp T.unpack--unconsString :: PrimitiveFunc-unconsString = oneArg $ \val -> do- str <- fromEgison val- case T.uncons str of- Just (c, rest) -> return $ Tuple [Char c, String rest]- Nothing -> throwError $ Default "Tried to unsnoc empty string"--lengthString :: PrimitiveFunc-lengthString = unaryOp (toInteger . T.length)--appendString :: PrimitiveFunc-appendString = binaryOp T.append--splitString :: PrimitiveFunc-splitString = twoArgs $ \pat src -> do- patStr <- fromEgison pat- srcStr <- fromEgison src- return . Collection . Sq.fromList $ map String $ T.splitOn patStr srcStr--regexString :: PrimitiveFunc-regexString = twoArgs $ \pat src -> do- patStr <- fromEgison pat- srcStr <- fromEgison src- case (T.unpack srcStr =~~ T.unpack patStr) :: (Maybe (String, String, String)) of- Nothing -> return . Collection . Sq.fromList $ []- Just (a,b,c) -> return . Collection . Sq.fromList $ [Tuple [String $ T.pack a, String $ T.pack b, String $ T.pack c]]--regexStringCaptureGroup :: PrimitiveFunc-regexStringCaptureGroup = twoArgs $ \pat src -> do- patStr <- fromEgison pat- srcStr <- fromEgison src- case (T.unpack srcStr =~~ T.unpack patStr) :: (Maybe [[String]]) of- Nothing -> return . Collection . Sq.fromList $ []- Just ((x:xs):_) -> do let (a, c) = T.breakOn (T.pack x) srcStr- return . Collection . Sq.fromList $ [Tuple [String a, Collection (Sq.fromList (map (String . T.pack) xs)), String (T.drop (length x) c)]]----regexStringMatch :: PrimitiveFunc---regexStringMatch = twoArgs $ \pat src -> do--- case (pat, src) of--- (String patStr, String srcStr) -> return . Bool $ (((T.unpack srcStr) =~ (T.unpack patStr)) :: Bool)--- (String _, _) -> throwError =<< TypeMismatch "string" (Value src) <$> getFuncNameStack--- (_, _) -> throwError =<< TypeMismatch "string" (Value pat) <$> getFuncNameStack--addPrime :: PrimitiveFunc-addPrime = oneArg $ \sym ->- case sym of- ScalarData (Div (Plus [Term 1 [(Symbol id name is, 1)]]) (Plus [Term 1 []])) ->- return (ScalarData (Div (Plus [Term 1 [(Symbol id (name ++ "'") is, 1)]]) (Plus [Term 1 []])))- _ -> throwError =<< TypeMismatch "symbol" (Value sym) <$> getFuncNameStack+ dfOrder'' (Value (TensorData (Tensor ns _ is))) =+ return $ Value (toEgison (fromIntegral (length ns - length is) :: Integer))+ dfOrder'' (ITensor (Tensor ns _ is)) =+ return $ Value (toEgison (fromIntegral (length ns - length is) :: Integer))+ dfOrder'' _ = return $ Value (toEgison (0 :: Integer)) -addSubscript :: PrimitiveFunc+addSubscript :: String -> PrimitiveFunc addSubscript = twoArgs $ \fn sub -> case (fn, sub) of- (ScalarData (Div (Plus [Term 1 [(Symbol id name is, 1)]]) (Plus [Term 1 []])),- ScalarData s@(Div (Plus [Term 1 [(Symbol _ _ [], 1)]]) (Plus [Term 1 []]))) ->- return (ScalarData (Div (Plus [Term 1 [(Symbol id name (is ++ [Subscript s]), 1)]]) (Plus [Term 1 []])))- (ScalarData (Div (Plus [Term 1 [(Symbol id name is, 1)]]) (Plus [Term 1 []])),- ScalarData s@(Div (Plus [Term _ []]) (Plus [Term 1 []]))) ->- return (ScalarData (Div (Plus [Term 1 [(Symbol id name (is ++ [Subscript s]), 1)]]) (Plus [Term 1 []])))- (ScalarData (Div (Plus [Term 1 [(Symbol{}, 1)]]) (Plus [Term 1 []])),- _) -> throwError =<< TypeMismatch "symbol or integer" (Value sub) <$> getFuncNameStack+ (ScalarData (SingleSymbol (Symbol id name is)), ScalarData s@(SingleSymbol (Symbol _ _ []))) ->+ return (ScalarData (SingleSymbol (Symbol id name (is ++ [Sub s]))))+ (ScalarData (SingleSymbol (Symbol id name is)), ScalarData s@(SingleTerm _ [])) ->+ return (ScalarData (SingleSymbol (Symbol id name (is ++ [Sub s])))) _ -> throwError =<< TypeMismatch "symbol or integer" (Value fn) <$> getFuncNameStack -addSuperscript :: PrimitiveFunc+addSuperscript :: String -> PrimitiveFunc addSuperscript = twoArgs $ \fn sub -> case (fn, sub) of- (ScalarData (Div (Plus [Term 1 [(Symbol id name is, 1)]]) (Plus [Term 1 []])),- ScalarData s@(Div (Plus [Term 1 [(Symbol _ _ [], 1)]]) (Plus [Term 1 []]))) ->- return (ScalarData (Div (Plus [Term 1 [(Symbol id name (is ++ [Superscript s]), 1)]]) (Plus [Term 1 []])))- (ScalarData (Div (Plus [Term 1 [(Symbol id name is, 1)]]) (Plus [Term 1 []])),- ScalarData s@(Div (Plus [Term _ []]) (Plus [Term 1 []]))) ->- return (ScalarData (Div (Plus [Term 1 [(Symbol id name (is ++ [Superscript s]), 1)]]) (Plus [Term 1 []])))- (ScalarData (Div (Plus [Term 1 [(Symbol{}, 1)]]) (Plus [Term 1 []])),- _) -> throwError =<< TypeMismatch "symbol" (Value sub) <$> getFuncNameStack+ (ScalarData (SingleSymbol (Symbol id name is)), ScalarData s@(SingleSymbol (Symbol _ _ []))) ->+ return (ScalarData (SingleSymbol (Symbol id name (is ++ [Sup s]))))+ (ScalarData (SingleSymbol (Symbol id name is)), ScalarData s@(SingleTerm _ [])) ->+ return (ScalarData (SingleSymbol (Symbol id name (is ++ [Sup s])))) _ -> throwError =<< TypeMismatch "symbol" (Value fn) <$> getFuncNameStack -readProcess' :: PrimitiveFunc-readProcess' = threeArgs' $ \cmd args input ->- case (cmd, args, input) of- (String cmdStr, Collection argStrs, String inputStr) -> do- let cmd' = T.unpack cmdStr- let args' = map (\case String argStr -> T.unpack argStr) (toList argStrs)- let input' = T.unpack inputStr- outputStr <- liftIO $ readProcess cmd' args' input'- return (String (T.pack outputStr))- (_, _, _) -> throwError =<< TypeMismatch "(string, collection, string)" (Value (Tuple [cmd, args, input])) <$> getFuncNameStack--read' :: PrimitiveFunc-read'= oneArg' $ \val -> do- str <- fromEgison val- ast <- readExpr False (T.unpack str)- evalExprDeep nullEnv ast--readTSV :: PrimitiveFunc-readTSV= oneArg' $ \val -> do- str <- fromEgison val- exprs <- readExprs False (T.unpack str)- rets <- mapM (evalExprDeep nullEnv) exprs- case rets of- [ret] -> return ret- _ -> return (Tuple rets)--show' :: PrimitiveFunc-show'= oneArg' $ \val -> return $ toEgison $ T.pack $ show val--showTSV' :: PrimitiveFunc-showTSV'= oneArg' $ \val -> return $ toEgison $ T.pack $ showTSV val------- Test-----assert :: PrimitiveFunc+assert :: String -> PrimitiveFunc assert = twoArgs' $ \label test -> do test <- fromEgison test if test then return $ Bool True else throwError =<< Assertion (show label) <$> getFuncNameStack -assertEqual :: PrimitiveFunc+assertEqual :: String -> PrimitiveFunc assertEqual = threeArgs' $ \label actual expected -> if actual == expected then return $ Bool True else throwError =<< Assertion (show label ++ "\n expected: " ++ show expected ++ "\n but found: " ++ show actual) <$> getFuncNameStack------- IO Primitives-----ioPrimitives :: [(String, PrimitiveFunc)]-ioPrimitives = [ ("return", return')- , ("openInputFile", makePort ReadMode)- , ("openOutputFile", makePort WriteMode)- , ("closeInputPort", closePort)- , ("closeOutputPort", closePort)- , ("readChar", readChar)- , ("readLine", readLine)- , ("writeChar", writeChar)- , ("write", writeString)-- , ("readCharFromPort", readCharFromPort)- , ("readLineFromPort", readLineFromPort)- , ("writeCharToPort", writeCharToPort)- , ("writeToPort", writeStringToPort)-- , ("isEof", isEOFStdin)- , ("flush", flushStdout)- , ("isEofPort", isEOFPort)- , ("flushPort", flushPort)- , ("readFile", readFile')-- , ("rand", randRange)- , ("f.rand", randRangeDouble)-- , ("newIORef", newIORef')- , ("writeIORef", writeIORef')- , ("readIORef", readIORef')- ]--makeIO :: EvalM EgisonValue -> EgisonValue-makeIO m = IOFunc $ fmap (Value . Tuple . (World :) . (:[])) m--makeIO' :: EvalM () -> EgisonValue-makeIO' m = IOFunc $ m >> return (Value $ Tuple [World, Tuple []])--return' :: PrimitiveFunc-return' = oneArg' $ \val -> return $ makeIO $ return val--makePort :: IOMode -> PrimitiveFunc-makePort mode = oneArg' $ \val -> do- filename <- fromEgison val- port <- liftIO $ openFile (T.unpack filename) mode- return $ makeIO $ return (Port port)--closePort :: PrimitiveFunc-closePort = oneArg' $ \val -> do- port <- fromEgison val- return $ makeIO' $ liftIO $ hClose port--writeChar :: PrimitiveFunc-writeChar = oneArg' $ \val -> do- c <- fromEgison val- return $ makeIO' $ liftIO $ putChar c--writeCharToPort :: PrimitiveFunc-writeCharToPort = twoArgs' $ \val val' -> do- port <- fromEgison val- c <- fromEgison val'- return $ makeIO' $ liftIO $ hPutChar port c--writeString :: PrimitiveFunc-writeString = oneArg' $ \val -> do- s <- fromEgison val- return $ makeIO' $ liftIO $ T.putStr s--writeStringToPort :: PrimitiveFunc-writeStringToPort = twoArgs' $ \val val' -> do- port <- fromEgison val- s <- fromEgison val'- return $ makeIO' $ liftIO $ T.hPutStr port s--flushStdout :: PrimitiveFunc-flushStdout = noArg $ return $ makeIO' $ liftIO $ hFlush stdout--flushPort :: PrimitiveFunc-flushPort = oneArg' $ \val -> do- port <- fromEgison val- return $ makeIO' $ liftIO $ hFlush port--readChar :: PrimitiveFunc-readChar = noArg $ return $ makeIO $ liftIO $ fmap Char getChar--readCharFromPort :: PrimitiveFunc-readCharFromPort = oneArg' $ \val -> do- port <- fromEgison val- c <- liftIO $ hGetChar port- return $ makeIO $ return (Char c)--readLine :: PrimitiveFunc-readLine = noArg $ return $ makeIO $ liftIO $ fmap toEgison T.getLine--readLineFromPort :: PrimitiveFunc-readLineFromPort = oneArg' $ \val -> do- port <- fromEgison val- s <- liftIO $ T.hGetLine port- return $ makeIO $ return $ toEgison s--readFile' :: PrimitiveFunc-readFile' = oneArg' $ \val -> do- filename <- fromEgison val- s <- liftIO $ T.readFile $ T.unpack filename- return $ makeIO $ return $ toEgison s--isEOFStdin :: PrimitiveFunc-isEOFStdin = noArg $ return $ makeIO $ liftIO $ fmap Bool isEOF--isEOFPort :: PrimitiveFunc-isEOFPort = oneArg' $ \val -> do- port <- fromEgison val- b <- liftIO $ hIsEOF port- return $ makeIO $ return (Bool b)--randRange :: PrimitiveFunc-randRange = twoArgs' $ \val val' -> do- i <- fromEgison val :: EvalM Integer- i' <- fromEgison val' :: EvalM Integer- n <- liftIO $ getStdRandom $ randomR (i, i')- return $ makeIO $ return $ toEgison n--randRangeDouble :: PrimitiveFunc-randRangeDouble = twoArgs' $ \val val' -> do- i <- fromEgison val :: EvalM Double- i' <- fromEgison val' :: EvalM Double- n <- liftIO $ getStdRandom $ randomR (i, i')- return $ makeIO $ return $ toEgison n--newIORef' :: PrimitiveFunc-newIORef' = noArg $ do- ref <- liftIO $ newIORef Undefined- return $ makeIO $ return (RefBox ref)--writeIORef' :: PrimitiveFunc-writeIORef' = twoArgs $ \ref val -> do- ref' <- fromEgison ref- return $ makeIO' $ liftIO $ writeIORef ref' val--readIORef' :: PrimitiveFunc-readIORef' = oneArg $ \ref -> do- ref' <- fromEgison ref- val <- liftIO $ readIORef ref'- return $ makeIO $ return val- {-- -- for 'egison-sqlite' sqlite :: PrimitiveFunc
+ hs-src/Language/Egison/Primitives/Arith.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++{- |+Module : Language.Egison.Primitives.Arith+Licence : MIT++This module implements arithmetic primitive functions.+-}++module Language.Egison.Primitives.Arith+ ( primitiveArithFunctions+ ) where++import Control.Monad.Except+import Language.Egison.Data+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.Primitives.Utils+import Language.Egison.Math++primitiveArithFunctions :: [(String, EgisonValue)]+primitiveArithFunctions =+ map (\(name, fn) -> (name, PrimitiveFunc (fn name))) strictPrimitives++strictPrimitives :: [(String, String -> PrimitiveFunc)]+strictPrimitives =+ [ ("b.+", plus)+ , ("b.-", minus)+ , ("b.*", multiply)+ , ("b./", divide)+ , ("f.+", floatBinaryOp (+))+ , ("f.-", floatBinaryOp (-))+ , ("f.*", floatBinaryOp (*))+ , ("f./", floatBinaryOp (/))+ , ("numerator", numerator')+ , ("denominator", denominator')+ , ("fromMathExpr", fromScalarData)+ , ("toMathExpr'", toScalarData)+ , ("symbolNormalize", symbolNormalize)++ , ("modulo", integerBinaryOp mod)+ , ("quotient", integerBinaryOp quot)+ , ("%", integerBinaryOp rem)+ , ("b.abs", rationalUnaryOp abs)+ , ("b.neg", rationalUnaryOp negate)++ , ("=", eq)+ , ("<", scalarCompare (<))+ , ("<=", scalarCompare (<=))+ , (">", scalarCompare (>))+ , (">=", scalarCompare (>=))++ , ("round", floatToIntegerOp round)+ , ("floor", floatToIntegerOp floor)+ , ("ceiling", floatToIntegerOp ceiling)+ , ("truncate", truncate')++ , ("b.sqrt", floatUnaryOp sqrt)+ , ("b.sqrt'", floatUnaryOp sqrt)+ , ("b.exp", floatUnaryOp exp)+ , ("b.log", floatUnaryOp log)+ , ("b.sin", floatUnaryOp sin)+ , ("b.cos", floatUnaryOp cos)+ , ("b.tan", floatUnaryOp tan)+ , ("b.asin", floatUnaryOp asin)+ , ("b.acos", floatUnaryOp acos)+ , ("b.atan", floatUnaryOp atan)+ , ("b.sinh", floatUnaryOp sinh)+ , ("b.cosh", floatUnaryOp cosh)+ , ("b.tanh", floatUnaryOp tanh)+ , ("b.asinh", floatUnaryOp asinh)+ , ("b.acosh", floatUnaryOp acosh)+ , ("b.atanh", floatUnaryOp atanh)+ ]+++rationalUnaryOp :: (Rational -> Rational) -> String -> PrimitiveFunc+rationalUnaryOp = unaryOp++integerBinaryOp :: (Integer -> Integer -> Integer) -> String -> PrimitiveFunc+integerBinaryOp = binaryOp++floatUnaryOp :: (Double -> Double) -> String -> PrimitiveFunc+floatUnaryOp = unaryOp++floatBinaryOp :: (Double -> Double -> Double) -> String -> PrimitiveFunc+floatBinaryOp = binaryOp++floatToIntegerOp :: (Double -> Integer) -> String -> PrimitiveFunc+floatToIntegerOp = unaryOp++--+-- Arith+--+scalarBinaryOp :: (ScalarData -> ScalarData -> ScalarData) -> String -> PrimitiveFunc+scalarBinaryOp mOp = twoArgs scalarBinaryOp'+ where+ scalarBinaryOp' (ScalarData m1) (ScalarData m2) = (return . ScalarData) (mOp m1 m2)+ scalarBinaryOp' (ScalarData _) val = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack+ scalarBinaryOp' val _ = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack++plus :: String -> PrimitiveFunc+plus = scalarBinaryOp mathPlus++minus :: String -> PrimitiveFunc+minus = scalarBinaryOp (\m1 m2 -> mathPlus m1 (mathNegate m2))++multiply :: String -> PrimitiveFunc+multiply = scalarBinaryOp mathMult++divide :: String -> PrimitiveFunc+divide = scalarBinaryOp mathDiv++numerator' :: String -> PrimitiveFunc+numerator' = oneArg numerator''+ where+ numerator'' (ScalarData m) = return $ ScalarData (mathNumerator m)+ numerator'' val = throwError =<< TypeMismatch "rational" (Value val) <$> getFuncNameStack++denominator' :: String -> PrimitiveFunc+denominator' = oneArg denominator''+ where+ denominator'' (ScalarData m) = return $ ScalarData (mathDenominator m)+ denominator'' val = throwError =<< TypeMismatch "rational" (Value val) <$> getFuncNameStack++fromScalarData :: String -> PrimitiveFunc+fromScalarData = oneArg fromScalarData'+ where+ fromScalarData' (ScalarData m) = return $ mathExprToEgison m+ fromScalarData' val = throwError =<< TypeMismatch "number" (Value val) <$> getFuncNameStack++toScalarData :: String -> PrimitiveFunc+toScalarData = oneArg $ \val ->+ ScalarData . mathNormalize' <$> egisonToScalarData val++symbolNormalize :: String -> PrimitiveFunc+symbolNormalize = oneArg $ \val ->+ case val of+ ScalarData s -> return $ ScalarData (rewriteSymbol s)+ _ -> throwError =<< TypeMismatch "math expression" (Value val) <$> getFuncNameStack++--+-- Pred+--+eq :: String -> PrimitiveFunc+eq = twoArgs' $ \val val' ->+ return $ Bool $ val == val'++scalarCompare :: (forall a. Ord a => a -> a -> Bool) -> String -> PrimitiveFunc+scalarCompare cmp = twoArgs' $ \val1 val2 ->+ case (val1, val2) of+ (ScalarData _, ScalarData _) -> do+ r1 <- fromEgison val1 :: EvalM Rational+ r2 <- fromEgison val2 :: EvalM Rational+ return $ Bool (cmp r1 r2)+ (Float f1, Float f2) -> return $ Bool (cmp f1 f2)+ (ScalarData _, _) -> throwError =<< TypeMismatch "number" (Value val2) <$> getFuncNameStack+ (Float _, _) -> throwError =<< TypeMismatch "float" (Value val2) <$> getFuncNameStack+ _ -> throwError =<< TypeMismatch "number" (Value val1) <$> getFuncNameStack++truncate' :: String -> PrimitiveFunc+truncate' = oneArg $ \val -> numberUnaryOp' val+ where+ numberUnaryOp' (ScalarData (Div (Plus []) _)) = return $ toEgison (0 :: Integer)+ numberUnaryOp' (ScalarData (Div (Plus [Term x []]) (Plus [Term y []]))) = return $ toEgison (quot x y)+ numberUnaryOp' (Float x) = return $ toEgison (truncate x :: Integer)+ numberUnaryOp' val = throwError =<< TypeMismatch "rational or float" (Value val) <$> getFuncNameStack
+ hs-src/Language/Egison/Primitives/IO.hs view
@@ -0,0 +1,199 @@+{- |+Module : Language.Egison.Primitives.IO+Licence : MIT++This module implements primitive functions that performs IO operations.+-}++module Language.Egison.Primitives.IO+ ( ioPrimitives+ ) where++import Control.Monad.Except++import Data.IORef++import System.IO+import System.Process (readProcess)+import System.Random (getStdRandom, randomR)++import qualified Data.Text as T+import qualified Data.Text.IO as T++import Language.Egison.Core (evalWHNF)+import Language.Egison.Data+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.Primitives.Utils+++--+-- IO Primitives+--++ioPrimitives :: [(String, EgisonValue)]+ioPrimitives =+ map (\(name, fn) -> (name, PrimitiveFunc (fn name))) ioStrictPrimitives +++ map (\(name, fn) -> (name, LazyPrimitiveFunc (fn name))) ioLazyPrimitives++ioStrictPrimitives :: [(String, String -> PrimitiveFunc)]+ioStrictPrimitives =+ [ ("return", return')+ , ("openInputFile", makePort ReadMode)+ , ("openOutputFile", makePort WriteMode)+ , ("closeInputPort", closePort)+ , ("closeOutputPort", closePort)+ , ("readChar", readChar)+ , ("readLine", readLine)+ , ("writeChar", writeChar)+ , ("write", writeString)++ , ("readCharFromPort", readCharFromPort)+ , ("readLineFromPort", readLineFromPort)+ , ("writeCharToPort", writeCharToPort)+ , ("writeToPort", writeStringToPort)++ , ("isEof", isEOFStdin)+ , ("flush", flushStdout)+ , ("isEofPort", isEOFPort)+ , ("flushPort", flushPort)+ , ("readFile", readFile')++ , ("rand", randRange)+ , ("f.rand", randRangeDouble)++ , ("newIORef", newIORef')+ , ("writeIORef", writeIORef')+ , ("readIORef", readIORef')++ , ("readProcess", readProcess')+ ]++ioLazyPrimitives :: [(String, String -> LazyPrimitiveFunc)]+ioLazyPrimitives =+ [ ("io", io)+ ]++makeIO :: EvalM EgisonValue -> EgisonValue+makeIO m = IOFunc $ fmap (Value . Tuple . (World :) . (:[])) m++makeIO' :: EvalM () -> EgisonValue+makeIO' m = IOFunc $ m >> return (Value $ Tuple [World, Tuple []])++return' :: String -> PrimitiveFunc+return' = oneArg' $ \val -> return $ makeIO $ return val++makePort :: IOMode -> String -> PrimitiveFunc+makePort mode = oneArg' $ \val -> do+ filename <- fromEgison val+ port <- liftIO $ openFile (T.unpack filename) mode+ return $ makeIO $ return (Port port)++closePort :: String -> PrimitiveFunc+closePort = oneArg' $ \val -> do+ port <- fromEgison val+ return $ makeIO' $ liftIO $ hClose port++writeChar :: String -> PrimitiveFunc+writeChar = oneArg' $ \val -> do+ c <- fromEgison val+ return $ makeIO' $ liftIO $ putChar c++writeCharToPort :: String -> PrimitiveFunc+writeCharToPort = twoArgs' $ \val val' -> do+ port <- fromEgison val+ c <- fromEgison val'+ return $ makeIO' $ liftIO $ hPutChar port c++writeString :: String -> PrimitiveFunc+writeString = oneArg' $ \val -> do+ s <- fromEgison val+ return $ makeIO' $ liftIO $ T.putStr s++writeStringToPort :: String -> PrimitiveFunc+writeStringToPort = twoArgs' $ \val val' -> do+ port <- fromEgison val+ s <- fromEgison val'+ return $ makeIO' $ liftIO $ T.hPutStr port s++flushStdout :: String -> PrimitiveFunc+flushStdout = noArg $ return $ makeIO' $ liftIO $ hFlush stdout++flushPort :: String -> PrimitiveFunc+flushPort = oneArg' $ \val -> do+ port <- fromEgison val+ return $ makeIO' $ liftIO $ hFlush port++readChar :: String -> PrimitiveFunc+readChar = noArg $ return $ makeIO $ liftIO (Char <$> getChar)++readCharFromPort :: String -> PrimitiveFunc+readCharFromPort = oneArg' $ \val -> do+ port <- fromEgison val+ return . makeIO $ liftIO (Char <$> hGetChar port)++readLine :: String -> PrimitiveFunc+readLine = noArg $ return $ makeIO $ liftIO (toEgison <$> T.getLine)++readLineFromPort :: String -> PrimitiveFunc+readLineFromPort = oneArg' $ \val -> do+ port <- fromEgison val+ return $ makeIO $ liftIO (toEgison <$> T.hGetLine port)++readFile' :: String -> PrimitiveFunc+readFile' = oneArg' $ \val -> do+ filename <- fromEgison val+ return $ makeIO $ liftIO (toEgison <$> T.readFile (T.unpack filename))++isEOFStdin :: String -> PrimitiveFunc+isEOFStdin = noArg $ return $ makeIO $ liftIO (Bool <$> isEOF)++isEOFPort :: String -> PrimitiveFunc+isEOFPort = oneArg' $ \val -> do+ port <- fromEgison val+ return $ makeIO $ liftIO (Bool <$> hIsEOF port)++randRange :: String -> PrimitiveFunc+randRange = twoArgs' $ \val val' -> do+ i <- fromEgison val :: EvalM Integer+ i' <- fromEgison val' :: EvalM Integer+ return $ makeIO $ liftIO (toEgison <$> getStdRandom (randomR (i, i')))++randRangeDouble :: String -> PrimitiveFunc+randRangeDouble = twoArgs' $ \val val' -> do+ i <- fromEgison val :: EvalM Double+ i' <- fromEgison val' :: EvalM Double+ return $ makeIO $ liftIO (toEgison <$> getStdRandom (randomR (i, i')))++newIORef' :: String -> PrimitiveFunc+newIORef' = noArg $ do+ ref <- liftIO $ newIORef Undefined+ return $ makeIO $ return (RefBox ref)++writeIORef' :: String -> PrimitiveFunc+writeIORef' = twoArgs $ \ref val -> do+ ref' <- fromEgison ref+ return $ makeIO' $ liftIO $ writeIORef ref' val++readIORef' :: String -> PrimitiveFunc+readIORef' = oneArg $ \ref -> do+ ref' <- fromEgison ref+ return $ makeIO $ liftIO $ readIORef ref'++readProcess' :: String -> PrimitiveFunc+readProcess' = threeArgs' $ \cmd args input -> do+ cmd' <- T.unpack <$> fromEgison cmd+ args' <- map T.unpack <$> fromEgison args+ input' <- T.unpack <$> fromEgison input+ return $ makeIO $ do+ outputStr <- liftIO $ readProcess cmd' args' input'+ return (String (T.pack outputStr))++io :: String -> LazyPrimitiveFunc+io = lazyOneArg io'+ where+ io' (Value (IOFunc m)) = do+ val <- m >>= evalWHNF+ case val of+ Tuple [_, val'] -> return $ Value val'+ _ -> throwError =<< TypeMismatch "io" (Value val) <$> getFuncNameStack+ io' whnf = throwError =<< TypeMismatch "io" whnf <$> getFuncNameStack
+ hs-src/Language/Egison/Primitives/String.hs view
@@ -0,0 +1,112 @@+{- |+Module : Language.Egison.Primitives.String+Licence : MIT++This module implements primitive functions that operates on / returns strings.+-}++module Language.Egison.Primitives.String+ ( primitiveStringFunctions+ ) where++import Control.Monad.Except++import qualified Data.Sequence as Sq+import qualified Data.Text as T++import Text.Regex.TDFA ((=~~))++import Language.Egison.Data+import Language.Egison.Eval+import Language.Egison.Parser+import Language.Egison.Pretty+import Language.Egison.Primitives.Utils+++primitiveStringFunctions :: [(String, EgisonValue)]+primitiveStringFunctions =+ map (\(name, fn) -> (name, PrimitiveFunc (fn name))) strictPrimitives++strictPrimitives :: [(String, String -> PrimitiveFunc)]+strictPrimitives =+ [ ("pack", pack)+ , ("unpack", unpack)+ , ("unconsString", unconsString)+ , ("lengthString", lengthString)+ , ("appendString", appendString)+ , ("splitString", splitString)+ , ("regex", regexString)+ , ("regexCg", regexStringCaptureGroup)++ , ("read", read')+ , ("readTsv", readTSV)+ , ("show", show')+ , ("showTsv", showTSV')+ ]++pack :: String -> PrimitiveFunc+pack = unaryOp T.pack++unpack :: String -> PrimitiveFunc+unpack = unaryOp T.unpack++unconsString :: String -> PrimitiveFunc+unconsString = oneArg $ \val -> do+ str <- fromEgison val+ case T.uncons str of+ Just (c, rest) -> return $ Tuple [Char c, String rest]+ Nothing -> throwError $ Default "Tried to unsnoc empty string"++lengthString :: String -> PrimitiveFunc+lengthString = unaryOp (toInteger . T.length)++appendString :: String -> PrimitiveFunc+appendString = binaryOp T.append++splitString :: String -> PrimitiveFunc+splitString = twoArgs $ \pat src -> do+ patStr <- fromEgison pat+ srcStr <- fromEgison src+ return . Collection . Sq.fromList $ map String $ T.splitOn patStr srcStr++regexString :: String -> PrimitiveFunc+regexString = twoArgs $ \pat src -> do+ patStr <- fromEgison pat+ srcStr <- fromEgison src+ case (T.unpack srcStr =~~ T.unpack patStr) :: (Maybe (String, String, String)) of+ Nothing -> return . Collection . Sq.fromList $ []+ Just (a,b,c) -> return . Collection . Sq.fromList $ [Tuple [String (T.pack a), String (T.pack b), String (T.pack c)]]++regexStringCaptureGroup :: String -> PrimitiveFunc+regexStringCaptureGroup = twoArgs $ \pat src -> do+ patStr <- fromEgison pat+ srcStr <- fromEgison src+ case (T.unpack srcStr =~~ T.unpack patStr) :: (Maybe [[String]]) of+ Nothing -> return . Collection . Sq.fromList $ []+ Just ((x:xs):_) -> do let (a, c) = T.breakOn (T.pack x) srcStr+ return . Collection . Sq.fromList $ [Tuple [String a, Collection (Sq.fromList (map (String . T.pack) xs)), String (T.drop (length x) c)]]++--+-- Read / Show+--++read' :: String -> PrimitiveFunc+read'= oneArg' $ \val -> do+ str <- fromEgison val+ ast <- readExpr (T.unpack str)+ evalExpr nullEnv ast++readTSV :: String -> PrimitiveFunc+readTSV = oneArg' $ \val -> do+ str <- fromEgison val+ exprs <- mapM (readExpr . T.unpack) (T.split (== '\t') str)+ rets <- mapM (evalExpr nullEnv) exprs+ case rets of+ [ret] -> return ret+ _ -> return (Tuple rets)++show' :: String -> PrimitiveFunc+show'= oneArg' $ \val -> return $ toEgison $ T.pack $ show val++showTSV' :: String -> PrimitiveFunc+showTSV'= oneArg' $ \val -> return $ toEgison $ T.pack $ showTSV val
+ hs-src/Language/Egison/Primitives/Types.hs view
@@ -0,0 +1,126 @@+{- |+Module : Language.Egison.Primitives.Types+Licence : MIT++This module implements primitive functions that dynamically checks the types of+objects.+-}++module Language.Egison.Primitives.Types+ ( primitiveTypeFunctions+ ) where++import Control.Monad.Except++import Data.Char (chr, ord)+import Data.Ratio ((%))++import Language.Egison.Data+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.Math+import Language.Egison.Primitives.Utils++primitiveTypeFunctions :: [(String, EgisonValue)]+primitiveTypeFunctions =+ map (\(name, fn) -> (name, PrimitiveFunc (fn name))) strictPrimitives +++ map (\(name, fn) -> (name, LazyPrimitiveFunc (fn name))) lazyPrimitives++strictPrimitives :: [(String, String -> PrimitiveFunc)]+strictPrimitives =+ [ ("itof", integerToFloat)+ , ("rtof", rationalToFloat)+ , ("ctoi", charToInteger)+ , ("itoc", integerToChar)+ ]++lazyPrimitives :: [(String, String -> LazyPrimitiveFunc)]+lazyPrimitives =+ [ ("isBool", lazyOneArg isBool)+ , ("isInteger", lazyOneArg isInteger)+ , ("isRational", lazyOneArg isRational)+ , ("isScalar", lazyOneArg isScalar)+ , ("isFloat", lazyOneArg isFloat)+ , ("isChar", lazyOneArg isChar)+ , ("isString", lazyOneArg isString)+ , ("isCollection", lazyOneArg isCollection)+ , ("isHash", lazyOneArg isHash)+ , ("isTensor", lazyOneArg isTensor)+ ]++--+-- Typing+--++isBool :: WHNFData -> EvalM WHNFData+isBool (Value (Bool _)) = return . Value $ Bool True+isBool _ = return . Value $ Bool False++isInteger :: WHNFData -> EvalM WHNFData+isInteger (Value (ScalarData (Div (Plus []) (Plus [Term 1 []])))) = return . Value $ Bool True+isInteger (Value (ScalarData (Div (Plus [Term _ []]) (Plus [Term 1 []])))) = return . Value $ Bool True+isInteger _ = return . Value $ Bool False++isRational :: WHNFData -> EvalM WHNFData+isRational (Value (ScalarData (Div (Plus []) (Plus [Term _ []])))) = return . Value $ Bool True+isRational (Value (ScalarData (Div (Plus [Term _ []]) (Plus [Term _ []])))) = return . Value $ Bool True+isRational _ = return . Value $ Bool False++isScalar :: WHNFData -> EvalM WHNFData+isScalar (Value (ScalarData _)) = return . Value $ Bool True+isScalar _ = return . Value $ Bool False++isTensor :: WHNFData -> EvalM WHNFData+isTensor (Value (TensorData _)) = return . Value $ Bool True+isTensor (ITensor _) = return . Value $ Bool True+isTensor _ = return . Value $ Bool False++isFloat :: WHNFData -> EvalM WHNFData+isFloat (Value (Float _)) = return . Value $ Bool True+isFloat _ = return . Value $ Bool False++isChar :: WHNFData -> EvalM WHNFData+isChar (Value (Char _)) = return . Value $ Bool True+isChar _ = return . Value $ Bool False++isString :: WHNFData -> EvalM WHNFData+isString (Value (String _)) = return . Value $ Bool True+isString _ = return . Value $ Bool False++isCollection :: WHNFData -> EvalM WHNFData+isCollection (Value (Collection _)) = return . Value $ Bool True+isCollection (ICollection _) = return . Value $ Bool True+isCollection _ = return . Value $ Bool False++isHash :: WHNFData -> EvalM WHNFData+isHash (Value (IntHash _)) = return . Value $ Bool True+isHash (Value (CharHash _)) = return . Value $ Bool True+isHash (Value (StrHash _)) = return . Value $ Bool True+isHash (IIntHash _) = return . Value $ Bool True+isHash (ICharHash _) = return . Value $ Bool True+isHash (IStrHash _) = return . Value $ Bool True+isHash _ = return . Value $ Bool False++--+-- Transform+--+integerToFloat :: String -> PrimitiveFunc+integerToFloat = rationalToFloat++rationalToFloat :: String -> PrimitiveFunc+rationalToFloat = oneArg $ \val ->+ case val of+ ScalarData (Div (Plus []) _) -> return $ Float 0+ ScalarData (Div (Plus [Term x []]) (Plus [Term y []])) -> return $ Float (fromRational (x % y))+ _ -> throwError =<< TypeMismatch "integer or rational number" (Value val) <$> getFuncNameStack++charToInteger :: String -> PrimitiveFunc+charToInteger = unaryOp ctoi+ where+ ctoi :: Char -> Integer+ ctoi = fromIntegral . ord++integerToChar :: String -> PrimitiveFunc+integerToChar = unaryOp itoc+ where+ itoc :: Integer -> Char+ itoc = chr . fromIntegral
+ hs-src/Language/Egison/Primitives/Utils.hs view
@@ -0,0 +1,102 @@+{- |+Module : Language.Egison.Primitives.Utils+Licence : MIT+-}++module Language.Egison.Primitives.Utils+ ( noArg+ , oneArg+ , oneArg'+ , twoArgs+ , twoArgs'+ , threeArgs'+ , lazyOneArg+ , unaryOp+ , binaryOp+ ) where++import Control.Monad.Except++import qualified Data.Vector as V++import Language.Egison.Data+import Language.Egison.EvalState (MonadEval(..))+import Language.Egison.Tensor++{-# INLINE noArg #-}+noArg :: EvalM EgisonValue -> String -> PrimitiveFunc+noArg f name args =+ case args of+ [] -> f+ [Tuple []] -> f+ _ ->+ throwError =<< ArgumentsNumPrimitive name 1 (length args) <$> getFuncNameStack++{-# INLINE oneArg #-}+oneArg :: (EgisonValue -> EvalM EgisonValue) -> String -> PrimitiveFunc+oneArg f name args =+ case args of+ [TensorData (Tensor ns ds js)] -> do+ ds' <- V.mapM f ds+ return $ TensorData (Tensor ns ds' js)+ [arg] -> f arg+ _ ->+ throwError =<< ArgumentsNumPrimitive name 1 (length args) <$> getFuncNameStack++{-# INLINE oneArg' #-}+oneArg' :: (EgisonValue -> EvalM EgisonValue) -> String -> PrimitiveFunc+oneArg' f name args =+ case args of+ [arg] -> f arg+ _ -> + throwError =<< ArgumentsNumPrimitive name 1 (length args) <$> getFuncNameStack++{-# INLINE twoArgs #-}+twoArgs :: (EgisonValue -> EgisonValue -> EvalM EgisonValue) -> String -> PrimitiveFunc+twoArgs f name args =+ case args of+ [TensorData t1@Tensor{}, TensorData t2@Tensor{}] ->+ tProduct (\x y -> f x y) t1 t2 >>= fromTensor+ [TensorData(Tensor ns ds js), val] -> do+ ds' <- V.mapM (`f` val) ds+ return $ TensorData (Tensor ns ds' js)+ [val, TensorData (Tensor ns ds js)] -> do+ ds' <- V.mapM (f val) ds+ return $ TensorData (Tensor ns ds' js)+ [val, val'] -> f val val'+ [val] -> return . PrimitiveFunc $ oneArg (f val) name+ _ -> throwError =<< ArgumentsNumPrimitive name 2 (length args) <$> getFuncNameStack++{-# INLINE twoArgs' #-}+twoArgs' :: (EgisonValue -> EgisonValue -> EvalM EgisonValue) -> String -> PrimitiveFunc+twoArgs' f name args =+ case args of+ [val, val'] -> f val val'+ [val] -> return . PrimitiveFunc $ oneArg' (f val) name+ _ -> throwError =<< ArgumentsNumPrimitive name 2 (length args) <$> getFuncNameStack++{-# INLINE threeArgs' #-}+threeArgs' :: (EgisonValue -> EgisonValue -> EgisonValue -> EvalM EgisonValue) -> String -> PrimitiveFunc+threeArgs' f name args =+ case args of+ [val, val', val''] -> f val val' val''+ [val, val'] -> return . PrimitiveFunc $ oneArg' (f val val') name+ [val] -> return . PrimitiveFunc $ twoArgs' (f val) name+ _ -> throwError =<< ArgumentsNumPrimitive name 3 (length args) <$> getFuncNameStack++lazyOneArg :: (WHNFData -> EvalM WHNFData) -> String -> LazyPrimitiveFunc+lazyOneArg f name args =+ case args of+ [arg] -> f arg+ _ -> throwError =<< ArgumentsNumPrimitive name 1 (length args) <$> getFuncNameStack++unaryOp :: (EgisonData a, EgisonData b) => (a -> b) -> String -> PrimitiveFunc+unaryOp op = oneArg $ \val -> do+ v <- fromEgison val+ return $ toEgison (op v)++binaryOp :: (EgisonData a, EgisonData b) => (a -> a -> b) -> String -> PrimitiveFunc+binaryOp op = twoArgs $ \val val' -> do+ i <- fromEgison val+ i' <- fromEgison val'+ return $ toEgison (op i i')
+ hs-src/Language/Egison/RState.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}++{- |+Module : Language.Egison.RState+Licence : MIT++This module defines runtime state.+-}++module Language.Egison.RState+ ( RState (..)+ , RuntimeT+ , RuntimeM+ , MonadRuntime (..)+ , runRuntimeT+ , evalRuntimeT+ ) where++import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State.Strict++import Language.Egison.AST+import Language.Egison.CmdOptions++--+-- Runtime State+--++data RState = RState+ { indexCounter :: Int+ , exprOps :: [Op]+ , patternOps :: [Op]+ }++initialRState :: RState+initialRState = RState+ { indexCounter = 0+ , exprOps = reservedExprOp+ , patternOps = reservedPatternOp+ }++type RuntimeT m = ReaderT EgisonOpts (StateT RState m)++type RuntimeM = RuntimeT IO++class (Applicative m, Monad m) => MonadRuntime m where+ fresh :: m String++instance Monad m => MonadRuntime (RuntimeT m) where+ fresh = do+ st <- lift get+ lift (modify (\st -> st { indexCounter = indexCounter st + 1 }))+ return $ "$_" ++ show (indexCounter st)++runRuntimeT :: Monad m => EgisonOpts -> RuntimeT m a -> m (a, RState)+runRuntimeT opts = flip runStateT initialRState . flip runReaderT opts++evalRuntimeT :: Monad m => EgisonOpts -> RuntimeT m a -> m a+evalRuntimeT opts = flip evalStateT initialRState . flip runReaderT opts
hs-src/Language/Egison/Tensor.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE ViewPatterns #-} {- | Module : Language.Egison.Tensor@@ -12,27 +13,21 @@ -} module Language.Egison.Tensor- (+ ( TensorComponent (..) -- * Tensor- initTensor- , tToList- , tIndex , tref , enumTensorIndices , changeIndex , tTranspose , tTranspose' , tFlipIndices- , appendDFscripts- , removeDFscripts+ , appendDF+ , removeDF , tMap , tMap2- , tMapN- , tSum , tProduct , tContract , tContract'- , tConcat , tConcat' ) where @@ -40,32 +35,64 @@ import Control.Monad.Except hiding (join) import qualified Data.Vector as V-import Data.List (delete, find, findIndex,- partition, (\\))+import Data.List (delete, intersect, partition, (\\)) -import Control.Egison hiding (Integer)+import Control.Egison import qualified Control.Egison as M -import Language.Egison.AST hiding (PatVar) import Language.Egison.Data-import Language.Egison.IState (fresh, getFuncNameStack)-import Language.Egison.MathExpr+import Language.Egison.Data.Utils+import Language.Egison.EvalState (getFuncNameStack)+import Language.Egison.IExpr (Index(..), extractSupOrSubIndex)+import Language.Egison.Math+import Language.Egison.RState ++data IndexM m = IndexM m+instance M.Matcher m a => M.Matcher (IndexM m) (Index a)++sub :: M.Matcher m a => M.Pattern (PP a) (IndexM m) (Index a) a+sub _ _ (Sub a) = pure a+sub _ _ _ = mzero+subM :: M.Matcher m a => IndexM m -> Index a -> m+subM (IndexM m) _ = m++sup :: M.Matcher m a => M.Pattern (PP a) (IndexM m) (Index a) a+sup _ _ (Sup a) = pure a+sup _ _ _ = mzero+supM :: M.Matcher m a => IndexM m -> Index a -> m+supM (IndexM m) _ = m++supsub :: M.Matcher m a => M.Pattern (PP a) (IndexM m) (Index a) a+supsub _ _ (SupSub a) = pure a+supsub _ _ _ = mzero+supsubM :: M.Matcher m a => IndexM m -> Index a -> m+supsubM (IndexM m) _ = m+ -- -- Tensors -- -initTensor :: Shape -> [a] -> Tensor a-initTensor ns xs = Tensor ns (V.fromList xs) []+class TensorComponent a b | a -> b where+ fromTensor :: Tensor b -> EvalM a+ toTensor :: a -> EvalM (Tensor b) +instance TensorComponent EgisonValue EgisonValue where+ fromTensor t@Tensor{} = return $ TensorData t+ fromTensor (Scalar x) = return x+ toTensor (TensorData t) = return t+ toTensor x = return $ Scalar x++instance TensorComponent WHNFData ObjectRef where+ fromTensor t@Tensor{} = return $ ITensor t+ fromTensor (Scalar x) = evalRef x+ toTensor (ITensor t) = return t+ toTensor x = Scalar <$> newEvaluatedObjectRef x+ tShape :: Tensor a -> Shape tShape (Tensor ns _ _) = ns tShape (Scalar _) = [] -tToList :: Tensor a -> [a]-tToList (Tensor _ xs _) = V.toList xs-tToList (Scalar x) = [x]- tToVector :: Tensor a -> V.Vector a tToVector (Tensor _ xs _) = xs tToVector (Scalar x) = V.fromList [x]@@ -74,80 +101,60 @@ tIndex (Tensor _ _ js) = js tIndex (Scalar _) = [] -tIntRef' :: HasTensor a => Integer -> Tensor a -> EvalM a+tIntRef' :: Integer -> Tensor a -> EvalM (Tensor a) tIntRef' i (Tensor [n] xs _) = if 0 < i && i <= n- then fromTensor $ Scalar $ xs V.! fromIntegral (i - 1)+ then return . Scalar $ xs V.! fromIntegral (i - 1) else throwError =<< TensorIndexOutOfBounds i n <$> getFuncNameStack tIntRef' i (Tensor (n:ns) xs js) = if 0 < i && i <= n- then let w = fromIntegral (product ns) in- let ys = V.take w (V.drop (w * fromIntegral (i - 1)) xs) in- fromTensor $ Tensor ns ys (cdr js)+ then let w = fromIntegral (product ns)+ ys = V.take w (V.drop (w * fromIntegral (i - 1)) xs)+ in return $ Tensor ns ys (cdr js) else throwError =<< TensorIndexOutOfBounds i n <$> getFuncNameStack tIntRef' _ _ = throwError $ Default "More indices than the order of the tensor" -tIntRef :: HasTensor a => [Integer] -> Tensor a -> EvalM (Tensor a)+tIntRef :: [Integer] -> Tensor a -> EvalM (Tensor a) tIntRef [] (Tensor [] xs _) | V.length xs == 1 = return $ Scalar (xs V.! 0) | otherwise = throwError =<< EgisonBug "sevaral elements in scalar tensor" <$> getFuncNameStack tIntRef [] t = return t-tIntRef (m:ms) t = tIntRef' m t >>= toTensor >>= tIntRef ms+tIntRef (m:ms) t = tIntRef' m t >>= tIntRef ms --- TODO(momohatt): Refactor.-tref :: HasTensor a => [Index EgisonValue] -> Tensor a -> EvalM a+tIntRef1 :: [Integer] -> Tensor a -> EvalM a+tIntRef1 [] (Scalar x) = return x+tIntRef1 [] (Tensor [] xs _) | V.length xs == 1 = return (xs V.! 0)+tIntRef1 [] _ = throwError =<< EgisonBug "sevaral elements in scalar tensor" <$> getFuncNameStack+tIntRef1 (m:ms) t = tIntRef' m t >>= tIntRef1 ms++pattern SupOrSubIndex :: a -> Index a+pattern SupOrSubIndex i <- (extractSupOrSubIndex -> Just i)++tref :: [Index EgisonValue] -> Tensor a -> EvalM (Tensor a) tref [] (Tensor [] xs _)- | V.length xs == 1 = fromTensor $ Scalar (xs V.! 0)+ | V.length xs == 1 = return $ Scalar (xs V.! 0) | otherwise = throwError =<< EgisonBug "sevaral elements in scalar tensor" <$> getFuncNameStack-tref [] t = fromTensor t-tref (s@(Subscript (ScalarData (SingleSymbol _))):ms) (Tensor (_:ns) xs js) = do- let yss = split (product ns) xs- ts <- mapM (\ys -> tref ms (Tensor ns ys (cdr js))) yss- mapM toTensor ts >>= tConcat s >>= fromTensor-tref (s@(Superscript (ScalarData (SingleSymbol _))):ms) (Tensor (_:ns) xs js) = do- let yss = split (product ns) xs- ts <- mapM (\ys -> tref ms (Tensor ns ys (cdr js))) yss- mapM toTensor ts >>= tConcat s >>= fromTensor-tref (s@(SupSubscript (ScalarData (SingleSymbol _))):ms) (Tensor (_:ns) xs js) = do+tref [] t = return t+tref (s@(SupOrSubIndex (ScalarData (SingleSymbol _))):ms) (Tensor (_:ns) xs js) = do let yss = split (product ns) xs ts <- mapM (\ys -> tref ms (Tensor ns ys (cdr js))) yss- mapM toTensor ts >>= tConcat s >>= fromTensor-tref (Subscript (ScalarData (SingleTerm m [])):ms) t = tIntRef' m t >>= toTensor >>= tref ms-tref (Superscript (ScalarData (SingleTerm m [])):ms) t = tIntRef' m t >>= toTensor >>= tref ms-tref (SupSubscript (ScalarData (SingleTerm m [])):ms) t = tIntRef' m t >>= toTensor >>= tref ms-tref (Subscript (ScalarData ZeroExpr):_) _ = throwError $ Default "tensor index out of bounds: 0"-tref (Superscript (ScalarData ZeroExpr):_) _ = throwError $ Default "tensor index out of bounds: 0"-tref (SupSubscript (ScalarData ZeroExpr):_) _ = throwError $ Default "tensor index out of bounds: 0"-tref (Subscript (Tuple [mVal, nVal]):ms) t@(Tensor is _ _) = do- m <- fromEgison mVal- n <- fromEgison nVal- if m > n- then- fromTensor (Tensor (replicate (length is) 0) V.empty [])- else do- ts <- mapM (\i -> tIntRef' i t >>= toTensor >>= tref ms >>= toTensor) [m..n]- symId <- fresh- tConcat (Subscript (symbolScalarData "" (":::" ++ symId))) ts >>= fromTensor-tref (Superscript (Tuple [mVal, nVal]):ms) t@(Tensor is _ _) = do- m <- fromEgison mVal- n <- fromEgison nVal- if m > n- then- fromTensor (Tensor (replicate (length is) 0) V.empty [])- else do- ts <- mapM (\i -> tIntRef' i t >>= toTensor >>= tref ms >>= toTensor) [m..n]- symId <- fresh- tConcat (Superscript (symbolScalarData "" (":::" ++ symId))) ts >>= fromTensor-tref (SupSubscript (Tuple [mVal, nVal]):ms) t@(Tensor is _ _) = do+ tConcat s ts+tref (SupOrSubIndex (ScalarData (SingleTerm m [])):ms) t = tIntRef' m t >>= tref ms+tref (SupOrSubIndex (ScalarData ZeroExpr):_) _ = throwError $ Default "tensor index out of bounds: 0"+tref (s@(SupOrSubIndex (Tuple [mVal, nVal])):ms) t@(Tensor is _ _) = do m <- fromEgison mVal n <- fromEgison nVal if m > n then- fromTensor (Tensor (replicate (length is) 0) V.empty [])+ return (Tensor (replicate (length is) 0) V.empty []) else do- ts <- mapM (\i -> tIntRef' i t >>= toTensor >>= tref ms >>= toTensor) [m..n]+ ts <- mapM (\i -> tIntRef' i t >>= tref ms) [m..n] symId <- fresh- tConcat (SupSubscript (symbolScalarData "" (":::" ++ symId))) ts >>= fromTensor+ let index = symbolScalarData "" (":::" ++ symId)+ case s of+ Sub{} -> tConcat (Sub index) ts+ Sup{} -> tConcat (Sup index) ts+ SupSub{} -> tConcat (SupSub index) ts tref (_:_) _ = throwError $ Default "Tensor index must be an integer or a single symbol." -- Enumarates all indices (1-indexed) from shape@@ -159,107 +166,83 @@ enumTensorIndices (n:ns) = concatMap (\i -> map (i:) (enumTensorIndices ns)) [1..n] changeIndex :: Index String -> EgisonValue -> Index String-changeIndex (Superscript s) m = Superscript (s ++ show m)-changeIndex (Subscript s) m = Subscript (s ++ show m)+changeIndex (Sup s) m = Sup (s ++ show m)+changeIndex (Sub s) m = Sub (s ++ show m) -- transIndex [a, b, c] [c, a, b] [2, 3, 4] = [4, 2, 3]-transIndex :: [Index EgisonValue] -> [Index EgisonValue] -> [Integer] -> EvalM [Integer]+transIndex :: [Index EgisonValue] -> [Index EgisonValue] -> Shape -> EvalM Shape transIndex is js ns = do- mapM (\j -> matchDFS (zip is ns) (List (Pair Eql M.Something))- [[mc| _ ++ (#j, $n) : _ -> return n |]- ,[mc| _ -> throwError $ Default "cannot transpose becuase of the inconsitent symbolic tensor indices" |]])+ mapM (\j -> case lookup j (zip is ns) of+ Just n -> return n+ Nothing -> throwError $ Default "cannot transpose becuase of the inconsitent symbolic tensor indices") js -tTranspose :: HasTensor a => [Index EgisonValue] -> Tensor a -> EvalM (Tensor a)-tTranspose is t@(Tensor ns _ js) =- if length is <= length js- then do let js' = take (length is) js- let k = fromIntegral (length ns - length is)- let ds = map (DFscript 0) [1..k]- ns' <- transIndex (js' ++ ds) (is ++ ds) ns- xs' <- V.fromList <$> mapM (transIndex (is ++ ds) (js' ++ ds)) (enumTensorIndices ns') >>= mapM (`tIntRef` t) >>= mapM fromTensor- return $ Tensor ns' xs' is- else return t+tTranspose :: [Index EgisonValue] -> Tensor a -> EvalM (Tensor a)+tTranspose is t@(Tensor _ _ js) | length is > length js =+ return t+tTranspose is t@(Tensor ns _ js) = do+ let js' = take (length is) js+ let ds = complementWithDF ns is+ ns' <- transIndex (js' ++ ds) (is ++ ds) ns+ xs' <- V.fromList <$> mapM (transIndex (is ++ ds) (js' ++ ds)) (enumTensorIndices ns') >>= mapM (`tIntRef1` t)+ return $ Tensor ns' xs' is -tTranspose' :: HasTensor a => [EgisonValue] -> Tensor a -> EvalM (Tensor a)-tTranspose' is t@(Tensor _ _ js) = do- case g is js of+tTranspose' :: [EgisonValue] -> Tensor a -> EvalM (Tensor a)+tTranspose' is t@(Tensor _ _ js) =+ case mapM (\i -> f i js) is of Nothing -> return t Just is' -> tTranspose is' t where- f :: Index EgisonValue -> EgisonValue- f (Subscript i) = i- f (Superscript i) = i- f (SupSubscript i) = i- g :: [EgisonValue] -> [Index EgisonValue] -> Maybe [Index EgisonValue]- g [] _ = return []- g (i:is) js = case find (\j -> i == f j) js of- Nothing -> Nothing- Just j' -> do js' <- g is js- return $ j':js'+ f :: EgisonValue -> [Index EgisonValue] -> Maybe (Index EgisonValue)+ f i js =+ match dfs js (List (IndexM Eql))+ [ [mc| _ ++ ($j & (sub #i | sup #i | supsub #i)) : _ -> Just j |]+ , [mc| _ -> Nothing |]+ ] -tFlipIndices :: HasTensor a => Tensor a -> EvalM (Tensor a)-tFlipIndices (Tensor ns xs js) = return $ Tensor ns xs (map flipIndex js)- where- flipIndex (Subscript i) = Superscript i- flipIndex (Superscript i) = Subscript i- flipIndex x = x+tFlipIndices :: Tensor a -> EvalM (Tensor a)+tFlipIndices (Tensor ns xs js) = return $ Tensor ns xs (map reverseIndex js) -appendDFscripts :: Integer -> WHNFData -> EvalM WHNFData-appendDFscripts id (Intermediate (ITensor (Tensor s xs is))) = do+appendDF :: Integer -> WHNFData -> WHNFData+appendDF id (ITensor (Tensor s xs is)) = let k = fromIntegral (length s - length is)- return $ Intermediate (ITensor (Tensor s xs (is ++ map (DFscript id) [1..k])))-appendDFscripts id (Value (TensorData (Tensor s xs is))) = do+ in ITensor (Tensor s xs (is ++ map (DF id) [1..k]))+appendDF id (Value (TensorData (Tensor s xs is))) = let k = fromIntegral (length s - length is)- return $ Value (TensorData (Tensor s xs (is ++ map (DFscript id) [1..k])))-appendDFscripts _ whnf = return whnf+ in Value (TensorData (Tensor s xs (is ++ map (DF id) [1..k])))+appendDF _ whnf = whnf -removeDFscripts :: WHNFData -> EvalM WHNFData-removeDFscripts (Intermediate (ITensor (Tensor s xs is))) = do+removeDF :: WHNFData -> EvalM WHNFData+removeDF (ITensor (Tensor s xs is)) = do let (ds, js) = partition isDF is Tensor s ys _ <- tTranspose (js ++ ds) (Tensor s xs is)- return (Intermediate (ITensor (Tensor s ys js)))+ return (ITensor (Tensor s ys js)) where- isDF (DFscript _ _) = True- isDF _ = False-removeDFscripts (Value (TensorData (Tensor s xs is))) = do+ isDF (DF _ _) = True+ isDF _ = False+removeDF (Value (TensorData (Tensor s xs is))) = do let (ds, js) = partition isDF is Tensor s ys _ <- tTranspose (js ++ ds) (Tensor s xs is) return (Value (TensorData (Tensor s ys js))) where- isDF (DFscript _ _) = True- isDF _ = False-removeDFscripts whnf = return whnf+ isDF (DF _ _) = True+ isDF _ = False+removeDF whnf = return whnf -tMap :: HasTensor a => (a -> EvalM a) -> Tensor a -> EvalM (Tensor a)+tMap :: (a -> EvalM b) -> Tensor a -> EvalM (Tensor b) tMap f (Tensor ns xs js') = do- let k = fromIntegral $ length ns - length js'- let js = js' ++ map (DFscript 0) [1..k]- xs' <- V.fromList <$> mapM f (V.toList xs)- t <- toTensor (V.head xs')- case t of- Tensor ns1 _ js1' -> do- let k1 = fromIntegral $ length ns1 - length js1'- let js1 = js1' ++ map (DFscript 0) [1..k1]- tContract' $ Tensor (ns ++ ns1) (V.concat (V.toList (V.map tensorElems xs'))) (js ++ js1)- _ -> return $ Tensor ns xs' js+ let js = js' ++ complementWithDF ns js'+ xs' <- V.mapM f xs+ return $ Tensor ns xs' js tMap f (Scalar x) = Scalar <$> f x -tMapN :: HasTensor a => ([a] -> EvalM a) -> [Tensor a] -> EvalM (Tensor a)-tMapN f ts@(Tensor ns _ js : _) = do- xs' <- mapM (\is -> mapM (tIntRef is) ts >>= mapM fromTensor >>= f) (enumTensorIndices ns)- return $ Tensor ns (V.fromList xs') js-tMapN f xs = Scalar <$> (mapM fromTensor xs >>= f)--tMap2 :: HasTensor a => (a -> a -> EvalM a) -> Tensor a -> Tensor a -> EvalM (Tensor a)+tMap2 :: (a -> b -> EvalM c) -> Tensor a -> Tensor b -> EvalM (Tensor c) tMap2 f (Tensor ns1 xs1 js1') (Tensor ns2 xs2 js2') = do- let k1 = fromIntegral $ length ns1 - length js1'- let js1 = js1' ++ map (DFscript 0) [1..k1]- let k2 = fromIntegral $ length ns2 - length js2'- let js2 = js2' ++ map (DFscript 0) [1..k2]- let (cjs, tjs1, tjs2) = h js1 js2- t1' <- tTranspose (cjs ++ tjs1) (Tensor ns1 xs1 js1)- t2' <- tTranspose (cjs ++ tjs2) (Tensor ns2 xs2 js2)+ let js1 = js1' ++ complementWithDF ns1 js1'+ let js2 = js2' ++ complementWithDF ns2 js2'+ let cjs = js1 `intersect` js2+ t1' <- tTranspose (cjs ++ (js1 \\ cjs)) (Tensor ns1 xs1 js1)+ t2' <- tTranspose (cjs ++ (js2 \\ cjs)) (Tensor ns2 xs2 js2) let cns = take (length cjs) (tShape t1') rts1 <- mapM (`tIntRef` t1') (enumTensorIndices cns) rts2 <- mapM (`tIntRef` t2') (enumTensorIndices cns)@@ -267,9 +250,6 @@ let ret = Tensor (cns ++ tShape (head rts')) (V.concat (map tToVector rts')) (cjs ++ tIndex (head rts')) tTranspose (uniq (tDiagIndex (js1 ++ js2))) ret where- h :: [Index EgisonValue] -> [Index EgisonValue] -> ([Index EgisonValue], [Index EgisonValue], [Index EgisonValue])- h js1 js2 = let cjs = filter (`elem` js2) js1 in- (cjs, js1 \\ cjs, js2 \\ cjs) uniq :: [Index EgisonValue] -> [Index EgisonValue] uniq [] = [] uniq (x:xs) = x:uniq (delete x xs)@@ -277,7 +257,7 @@ tMap2 f (Scalar x) t@Tensor{} = tMap (f x) t tMap2 f (Scalar x1) (Scalar x2) = Scalar <$> f x1 x2 -tDiag :: HasTensor a => Tensor a -> EvalM (Tensor a)+tDiag :: Tensor a -> EvalM (Tensor a) tDiag t@(Tensor _ _ js) = case filter (\j -> any (p j) js) js of [] -> return t@@ -285,126 +265,109 @@ let ys = js \\ (xs ++ map reverseIndex xs) t2 <- tTranspose (xs ++ map reverseIndex xs ++ ys) t let (ns1, tmp) = splitAt (length xs) (tShape t2)- let (_, ns2) = splitAt (length xs) tmp+ let ns2 = drop (length xs) tmp ts <- mapM (\is -> tIntRef (is ++ is) t2) (enumTensorIndices ns1)- return $ Tensor (ns1 ++ ns2) (V.concat (map tToVector ts)) (map toSupSubscript xs ++ ys)+ return $ Tensor (ns1 ++ ns2) (V.concat (map tToVector ts)) (map toSupSub xs ++ ys) where p :: Index EgisonValue -> Index EgisonValue -> Bool- p (Superscript i) (Subscript j) = i == j- p (Subscript _) _ = False- p _ _ = False+ p (Sup i) (Sub j) = i == j+ p _ _ = False tDiag t = return t tDiagIndex :: [Index EgisonValue] -> [Index EgisonValue] tDiagIndex js =- let xs = filter (\j -> any (p j) js) js- ys = js \\ (xs ++ map reverseIndex xs)- in map toSupSubscript xs ++ ys- where- p :: Index EgisonValue -> Index EgisonValue -> Bool- p (Superscript i) (Subscript j) = i == j- p (Subscript _) _ = False- p _ _ = False--tSum :: HasTensor a => (a -> a -> EvalM a) -> Tensor a -> Tensor a -> EvalM (Tensor a)-tSum f (Tensor ns1 xs1 js1) t2@Tensor{} = do- t2' <- tTranspose js1 t2- case t2' of- (Tensor ns2 xs2 _)- | ns2 == ns1 -> do ys <- V.mapM (uncurry f) (V.zip xs1 xs2)- return (Tensor ns1 ys js1)- | otherwise -> throwError =<< InconsistentTensorShape <$> getFuncNameStack+ match dfs js (List (IndexM Eql))+ [ [mc| $hjs ++ sup $i : $mjs ++ sub #i : $tjs ->+ tDiagIndex (SupSub i : hjs ++ mjs ++ tjs) |]+ , [mc| $hjs ++ sub $i : $mjs ++ sup #i : $tjs ->+ tDiagIndex (SupSub i : hjs ++ mjs ++ tjs) |]+ , [mc| _ -> js |]+ ] -tProduct :: HasTensor a => (a -> a -> EvalM a) -> Tensor a -> Tensor a -> EvalM (Tensor a)+tProduct :: (a -> b -> EvalM c) -> Tensor a -> Tensor b -> EvalM (Tensor c) tProduct f (Tensor ns1 xs1 js1') (Tensor ns2 xs2 js2') = do- let k1 = fromIntegral $ length ns1 - length js1'- let js1 = js1' ++ map (DFscript 0) [1..k1]- let k2 = fromIntegral $ length ns2 - length js2'- let js2 = js2' ++ map (DFscript 0) [1..k2]+ let js1 = js1' ++ complementWithDF ns1 js1'+ let js2 = js2' ++ complementWithDF ns2 js2' let (cjs1, cjs2, tjs1, tjs2) = h js1 js2 let t1 = Tensor ns1 xs1 js1 let t2 = Tensor ns2 xs2 js2 case cjs1 of [] -> do- xs' <- V.fromList <$> mapM (\is -> do- let is1 = take (length ns1) is- let is2 = take (length ns2) (drop (length ns1) is)- x1 <- tIntRef is1 t1 >>= fromTensor- x2 <- tIntRef is2 t2 >>= fromTensor- f x1 x2) (enumTensorIndices (ns1 ++ ns2))- tContract' (Tensor (ns1 ++ ns2) xs' (js1 ++ js2))+ xs' <- mapM (\is -> do let is1 = take (length ns1) is+ let is2 = take (length ns2) (drop (length ns1) is)+ x1 <- tIntRef1 is1 t1+ x2 <- tIntRef1 is2 t2+ f x1 x2)+ (enumTensorIndices (ns1 ++ ns2))+ tContract' (Tensor (ns1 ++ ns2) (V.fromList xs') (js1 ++ js2)) _ -> do t1' <- tTranspose (cjs1 ++ tjs1) t1 t2' <- tTranspose (cjs2 ++ tjs2) t2 let (cns1, _) = splitAt (length cjs1) (tShape t1') rts' <- mapM (\is -> do rt1 <- tIntRef is t1' rt2 <- tIntRef is t2'- tProduct f rt1 rt2) (enumTensorIndices cns1)- let ret = Tensor (cns1 ++ tShape (head rts')) (V.concat (map tToVector rts')) (map toSupSubscript cjs1 ++ tIndex (head rts'))- tTranspose (uniq (map toSupSubscript cjs1 ++ tjs1 ++ tjs2)) ret+ tProduct f rt1 rt2)+ (enumTensorIndices cns1)+ let ret = Tensor (cns1 ++ tShape (head rts')) (V.concat (map tToVector rts')) (map toSupSub cjs1 ++ tIndex (head rts'))+ tTranspose (uniq (map toSupSub cjs1 ++ tjs1 ++ tjs2)) ret where h :: [Index EgisonValue] -> [Index EgisonValue] -> ([Index EgisonValue], [Index EgisonValue], [Index EgisonValue], [Index EgisonValue]) h js1 js2 = let cjs = filter (\j -> any (p j) js2) js1 in (cjs, map reverseIndex cjs, js1 \\ cjs, js2 \\ map reverseIndex cjs) p :: Index EgisonValue -> Index EgisonValue -> Bool- p (Superscript i) (Subscript j) = i == j- p (Subscript i) (Superscript j) = i == j- p _ _ = False+ p (Sup i) (Sub j) = i == j+ p (Sub i) (Sup j) = i == j+ p _ _ = False uniq :: [Index EgisonValue] -> [Index EgisonValue] uniq [] = [] uniq (x:xs) = x:uniq (delete x xs)-tProduct f (Scalar x) (Tensor ns xs js) = do- xs' <- V.mapM (f x) xs- return $ Tensor ns xs' js-tProduct f (Tensor ns xs js) (Scalar x) = do- xs' <- V.mapM (`f` x) xs- return $ Tensor ns xs' js+tProduct f (Scalar x) t@Tensor{} = tMap (f x) t+tProduct f t@Tensor{} (Scalar x) = tMap (`f` x) t tProduct f (Scalar x1) (Scalar x2) = Scalar <$> f x1 x2 -tContract :: HasTensor a => Tensor a -> EvalM [Tensor a]+tContract :: Tensor a -> EvalM [Tensor a] tContract t = do t' <- tDiag t case t' of- (Tensor (n:_) _ (SupSubscript _ : _)) -> do+ Tensor (n:_) _ (SupSub _ : _) -> do ts <- mapM (`tIntRef'` t') [1..n]- tss <- mapM toTensor ts >>= mapM tContract+ tss <- mapM tContract ts return $ concat tss _ -> return [t'] --- TODO: refactor in PMOP-tContract' :: HasTensor a => Tensor a -> EvalM (Tensor a)+tContract' :: Tensor a -> EvalM (Tensor a) tContract' t@(Tensor ns _ js) =- case findPair p js of- Nothing -> return t- Just (m, n) -> do- let (hjs, mjs, tjs) = removePair (m,n) js- xs' <- mapM (\i -> tref (hjs ++ [Subscript (ScalarData (SingleTerm i []))] ++ mjs- ++ [Subscript (ScalarData (SingleTerm i []))] ++ tjs) t)- [1..(ns !! m)]- mapM toTensor xs' >>= tConcat (js !! m) >>= tTranspose (hjs ++ [js !! m] ++ mjs ++ tjs) >>= tContract'+ match dfs js (List M.Something)+ [ [mc| $hjs ++ $a : $mjs ++ ?(p a) : $tjs -> do+ let m = fromIntegral (length hjs)+ xs' <- mapM (\i -> tref (hjs ++ (Sub (ScalarData (SingleTerm i [])) : mjs)+ ++ (Sub (ScalarData (SingleTerm i [])) : tjs)) t)+ [1..(ns !! m)]+ tConcat a xs' >>= tTranspose (hjs ++ a : mjs ++ tjs) >>= tContract' |]+ , [mc| _ -> return t |]+ ] where p :: Index EgisonValue -> Index EgisonValue -> Bool- p (Superscript i) (Superscript j) = i == j- p (Subscript i) (Subscript j) = i == j- p (DFscript i1 j1) (DFscript i2 j2) = (i1 == i2) && (j1 == j2)- p _ _ = False+ p (Sup i) (Sup j) = i == j+ p (Sub i) (Sub j) = i == j+ p (DF i1 j1) (DF i2 j2) = (i1 == i2) && (j1 == j2)+ p _ _ = False tContract' val = return val -tConcat :: HasTensor a => Index EgisonValue -> [Tensor a] -> EvalM (Tensor a)+tConcat :: Index EgisonValue -> [Tensor a] -> EvalM (Tensor a) tConcat s (Tensor ns@(0:_) _ js:_) = return $ Tensor (0:ns) V.empty (s:js) tConcat s ts@(Tensor ns _ js:_) = return $ Tensor (fromIntegral (length ts):ns) (V.concat (map tToVector ts)) (s:js) tConcat s ts = do ts' <- mapM getScalar ts return $ Tensor [fromIntegral (length ts)] (V.fromList ts') [s] -tConcat' :: HasTensor a => [Tensor a] -> EvalM (Tensor a)+tConcat' :: [Tensor a] -> EvalM (Tensor a) tConcat' (Tensor ns@(0:_) _ _ : _) = return $ Tensor (0:ns) V.empty [] tConcat' ts@(Tensor ns _ _ : _) = return $ Tensor (fromIntegral (length ts):ns) (V.concat (map tToVector ts)) [] tConcat' ts = do ts' <- mapM getScalar ts return $ Tensor [fromIntegral (length ts)] (V.fromList ts') [] - -- utility functions for tensors cdr :: [a] -> [a]@@ -413,37 +376,23 @@ split :: Integer -> V.Vector a -> [V.Vector a] split w xs- | V.null xs = []- | otherwise = let (hs, ts) = V.splitAt (fromIntegral w) xs in- hs:split w ts+ | V.null xs = []+ | otherwise = let (hs, ts) = V.splitAt (fromIntegral w) xs in+ hs:split w ts getScalar :: Tensor a -> EvalM a getScalar (Scalar x) = return x getScalar _ = throwError $ Default "Inconsitent Tensor order" -findPair :: (a -> a -> Bool) -> [a] -> Maybe (Int, Int)-findPair p xs = findPair' 0 p xs---- TODO: refactor in PMOP-findPair' :: Int -> (a -> a -> Bool) -> [a] -> Maybe (Int, Int)-findPair' _ _ [] = Nothing-findPair' m p (x:xs) = case findIndex (p x) xs of- Just i -> Just (m, m + i + 1)- Nothing -> findPair' (m + 1) p xs---- TODO: refactor in PMOP-removePair :: (Int, Int) -> [a] -> ([a],[a],[a])-removePair (m, n) xs = -- (0,1) [i i]- let (hms, tts) = splitAt n xs -- [i] [i]- ts = tail tts -- []- (hs, tms) = splitAt m hms -- [] [i]- ms = tail tms -- []- in (hs, ms, ts) -- [] [] []+reverseIndex :: Index a -> Index a+reverseIndex (Sup i) = Sub i+reverseIndex (Sub i) = Sup i+reverseIndex x = x -reverseIndex :: Index EgisonValue -> Index EgisonValue-reverseIndex (Superscript i) = Subscript i-reverseIndex (Subscript i) = Superscript i+toSupSub :: Index a -> Index a+toSupSub (Sup i) = SupSub i+toSupSub (Sub i) = SupSub i -toSupSubscript :: Index EgisonValue -> Index EgisonValue-toSupSubscript (Superscript i) = SupSubscript i-toSupSubscript (Subscript i) = SupSubscript i+complementWithDF :: Shape -> [Index a] -> [Index a]+complementWithDF ns js' = map (DF 0) [1..k]+ where k = fromIntegral $ length ns - length js'
− hs-src/Language/Egison/Types.hs
@@ -1,115 +0,0 @@-{- |-Module : Language.Egison.Types-Licence : MIT--This module contains functions for dynamic type systems.--}--module Language.Egison.Types- ( isBool- , isInteger- , isRational- , isSymbol- , isScalar- , isTensor- , isTensorWithIndex- , isBool'- , isInteger'- , isRational'- , isScalar'- , isFloat'- , isComplex'- , isTensor'- , isTensorWithIndex'- , isChar'- , isString'- , isCollection'- , isHash'- ) where--import Language.Egison.Data-import Language.Egison.MathExpr------- Typing-----isBool :: EgisonValue -> Bool-isBool (Bool _) = True-isBool _ = False--isBool' :: PrimitiveFunc-isBool' (Value val) = return $ Value $ Bool $ isBool val--isInteger :: EgisonValue -> Bool-isInteger (ScalarData (Div (Plus []) (Plus [Term 1 []]))) = True-isInteger (ScalarData (Div (Plus [Term _ []]) (Plus [Term 1 []]))) = True-isInteger _ = False--isInteger' :: PrimitiveFunc-isInteger' (Value val) = return $ Value $ Bool $ isInteger val--isRational :: EgisonValue -> Bool-isRational (ScalarData (Div (Plus []) (Plus [Term _ []]))) = True-isRational (ScalarData (Div (Plus [Term _ []]) (Plus [Term _ []]))) = True-isRational _ = False--isRational' :: PrimitiveFunc-isRational' (Value val) = return $ Value $ Bool $ isRational val--isSymbol :: EgisonValue -> Bool-isSymbol (ScalarData (Div (Plus [Term 1 [(Symbol{}, 1)]]) (Plus [Term 1 []]))) = True-isSymbol _ = False--isScalar :: EgisonValue -> Bool-isScalar (ScalarData _) = True-isScalar _ = False--isScalar' :: PrimitiveFunc-isScalar' (Value (ScalarData _)) = return $ Value $ Bool True-isScalar' _ = return $ Value $ Bool False--isTensor :: EgisonValue -> Bool-isTensor (TensorData _) = True-isTensor _ = False--isTensor' :: PrimitiveFunc-isTensor' (Value (TensorData _)) = return $ Value $ Bool True-isTensor' (Intermediate (ITensor _)) = return $ Value $ Bool True-isTensor' _ = return $ Value $ Bool False--isTensorWithIndex :: EgisonValue -> Bool-isTensorWithIndex (TensorData (Tensor _ _ (_:_))) = True-isTensorWithIndex _ = False--isTensorWithIndex' :: PrimitiveFunc-isTensorWithIndex' (Value val) = return $ Value $ Bool $ isTensorWithIndex val-isTensorWithIndex' _ = return $ Value $ Bool False--isFloat' :: PrimitiveFunc-isFloat' (Value (Float _)) = return $ Value $ Bool True-isFloat' _ = return $ Value $ Bool False--isComplex' :: PrimitiveFunc-isComplex' (Value (Float _)) = return $ Value $ Bool True-isComplex' _ = return $ Value $ Bool False--isChar' :: PrimitiveFunc-isChar' (Value (Char _)) = return $ Value $ Bool True-isChar' _ = return $ Value $ Bool False--isString' :: PrimitiveFunc-isString' (Value (String _)) = return $ Value $ Bool True-isString' _ = return $ Value $ Bool False--isCollection' :: PrimitiveFunc-isCollection' (Value (Collection _)) = return $ Value $ Bool True-isCollection' (Intermediate (ICollection _)) = return $ Value $ Bool True-isCollection' _ = return $ Value $ Bool False--isHash' :: PrimitiveFunc-isHash' (Value (IntHash _)) = return $ Value $ Bool True-isHash' (Value (StrHash _)) = return $ Value $ Bool True-isHash' (Intermediate (IIntHash _)) = return $ Value $ Bool True-isHash' (Intermediate (IStrHash _)) = return $ Value $ Bool True-isHash' _ = return $ Value $ Bool False
hs-src/Tool/translator.hs view
@@ -1,9 +1,9 @@ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ViewPatterns #-} module Main where import Control.Arrow ((***))-import Data.List (find) import Data.Maybe (fromJust) import Data.Text.Prettyprint.Doc.Render.Text (putDoc) import System.Environment (getArgs)@@ -13,58 +13,85 @@ import Language.Egison.Parser.SExpr import Language.Egison.Pretty ++exprInfix :: [(String, Op)]+exprInfix =+ [ ("**", Op "^" 8 InfixL False)+ , ("**'", Op "^'" 8 InfixL False)+ , ("*", Op "*" 7 InfixL False)+ , ("/", Op "/" 7 InfixL False)+ , ("*'", Op "*'" 7 InfixL False)+ , ("/'", Op "/'" 7 InfixL False)+ , (".", Op "." 7 InfixL False) -- tensor multiplication+ , (".'", Op ".'" 7 InfixL False) -- tensor multiplication+ , ("remainder", Op "%" 7 InfixL False) -- primitive function+ , ("+", Op "+" 6 InfixL False)+ , ("-", Op "-" 6 InfixL False)+ , ("+'", Op "+'" 6 InfixL False)+ , ("-'", Op "-'" 6 InfixL False)+ , ("append", Op "++" 5 InfixR False)+ , ("cons", Op "::" 5 InfixR False)+ , ("equal", Op "=" 4 InfixL False) -- primitive function+ , ("lte", Op "<=" 4 InfixL False) -- primitive function+ , ("gte", Op ">=" 4 InfixL False) -- primitive function+ , ("lt", Op "<" 4 InfixL False) -- primitive function+ , ("gt", Op ">" 4 InfixL False) -- primitive function+ , ("&&", Op "&&" 3 InfixR False)+ , ("and", Op "&&" 3 InfixR False)+ , ("||", Op "||" 2 InfixR False)+ , ("or", Op "||" 2 InfixR False)+ , ("apply", Op "$" 0 InfixR False)+ ]++patternInfix :: [(String, Op)]+patternInfix =+ [ ("^", Op "^" 8 InfixL False) -- PowerPat+ , ("*", Op "*" 7 InfixL False) -- MultPat+ , ("div", Op "/" 7 InfixL False) -- DivPat+ , ("+", Op "+" 6 InfixL False) -- PlusPat+ , ("cons", Op "::" 5 InfixR False)+ , ("join", Op "++" 5 InfixR False)+ , ("&", Op "&" 3 InfixR False)+ , ("|", Op "|" 2 InfixR False)+ ]++lookupVarExprInfix :: String -> Maybe Op+lookupVarExprInfix x = lookup x exprInfix+ class SyntaxElement a where toNonS :: a -> a -instance SyntaxElement EgisonTopExpr where+instance SyntaxElement TopExpr where toNonS (Define x y) = Define (toNonS x) (toNonS y)- toNonS (Redefine _ _) = error "Not supported" toNonS (Test x) = Test (toNonS x) toNonS (Execute x) = Execute (toNonS x) toNonS x = x -instance SyntaxElement EgisonExpr where- toNonS (IntegerExpr x) = IntegerExpr x- toNonS (VarExpr v) | any (\op -> func op == prettyS v) reservedExprInfix =+instance SyntaxElement Expr where+ toNonS (VarExpr (lookupVarExprInfix -> Just op)) = SectionExpr op Nothing Nothing- where- op = fromJust $ find (\op -> func op == prettyS v) reservedExprInfix- toNonS (VarExpr x) = VarExpr (toNonS x)+ toNonS (VarExpr x) = VarExpr x toNonS (IndexedExpr b x ys) = IndexedExpr b (toNonS x) (map toNonS ys) toNonS (SubrefsExpr b x y) = SubrefsExpr b (toNonS x) (toNonS y) toNonS (SuprefsExpr b x y) = SuprefsExpr b (toNonS x) (toNonS y) toNonS (UserrefsExpr b x y) = UserrefsExpr b (toNonS x) (toNonS y)- toNonS (PowerExpr x y) = InfixExpr powerOp (toNonS x) (toNonS y)- where powerOp = fromJust $ find (\op -> repr op == "^") reservedExprInfix- toNonS (InductiveDataExpr x ys) = InductiveDataExpr x (map toNonS ys) toNonS (TupleExpr xs) = TupleExpr (map toNonS xs)- toNonS (CollectionExpr xs)- | all isElementExpr xs = CollectionExpr (map toNonS xs)- | otherwise = f xs- where- isElementExpr :: InnerExpr -> Bool- isElementExpr ElementExpr{} = True- isElementExpr _ = False- f [] = CollectionExpr []- f [ElementExpr x] = CollectionExpr [ElementExpr (toNonS x)]- f [SubCollectionExpr x] = toNonS x- f (ElementExpr x : xs) = InfixExpr cons (toNonS x) (f xs)- f (SubCollectionExpr x : xs) = InfixExpr append (toNonS x) (f xs)- cons = fromJust $ find (\op -> repr op == "::") reservedExprInfix- append = fromJust $ find (\op -> repr op == "++") reservedExprInfix+ toNonS (CollectionExpr xs) = CollectionExpr (map toNonS xs)+ toNonS (ConsExpr x xs) = InfixExpr cons (toNonS x) (toNonS xs)+ where cons = fromJust $ lookup "cons" exprInfix+ toNonS (JoinExpr x xs) = InfixExpr append (toNonS x) (toNonS xs)+ where append = fromJust $ lookup "append" exprInfix toNonS (HashExpr xs) = HashExpr (map (toNonS *** toNonS) xs) toNonS (VectorExpr xs) = VectorExpr (map toNonS xs) - toNonS (LambdaExpr xs e) = LambdaExpr xs (toNonS e)+ toNonS (LambdaExpr xs e) = LambdaExpr xs (toNonS e) toNonS (MemoizedLambdaExpr xs e) = MemoizedLambdaExpr xs (toNonS e) toNonS (CambdaExpr x e) = CambdaExpr x (toNonS e) toNonS (PatternFunctionExpr xs p) = PatternFunctionExpr xs (toNonS p) toNonS (IfExpr x y z) = IfExpr (toNonS x) (toNonS y) (toNonS z) toNonS (LetRecExpr xs y) = LetRecExpr (map toNonS xs) (toNonS y)- toNonS (LetExpr xs y) = LetRecExpr (map toNonS xs) (toNonS y)- toNonS (LetStarExpr xs y) = LetRecExpr (map toNonS xs) (toNonS y) toNonS (WithSymbolsExpr xs y) = WithSymbolsExpr xs (toNonS y) toNonS (MatchExpr pmmode m p xs) = MatchExpr pmmode (toNonS m) (toNonS p) (map toNonS xs)@@ -78,44 +105,31 @@ toNonS (QuoteExpr x) = QuoteExpr (toNonS x) toNonS (QuoteSymbolExpr x) = QuoteSymbolExpr (toNonS x)- toNonS (WedgeApplyExpr (VarExpr f) (TupleExpr (y:ys)))- | any (\op -> func op == prettyS f) reservedExprInfix =- optimize $ foldl (\acc x -> InfixExpr op acc (toNonS x)) (toNonS y) ys+ toNonS (WedgeApplyExpr (VarExpr (lookupVarExprInfix -> Just op)) (y:ys)) =+ optimize $ foldl (\acc x -> InfixExpr op' acc (toNonS x)) (toNonS y) ys where- op =- let op' = fromJust $ find (\op -> func op == prettyS f) reservedExprInfix- in op' { isWedge = True }+ op' = op { isWedge = True } - optimize (InfixExpr (Infix { repr = "*" }) (IntegerExpr (-1)) e2) =+ optimize (InfixExpr Op{ repr = "*" } (ConstantExpr (IntegerExpr (-1))) e2) = PrefixExpr "-" (optimize e2) optimize (InfixExpr op e1 e2) = InfixExpr op (optimize e1) (optimize e2) optimize e = e- toNonS (WedgeApplyExpr x y) = WedgeApplyExpr (toNonS x) (toNonS y)+ toNonS (WedgeApplyExpr x ys) = WedgeApplyExpr (toNonS x) (map toNonS ys) toNonS (DoExpr xs y) = DoExpr (map toNonS xs) (toNonS y)- toNonS (IoExpr x) = IoExpr (toNonS x) toNonS (SeqExpr e1 e2) = SeqExpr (toNonS e1) (toNonS e2)- toNonS (ApplyExpr (VarExpr f) (TupleExpr (y:ys))) | prettyS f == "and" =- foldl (\acc x -> InfixExpr op acc (toNonS x)) (toNonS y) ys- where op = fromJust $ find (\op -> repr op == "&&") reservedExprInfix- toNonS (ApplyExpr (VarExpr f) (TupleExpr (y:ys))) | prettyS f == "or" =- foldl (\acc x -> InfixExpr op acc (toNonS x)) (toNonS y) ys- where op = fromJust $ find (\op -> repr op == "||") reservedExprInfix- toNonS (ApplyExpr (VarExpr f) (TupleExpr (y:ys)))- | any (\op -> func op == prettyS f) reservedExprInfix =- optimize $ foldl (\acc x -> InfixExpr op acc (toNonS x)) (toNonS y) ys+ toNonS (ApplyExpr (VarExpr (lookupVarExprInfix -> Just op)) (y:ys)) =+ optimize $ foldl (\acc x -> InfixExpr op acc (toNonS x)) (toNonS y) ys where- op = fromJust $ find (\op -> func op == prettyS f) reservedExprInfix-- optimize (InfixExpr (Infix { repr = "*" }) (IntegerExpr (-1)) e2) =+ optimize (InfixExpr Op{ repr = "*" } (ConstantExpr (IntegerExpr (-1))) e2) = PrefixExpr "-" (optimize e2) optimize (InfixExpr op e1 e2) = InfixExpr op (optimize e1) (optimize e2) optimize e = e - toNonS (ApplyExpr x y) = ApplyExpr (toNonS x) (toNonS y)+ toNonS (ApplyExpr x ys) = ApplyExpr (toNonS x) (map toNonS ys) toNonS (CApplyExpr e1 e2) = CApplyExpr (toNonS e1) (toNonS e2) toNonS (AnonParamFuncExpr n e) = case AnonParamFuncExpr n (toNonS e) of@@ -138,44 +152,26 @@ toNonS x = x -instance SyntaxElement EgisonPattern where+instance SyntaxElement Pattern where toNonS (ValuePat e) = ValuePat (toNonS e) toNonS (PredPat e) = PredPat (toNonS e) toNonS (IndexedPat p es) = IndexedPat (toNonS p) (map toNonS es) toNonS (LetPat binds pat) = LetPat (map toNonS binds) (toNonS pat) toNonS (InfixPat op p1 p2) = InfixPat op (toNonS p1) (toNonS p2) toNonS (NotPat p) = NotPat (toNonS p)- toNonS (AndPat []) = error "Not supported: empty and pattern"- toNonS (AndPat ps) = toNonS (foldr1 (\p acc -> InfixPat op p acc) ps)- where op = fromJust $ find (\op -> repr op == "&") reservedPatternInfix- toNonS (OrPat []) = error "Not supported: empty or pattern"- toNonS (OrPat ps) = toNonS (foldr1 (\p acc -> InfixPat op p acc) ps)- where op = fromJust $ find (\op -> repr op == "|") reservedPatternInfix+ toNonS (AndPat p1 p2) = InfixPat op (toNonS p1) (toNonS p2)+ where op = fromJust $ lookup "&" patternInfix+ toNonS (OrPat p1 p2) = InfixPat op (toNonS p1) (toNonS p2)+ where op = fromJust $ lookup "|" patternInfix toNonS ForallPat{} = error "Not supported: forall pattern" toNonS (TuplePat ps) = TuplePat (map toNonS ps)- toNonS (InductivePat name [p1, p2])- | any (\op -> func op == name) reservedPatternInfix =- InfixPat op (toNonS p1) (toNonS p2)- where op = fromJust $ find (\op -> func op == name) reservedPatternInfix+ toNonS (InductivePat ((`lookup` patternInfix) -> Just op) [p1, p2]) =+ InfixPat op (toNonS p1) (toNonS p2) toNonS (InductivePat name ps) = InductivePat name (map toNonS ps) toNonS (LoopPat i range p1 p2) = LoopPat i (toNonS range) (toNonS p1) (toNonS p2) toNonS (PApplyPat e p) = PApplyPat (toNonS e) (map toNonS p) toNonS (SeqConsPat p1 p2) = SeqConsPat (toNonS p1) (toNonS p2) toNonS (DApplyPat p ps) = DApplyPat (toNonS p) (map toNonS ps)- toNonS (DivPat p1 p2) = InfixPat op (toNonS p1) (toNonS p2)- where op = fromJust $ find (\op -> repr op == "/") reservedPatternInfix- toNonS (PlusPat []) = InductivePat "plus" []- toNonS (PlusPat [p]) = InductivePat "plus" [toNonS p]- toNonS (PlusPat (p:ps)) =- foldl (\acc x -> InfixPat op acc (toNonS x)) (toNonS p) ps- where op = fromJust $ find (\op -> repr op == "+") reservedPatternInfix- toNonS (MultPat []) = InductivePat "mult" []- toNonS (MultPat [p]) = InductivePat "mult" [toNonS p]- toNonS (MultPat (p:ps)) =- foldl (\acc x -> InfixPat op acc (toNonS x)) (toNonS p) ps- where op = fromJust $ find (\op -> repr op == "*") reservedPatternInfix- toNonS (PowerPat p1 p2) = InfixPat op (toNonS p1) (toNonS p2)- where op = fromJust $ find (\op -> repr op == "^") reservedPatternInfix toNonS p = p instance SyntaxElement PrimitivePatPattern where@@ -188,21 +184,17 @@ toNonS (PDTuplePat pds) = PDTuplePat (map toNonS pds) toNonS (PDConsPat pd1 pd2) = PDConsPat (toNonS pd1) (toNonS pd2) toNonS (PDSnocPat pd1 pd2) = PDSnocPat (toNonS pd1) (toNonS pd2)- toNonS (PDConstantPat e) = PDConstantPat (toNonS e) toNonS pd = pd instance SyntaxElement LoopRange where toNonS (LoopRange e1 e2 p) = LoopRange (toNonS e1) (toNonS e2) (toNonS p) -instance SyntaxElement a => SyntaxElement (Index a) where+instance SyntaxElement a => SyntaxElement (IndexExpr a) where toNonS script = toNonS <$> script -instance SyntaxElement InnerExpr where- toNonS (ElementExpr x) = ElementExpr (toNonS x)- toNonS (SubCollectionExpr _) = error "Not supported: SubCollectionExpr"- instance SyntaxElement BindingExpr where- toNonS (vars, x) = (map toNonS vars, toNonS x)+ toNonS (Bind pdp x) = Bind (toNonS pdp) (toNonS x)+ toNonS (BindWithIndices var x) = BindWithIndices var (toNonS x) instance SyntaxElement MatchClause where toNonS (pat, body) = (toNonS pat, toNonS body)@@ -210,9 +202,8 @@ instance SyntaxElement PatternDef where toNonS (x, y, zs) = (toNonS x, toNonS y, map (\(z, w) -> (toNonS z, toNonS w)) zs) -instance SyntaxElement Var where+instance SyntaxElement VarWithIndices where toNonS = id- main :: IO () main = do
lib/core/assoc.egi view
@@ -4,14 +4,14 @@ -- -- -toAssoc xs :=+def toAssoc xs := match xs as list something with | [] -> [] | $x :: (loop $i (2, $n) (#x :: ...) (!(#x :: _) & $rs)) -> (x, n) :: toAssoc rs -fromAssoc xs :=+def fromAssoc xs := match xs as list (something, integer) with | [] -> [] | ($x, $n) :: $rs -> take n (repeat1 x) ++ fromAssoc rs@@ -19,7 +19,7 @@ -- -- Assoc List ---assocList a :=+def assocList a := matcher | [] as () with | [] -> [()]@@ -49,7 +49,7 @@ -- -- Assoc Multiset ---assocMultiset a :=+def assocMultiset a := matcher | [] as () with | [] -> [()]@@ -85,10 +85,10 @@ | $ as (something) with | $tgt -> [tgt] -AC.intersect xs ys :=+def AC.intersect xs ys := matchAll (xs, ys) as (assocMultiset something, assocMultiset something) with | (ncons $x $m _, ncons #x $n _) -> (x, min m n) -AC.intersectAs a xs ys :=+def AC.intersectAs a xs ys := matchAll (xs, ys) as (assocMultiset a, assocMultiset a) with | (ncons $x $m _, ncons #x $n _) -> (x, min m n)
lib/core/base.egi view
@@ -4,56 +4,60 @@ -- -- -eq :=+def eq := matcher | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as (something) with | $tgt -> [tgt] -bool := eq-char := eq-integer := eq-float := eq+def bool := eq+def char := eq+def integer := eq+def float := eq -- -- Utility -- -id := 1#%1+def id := 1#%1 -fst := 2#%1+def fst (x, y) := x+def snd (x, y) := y -snd := 2#%2+infixr expression 0 $ -apply f x := f x+def ($) f x := f x -compose f g := \x -> g (f x)+def compose f g := \x -> g (f x) -flip fn := \$x $y -> fn y x+def flip fn := \$x $y -> fn y x -eqAs a x y :=+def eqAs a x y := match x as a with | #y -> True | _ -> False +def curry f x y := f (x, y)+def uncurry f (x, y) := f x y+ -- -- Boolean -- -(&&) b1 b2 := if b1 then b2 else False-(||) b1 b2 := if b1 then True else b2+infixr expression 3 &&+infixr expression 2 || -not b :=- match b as bool with- | #True -> False- | #False -> True+def (&&) b1 b2 := if b1 then b2 else False+def (||) b1 b2 := if b1 then True else b2 +def not b := if b then False else True+ -- -- Unordered Pair -- -unorderedPair m :=+def unorderedPair m := matcher | ($, $) as (m, m) with | ($x, $y) -> [(x, y), (y, x)]
lib/core/collection.egi view
@@ -7,7 +7,7 @@ -- -- List ---list a :=+def list a := matcher | [] as () with | [] -> [()]@@ -18,6 +18,8 @@ | snoc $ $ as (a, list a) with | snoc $xs $x -> [(x, xs)] | _ -> []+ | _ ++ $ :: _ as (a) with+ | $tgt -> tgt | _ ++ $ as (list a) with | $tgt -> matchAll tgt as list a with@@ -41,7 +43,7 @@ | $ as (something) with | $tgt -> [tgt] -sortedList a :=+def sortedList a := matcher | [] as () with | [] -> [()]@@ -69,53 +71,43 @@ -- -- Accessors ---nth n xs :=+def nth n xs := match xs as list something with | loop $i (1, n - 1, _) (_ :: ...) ($x :: _) -> x -takeAndDrop n xs :=+def takeAndDrop n xs := match xs as list something with | loop $i (1, n, _) ($a_i :: ...) $rs -> (map (\i -> a_i) [1..n], rs) -take n xs :=+def take n xs := if n = 0 then [] else match xs as list something with | $x :: $xs -> x :: take (n - 1) xs | [] -> [] -drop n xs :=+def drop n xs := if n = 0 then xs else match xs as list something with | _ :: $xs -> drop (n - 1) xs | [] -> [] -takeWhile pred xs :=+def takeWhile pred xs := match xs as list something with | [] -> [] | $x :: $rs -> if pred x then x :: takeWhile pred rs else [] -takeWhileBy pred xs :=+def takeWhileBy pred xs := match xs as list something with | [] -> [] | $x :: $rs -> if pred x then x :: takeWhileBy pred rs else [x] -taileUntil pred xs :=- match xs as list something with- | [] -> []- | $x :: $rs -> if not (pred x) then x :: takeUntil pred rs else []--takeUntilBy pred xs :=- match xs as list something with- | [] -> []- | $x :: $rs -> if not (pred x) then x :: takeUntilBy pred rs else [x]--dropWhile pred xs :=+def dropWhile pred xs := match xs as list something with | [] -> [] | $x :: $rs -> if pred x then dropWhile pred rs else xs@@ -123,27 +115,27 @@ -- -- head, tail, uncons, unsnoc ---head xs :=+def head xs := match xs as list something with | $x :: _ -> x -tail xs :=+def tail xs := match xs as list something with | _ :: $ys -> ys -last xs :=+def last xs := match xs as list something with | snoc $x _ -> x -init xs :=+def init xs := match xs as list something with | snoc _ $ys -> ys -uncons xs :=+def uncons xs := match xs as list something with | $x :: $ys -> (x, ys) -unsnoc xs :=+def unsnoc xs := match xs as list something with | snoc $x $ys -> (ys, x) @@ -151,32 +143,32 @@ -- -- list functions ---isEmpty xs :=+def isEmpty xs := match xs as list something with | [] -> True | _ -> False -length xs := foldl 2#(%1 + 1) 0 xs+def length xs := foldl 2#(%1 + 1) 0 xs -map fn xs :=+def map fn xs := match xs as list something with | [] -> [] | $x :: $rs -> fn x :: map fn rs -map2 fn xs ys :=+def map2 fn xs ys := match (xs, ys) as (list something, list something) with | ([], _) -> [] | (_, []) -> [] | ($x :: $xs2, $y :: $ys2) -> fn x y :: map2 fn xs2 ys2 -map3 fn xs ys zs :=+def map3 fn xs ys zs := match (xs, ys, zs) as (list something, list something, list something) with | ([], _, _) -> [] | (_, [], _) -> [] | (_, _, []) -> [] | ($x :: $xs2, $y :: $ys2, $z :: $zs2) -> fn x y z :: map3 fn xs2 ys2 zs2 -map4 fn xs ys zs ws :=+def map4 fn xs ys zs ws := match (xs, ys, zs, ws) as (list something, list something, list something, list something) with | ([], _, _, _) -> []@@ -186,42 +178,42 @@ | ($x :: $xs2, $y :: $ys2, $z :: $zs2, $w :: $ws2) -> fn x y z w :: map4 fn xs2 ys2 zs2 ws2 -filter pred xs := foldr (\%y %ys -> if pred y then y :: ys else ys) [] xs+def filter pred xs := foldr (\%y %ys -> if pred y then y :: ys else ys) [] xs -partition pred xs := (filter pred xs, filter 1#(not (pred %1)) xs)+def partition pred xs := (filter pred xs, filter 1#(not (pred %1)) xs) -zip xs ys := map2 (\x y -> (x, y)) xs ys+def zip xs ys := map2 (\x y -> (x, y)) xs ys -zip3 xs ys zs := map3 (\x y z -> (x, y, z)) xs ys zs+def zip3 xs ys zs := map3 (\x y z -> (x, y, z)) xs ys zs -zip4 xs ys zs ws := map4 (\x y z w -> (x, y, z, w)) xs ys zs ws+def zip4 xs ys zs ws := map4 (\x y z w -> (x, y, z, w)) xs ys zs ws -lookup k ls :=+def lookup k ls := match ls as list (something, something) with | _ ++ (#k, $x) :: _ -> x -foldr fn %init %ls :=+def foldr fn %init %ls := match ls as list something with | [] -> init | $x :: $xs -> fn x (foldr fn init xs) -foldl fn %init %ls :=+def foldl fn %init %ls := match ls as list something with | [] -> init | $x :: $xs -> let z := fn init x in seq z (foldl fn z xs) -foldl1 fn %ls := foldl fn (head ls) (tail ls)+def foldl1 fn %ls := foldl fn (head ls) (tail ls) -reduce fn %ls := foldl fn (head ls) (tail ls)+def reduce fn %ls := foldl fn (head ls) (tail ls) -scanl fn %init %ls :=+def scanl fn %init %ls := init :: (match ls as list something with | [] -> [] | $x :: $xs -> scanl fn (fn init x) xs) -iterate fn %x :=+def iterate fn %x := let nx1 := fn x nx2 := fn nx1 nx3 := fn nx2@@ -229,7 +221,7 @@ nx5 := fn nx4 in x :: nx1 :: nx2 :: nx3 :: nx4 :: iterate fn nx5 -repeatedSquaring fn %x n :=+def repeatedSquaring fn %x n := match n as integer with | #1 -> x | ?isEven ->@@ -239,63 +231,63 @@ let y := repeatedSquaring fn x (quotient n 2) in fn (fn y y) x -append xs ys := xs ++ ys--concat xss := foldr (\%xs %rs -> xs ++ rs) [] xss+def concat xss := foldr (\%xs %rs -> xs ++ rs) [] xss -reverse xs :=+def reverse xs := match xs as list something with | [] -> [] | snoc $x $rs -> x :: reverse rs -intersperse sep ws :=+def intersperse sep ws := match ws as list something with | [] -> [] | $w :: $rs -> foldl (\s1 s2 -> s1 ++ [sep, s2]) [w] rs -intercalate := compose intersperse concat+def intercalate sep ws := concat (intersperse sep ws) -split sep ls :=+def split sep ls := match ls as list something with | $xs ++ #sep ++ $rs -> xs :: split sep rs | _ -> [ls] -splitAs a sep ls :=+def splitAs a sep ls := match ls as list a with | $xs ++ #sep ++ $rs -> xs :: splitAs a sep rs | _ -> [ls] -findCycle xs :=+def splitAt n ls := (take n ls, drop n ls)++def findCycle xs := head (matchAll xs as list something with | $ys ++ (_ :: _ & $cs) ++ #cs ++ _ -> (ys, cs)) -repeat %xs := xs ++ repeat xs+def repeat %xs := xs ++ repeat xs -repeat1 %x := x :: repeat1 x+def repeat1 %x := x :: repeat1 x -- -- Others ---all pred xs :=+def all pred xs := match xs as list something with | [] -> True | $x :: $rs -> if pred x then all pred rs else False -any pred xs :=+def any pred xs := match xs as list something with | [] -> False | $x :: $rs -> if pred x then True else any pred rs -from s :=+def from s := [s, s + 1, s + 2, s + 3, s + 4, s + 5, s + 6, s + 7, s + 8, s + 9, s + 10] ++ from (s + 11) -- Note. `between` is used in the definition of the list matcher.-between s e :=+def between s e := if s = e then [s] else if s < e then s :: between (s + 1) e else [] -L./ xs ys :=+def L./ xs ys := if length xs < length ys then ([], xs) else match (ys, xs) as (list mathExpr, list mathExpr) with@@ -304,14 +296,14 @@ (map2 (-) (take (length yrs) xrs)- (map 1#(%1 * (x / y)) yrs) ++ drop (length yrs) xrs)+ (map (* (x / y)) yrs) ++ drop (length yrs) xrs) ys in (x / y :: zs, rs) -- -- Multiset ---multiset a :=+def multiset a := matcher | [] as () with | [] -> [()]@@ -348,77 +340,77 @@ -- -- multiset operation ---deleteFirst %x xs :=+def deleteFirst %x xs := match xs as list something with | [] -> [] | #x :: $rs -> rs | $y :: $rs -> y :: deleteFirst x rs -deleteFirstAs a %x xs :=+def deleteFirstAs a %x xs := match xs as list a with | [] -> [] | #x :: $rs -> rs | $y :: $rs -> y :: deleteFirstAs a x rs -delete x xs :=+def delete x xs := match xs as list something with | [] -> [] | $hs ++ #x :: $ts -> hs ++ delete x ts | _ -> xs -deleteAs a x xs :=+def deleteAs a x xs := match xs as list a with | [] -> [] | $hs ++ #x :: $ts -> hs ++ deleteAs a x ts | _ -> xs -difference xs ys :=+def difference xs ys := match ys as list something with | [] -> xs | $y :: $rs -> difference (deleteFirst y xs) rs -differenceAs a xs ys :=+def differenceAs a xs ys := match ys as list a with | [] -> xs | $y :: $rs -> differenceAs a (deleteFirstAs a y xs) rs -include xs ys :=+def include xs ys := match ys as list something with | [] -> True | $y :: $rs -> if member y xs then include (deleteFirst y xs) rs else False -includeAs a xs ys :=+def includeAs a xs ys := match ys as list a with | [] -> True | $y :: $rs -> if memberAs a y xs then includeAs a (deleteFirst y xs) rs else False -union xs ys :=+def union xs ys := xs ++ (matchAll (ys, xs) as (multiset something, multiset something) with | ($y :: _, !(#y :: _)) -> y) -unionAs a xs ys :=+def unionAs a xs ys := xs ++ (matchAll (ys, xs) as (multiset a, multiset a) with | ($y :: _, !(#y :: _)) -> y) -intersect xs ys :=+def intersect xs ys := matchAll (xs, ys) as (multiset something, multiset something) with | ($x :: _, #x :: _) -> x -intersectAs a xs ys :=+def intersectAs a xs ys := matchAll (xs, ys) as (multiset a, multiset a) with | ($x :: _, #x :: _) -> x -- -- Simple predicate ---member x ys :=+def member x ys := match ys as list something with | _ ++ #x :: _ -> True | _ -> False -memberAs a x ys :=+def memberAs a x ys := match ys as list a with | _ ++ #x :: _ -> True | _ -> False@@ -426,41 +418,29 @@ -- -- Counting ---count x xs :=- foldl- (\match as (something, something) with- | ($r, #x) -> r + 1- | ($r, $y) -> r)- 0- xs+def count x xs :=+ foldl (\acc y -> if x = y then acc + 1 else acc) 0 xs -countAs a x xs :=- foldl- (\match as (a, a) with- | ($r, #x) -> r + 1- | ($r, $y) -> r)- 0- xs+def countAs a x xs :=+ foldl (\acc y -> if eqAs a x y then acc + 1 else acc) 0 xs -frequency xs :=- let us := unique xs- in map (\u -> (u, count u xs)) us+def frequency xs :=+ map (\u -> (u, count u xs)) (unique xs) -frequencyAs a xs :=- let us := uniqueAs a xs- in map (\u -> (u, countAs a u xs)) us+def frequencyAs a xs :=+ map (\u -> (u, countAs a u xs)) (uniqueAs a xs) -- -- Index ---elemIndices x xs :=+def elemIndices x xs := matchAll xs as list something with | $hs ++ #x :: _ -> 1 + length hs -- -- Set ---set a :=+def set a := matcher | [] as () with | [] -> [()]@@ -493,20 +473,20 @@ -- -- set operation ---add x xs := if member x xs then xs else xs ++ [x]+def add x xs := if member x xs then xs else xs ++ [x] -addAs a x xs := if memberAs a x xs then xs else xs ++ [x]+def addAs a x xs := if memberAs a x xs then xs else xs ++ [x] -fastUnique xs :=+def fastUnique xs := matchAll sort xs as list something with | _ ++ $x :: !(#x :: _) -> x -unique xs :=+def unique xs := reverse (matchAll reverse xs as list something with | _ ++ $x :: !(_ ++ #x :: _) -> x) -uniqueAs a xs := loopFn xs []+def uniqueAs a xs := loopFn xs [] where loopFn xs ys := match (xs, ys) as (list a, multiset a) with
lib/core/io.egi view
@@ -7,22 +7,22 @@ -- -- IO ---print x :=+def print x := do write x write "\n" flush () -printToPort port x :=+def printToPort port x := do writeToPort port x writeToPort port "\n" -display x :=+def display x := do write x flush () -displayToPort port x := do writeToPort port x+def displayToPort port x := do writeToPort port x -eachLine proc :=+def eachLine proc := do let eof := isEof () if eof then return ()@@ -30,7 +30,7 @@ proc line eachLine proc -eachLineFromPort port proc :=+def eachLineFromPort port proc := do let eof := isEofPort port if eof then return ()@@ -38,7 +38,7 @@ proc line eachLineFromPort port proc -eachFile files proc :=+def eachFile files proc := match files as list string with | [] -> return () | $file :: $rest ->@@ -50,7 +50,7 @@ -- -- Collection ---each proc xs :=+def each proc xs := match xs as list something with | [] -> do return () | $x :: $rs ->@@ -60,11 +60,11 @@ -- -- Debug ---debug %expr :=- io do print (show expr)- return expr+def debug %expr :=+ io $ do print (show expr)+ return expr -debug2 %msg %expr :=- io do display msg- print (show expr)- return expr+def debug2 %msg %expr :=+ io $ do display msg+ print (show expr)+ return expr
lib/core/maybe.egi view
@@ -4,7 +4,7 @@ -- -- -maybe a :=+def maybe a := matcher | nothing as () with | Nothing -> [()]
lib/core/number.egi view
@@ -7,7 +7,7 @@ -- -- Natural Numbers ---nat :=+def nat := matcher | o as () with | 0 -> [()]@@ -22,7 +22,7 @@ | $ as (something) with | $tgt -> [tgt] -nats :=+def nats := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,@@ -35,30 +35,27 @@ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100] ++ map (+ 100) nats -nats0 := 0 :: nats--odds := 1 :: map (+ 2) odds+def nats0 := 0 :: nats -evens := 2 :: map (+ 2) evens+def odds := 1 :: map (+ 2) odds+def evens := 2 :: map (+ 2) evens -fibs := [1, 1] ++ map2 (+) fibs (tail fibs)+def fibs := [1, 1] ++ map2 (+) fibs (tail fibs) -isPrime :=- \match as integer with- | ?(< 2) -> False- | $n -> n = findFactor n+def isPrime n :=+ if n < 2 then False else n = findFactor n -primes := 2 :: filter isPrime (drop 2 nats)+def primes := 2 :: filter isPrime (drop 2 nats) -divisor n d := 0 = n % d+def divisor n d := 0 = n % d -findFactor :=+def findFactor := memoizedLambda n -> match takeWhile (<= floor (sqrt (itof n))) primes as list integer with- | _ ++ (?1#(divisor n %1) & $x) :: _ -> x+ | _ ++ (?(divisor n) & $x) :: _ -> x | _ -> n -primeFactorization :=+def primeFactorization := \match as integer with | #1 -> [] | ?(< 0) & $n -> (-1) :: primeFactorization (neg n)@@ -66,19 +63,18 @@ let p := findFactor n in p :: primeFactorization (quotient n p) -pF := primeFactorization--isEven n := 0 = modulo n 2+def pF := primeFactorization -isOdd n := 1 = modulo n 2+def isEven n := 0 = modulo n 2+def isOdd n := 1 = modulo n 2 -fact n := foldl (*) 1 [1..n]+def fact n := foldl (*) 1 [1..n] -perm n r := foldl (*) 1 [(n - (r - 1))..n]+def perm n r := foldl (*) 1 [(n - (r - 1))..n] -comb n r := perm n r / fact r+def comb n r := perm n r / fact r -nAdic n x :=+def nAdic n x := if x = 0 then [] else let q := quotient x n@@ -88,7 +84,7 @@ -- -- Integers ---mod m :=+def mod m := matcher | #$n as () with | $tgt -> if modulo tgt m = modulo n m then [()] else []@@ -98,24 +94,24 @@ -- -- Floats ---exp2 x y := exp (log x * y)+def exp2 x y := exp (log x * y) -- -- Decimal Fractions ---rtodHelper m n :=+def rtodHelper m n := let q := quotient (m * 10) n r := m * 10 % n in (q, r) :: rtodHelper r n -rtod x :=+def rtod x := let m := numerator x n := denominator x q := quotient m n r := m % n in (q, map fst (rtodHelper r n)) -rtod' x :=+def rtod' x := let m := numerator x n := denominator x q := quotient m n@@ -123,11 +119,11 @@ (s, c) := findCycle (rtodHelper r n) in (q, map fst s, map fst c) -showDecimal c x :=- match 2#(%1, take c %2) (rtod x) as (integer, list integer) with+def showDecimal c x :=+ match (\(x, y) -> (x, take c y)) (rtod x) as (integer, list integer) with | ($q, $sc) -> foldl S.append (S.append (show q) ".") (map show sc) -showDecimal' x :=+def showDecimal' x := match rtod' x as (integer, list integer, list integer) with | ($q, $s, $c) -> foldl@@ -138,14 +134,14 @@ -- -- Continued Fraction ---regularContinuedFraction n xs := n + foldr (\a r -> 1 / (a + r)) 0 xs+def regularContinuedFraction n xs := n + foldr (\a r -> 1 / (a + r)) 0 xs -continuedFraction n xs ys :=+def continuedFraction n xs ys := match (xs, ys) as (list integer, list integer) with | ($x :: $xs, $y :: $ys) -> n + y / continuedFraction x xs ys | ([], []) -> n -regularContinuedFractionOfSqrtHelper m a b :=+def regularContinuedFractionOfSqrtHelper m a b := let n := floor (f.+ (rtof a) (f.* (rtof b) (sqrt (rtof m)))) x := m - power n 2 in if x = 0@@ -156,15 +152,15 @@ ((a - n) / y) (neg (b / y)) -regularContinuedFractionOfSqrt m :=+def regularContinuedFractionOfSqrt m := let n := floor (sqrt (rtof m)) x := m - power n 2 in if x = 0 then (n, []) else ( n- , map 3#%3 (regularContinuedFractionOfSqrtHelper m (n / x) (1 / x)) )+ , map (\(_, _, z) -> z) (regularContinuedFractionOfSqrtHelper m (n / x) (1 / x)) ) -regularContinuedFractionOfSqrt' m :=+def regularContinuedFractionOfSqrt' m := let n := floor (sqrt (rtof m)) x := m - power n 2 in if x = 0@@ -174,6 +170,6 @@ m (n / x) (1 / x))- in (n, map 3#%3 s, map 3#%3 c)+ in (n, map (\(_, _, x) -> x) s, map (\(_, _, x) -> x) c) -pi := f.pi+def pi := f.pi
lib/core/order.egi view
@@ -4,18 +4,18 @@ -- -- -ordering :=+def ordering := algebraicDataMatcher | less | equal | greater -compare m n :=+def compare m n := if isCollection m then compareC m n else if m < n then Less else if m = n then Equal else Greater -compareC c1 c2 :=+def compareC c1 c2 := match (c1, c2) as (list something, list something) with | ([], []) -> Equal | ([], _) -> Less@@ -23,21 +23,18 @@ | ($x :: $xs, #x :: $ys) -> compareC xs ys | ($x :: _, $y :: _) -> compare x y -min $x $y := if x < y then x else y--max $x $y := if x > y then x else y--min/fn f $xs := foldl1 2#(if f %1 %2 = Less then %1 else %2) xs--max/fn f $xs := foldl1 2#(if f %1 %2 = Greater then %1 else %2) xs+def min $x $y := if x < y then x else y+def max $x $y := if x > y then x else y -minimum $xs := foldl1 min xs+def min/fn f $xs := foldl1 2#(if f %1 %2 = Less then %1 else %2) xs+def max/fn f $xs := foldl1 2#(if f %1 %2 = Greater then %1 else %2) xs -maximum $xs := foldl1 max xs+def minimum $xs := foldl1 min xs+def maximum $xs := foldl1 max xs -splitByOrdering := 2#(splitByOrdering/fn compare %1 %2)+def splitByOrdering := splitByOrdering/fn compare -splitByOrdering/fn f p xs :=+def splitByOrdering/fn f p xs := match xs as list something with | [] -> ([], [], []) | $x :: $rs ->@@ -47,9 +44,9 @@ | equal -> (ys1, x :: ys2, ys3) | greater -> (ys1, ys2, x :: ys3) -sort := 1#(sort/fn compare %1)+def sort := sort/fn compare -sort/fn f xs :=+def sort/fn f xs := match xs as list something with | [] -> [] | $x :: [] -> [x]@@ -59,25 +56,25 @@ (ys1, ys2, ys3) := splitByOrdering/fn f p xs in sort/fn f ys1 ++ ys2 ++ sort/fn f ys3 -sortStrings xs :=+def sortStrings xs := sort/fn 2#(compareC (map ctoi (unpack %1)) (map ctoi (unpack %2))) xs -merge xs ys :=+def merge xs ys := match (xs, ys) as (list something, list something) with | ([], _) -> ys | (_, []) -> xs | ($x :: $txs, ?(>= x) :: _) -> x :: merge txs ys | (_, $y :: $tys) -> y :: merge xs tys -merge/fn f xs ys :=+def merge/fn f xs ys := match (xs, ys) as (list something, list something) with | ([], _) -> ys | (_, []) -> xs | ($x :: $txs, ?1#(f %1 x = Greater) :: _) -> x :: merge txs ys | (_, $y :: $tys) -> y :: merge xs tys -minimize f xs :=+def minimize f xs := foldl1 2#(if compare (f %1) (f %2) = Less then %1 else %2) xs -maximize f xs :=+def maximize f xs := foldl1 2#(if compare (f %1) (f %2) = Greater then %1 else %2) xs
lib/core/random.egi view
@@ -4,11 +4,11 @@ -- -- -rands s e := pureRand s e :: rands s e+def rands s e := pureRand s e :: rands s e -pureRand s e := io rand s e+def pureRand s e := io (rand s e) -randomize xs :=+def randomize xs := let randomize' xs n := if n = 0 then []@@ -17,9 +17,9 @@ in x :: randomize' (deleteFirst x xs) (n - 1) in randomize' xs (length xs) -R.between s e := randomize [s..e]+def R.between s e := randomize [s..e] -R.multiset a :=+def R.multiset a := matcher | [] as () with | [] -> [()]@@ -37,24 +37,24 @@ | $ as (something) with | $tgt -> [tgt] -R.uncons xs :=+def R.uncons xs := head (matchAll xs as R.multiset something with | $x :: $rs -> (x, rs)) -R.head xs :=+def R.head xs := head (matchAll xs as R.multiset something with | $x :: _ -> x) -R.tail xs :=+def R.tail xs := head (matchAll xs as R.multiset something with | _ :: $rs -> rs) -sample := R.head+def sample := R.head -R.set a :=+def R.set a := matcher | [] as () with | [] -> [()]@@ -71,6 +71,6 @@ | $ as (something) with | $tgt -> [tgt] -f.rands s e := f.pureRand s e :: f.rands s e+def f.rands s e := f.pureRand s e :: f.rands s e -f.pureRand s e := io f.rand s e+def f.pureRand s e := io (f.rand s e)
lib/core/shell.egi view
@@ -1,53 +1,58 @@-SH.genInput sopts copts :=- if io isEof ()+def SH.genInput sopts copts :=+ if io $ isEof () then []- else let x := io TSV.readLine sopts copts+ else let line := io $ readLine ()+ x := TSV.parseLine sopts copts line in seq x (x :: SH.genInput sopts copts) -TSV.readLine sopts copts :=- do let line := readLine ()- let fs := S.split "\t" line- in let fnS := \match as (list (list integer), list string) with- | ([], $fs) -> fs- | ( [$m] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ $ts ) ->- fnS- opts'- (hs ++ map (\t -> S.concat ["\"", t, "\""]) ts)- | ( [$m, #m] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ $mf :: $ts ) ->- fnS opts' (hs ++ S.concat ["\"", mf, "\""] :: ts)- | ( [$m, $n] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++- ($ms & ?(\ms -> n - m + 1 = length ms)) ++ $ts ) ->- fnS- opts'- (hs ++ map (\m -> S.concat ["\"", m, "\""]) ms ++ ts)- | ([$m, _] :: $opts', _) -> fnS ([m] :: opts') fs- | (_, _) -> fs- fnC := \match as (list (list integer), list string) with- | ([], $fs) -> fs- | ( [$m] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ [$mf] ) ->- fnC opts' (hs ++ [S.concat ["{", mf, "}"]])- | ( [$m] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ $mf ::- snoc $tf $ms ) ->- fnC- opts'- (hs ++ S.append "{" mf :: ms ++ [S.append tf "}"])- | ( [$m, #m] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ $mf :: $ts ) ->- fnC opts' (hs ++ S.concat ["{", mf, "}"] :: ts)- | ( [$m, $n] :: $opts'- , ($hs & ?(\hs -> m - 1 = length hs)) ++ $mf ::- ($ms & ?(\ms -> n - m - 1 = length ms)) ++ $nf ::- $ts ) ->- fnC- opts'- (hs ++ S.append "{" mf :: ms ++ S.append nf "}" :: ts)- | ([$m, _] :: $opts', _) -> fnC ([m] :: opts') fs- | (_, _) -> fs- in return (readTsv (S.intercalate "\t" (fnC copts (fnS sopts fs))))+def TSV.map fn showFn := do+ let eof := isEof ()+ if eof+ then return ()+ else do let line := readLine ()+ print (showFn (fn (readTsv line)))+ TSV.map fn showFn -TSV.show := showTsv+def TSV.filter fn := do+ let eof := isEof ()+ if eof+ then return ()+ else do let line := readLine ()+ if fn (readTsv line) then print line else return ()+ TSV.filter fn++def TSV.parseLine sopts copts line :=+ readTsv (S.intercalate "\t" (fnC copts (fnS sopts (S.split "\t" line))))+ where+ fnS sopts xs :=+ match sopts as list (list integer) with+ | [$m] :: $opts' ->+ let (hs, ts) := splitAt (m - 1) xs+ in fnS opts' (hs ++ map (\t -> S.concat ["\"", t, "\""]) ts)+ | [$m, #m] :: $opts' ->+ let (hs, ts') := splitAt (m - 1) xs+ (mf, ts) := uncons ts'+ in fnS opts' (hs ++ S.concat ["\"", mf, "\""] :: ts)+ | [$m, $n] :: $opts' ->+ let (hs, ts') := splitAt (m - 1) xs+ (ms, ts) := splitAt (n - m + 1) ts'+ in fnS opts' (hs ++ map (\m -> S.concat ["\"", m, "\""]) ms ++ ts)+ | [$m, _] :: $opts' -> fnS ([m] :: opts') xs+ | _ -> xs+ fnC copts xs :=+ match copts as list (list integer) with+ | [$m] :: $opts' ->+ let (hs, ts) := splitAt (m - 1) xs+ in fnC opts' (hs ++ [S.concat ["[", S.intercalate ", " ts, "]"]])+ | [$m, #m] :: $opts' ->+ let (hs, ts') := splitAt (m - 1) xs+ (mf, ts) := uncons ts'+ in fnC opts' (hs ++ S.concat ["[", mf, "]"] :: ts)+ | [$m, $n] :: $opts' ->+ let (hs, ts') := splitAt (m - 1) xs+ (ms, ts) := splitAt (n - m + 1) ts'+ in fnC opts' (hs ++ S.concat ["[", S.intercalate ", " ms, "]"] :: ts)+ | [$m, _] :: $opts' -> fnC ([m] :: opts') xs+ | _ -> xs++def TSV.show := showTsv
+ lib/core/sort.egi view
@@ -0,0 +1,44 @@+--+-- Sort+--++-- input: collection of collection of integers+-- output: a tuple of type (int, collection of integers)+-- where the first element is 1 if the number of swap needed to sort the input+-- is even, and -1 otherwise+-- and the second element is the sorted collection represented as a 1-d tensor+-- (vector)+def sortWithSign xs :=+ match xs as list something with+ -- Optimization for the case where the length is less than 3+ | [] -> (1, xs)+ | [$x] -> (1, x)+ | [$x, $y] ->+ if compare x y = Greater then (-1, y ++ x) else (1, x ++ y)+ | _ -> io $+ do let t := return (colToTensor xs)+ let n := return (length xs)+ let sgn := sort' 1 2 n t 1+ let xs' := return (map (\i -> io $ readIORef t_i) [1..n])+ return (sgn, concat xs')+ where+ colToTensor xs :=+ generateTensor (\n -> io $ do let t := newIORef ()+ writeIORef t (nth n xs)+ return t) [length xs]++ sort' i j n ts sgn :=+ if i = n+ then return sgn+ else do let x := readIORef ts_i+ let y := readIORef ts_j+ if compare x y = Greater then swap ts i j else return ()+ let swapped := return (if compare x y = Greater then -1 else 1)+ if j = n then sort' (i + 1) (i + 2) n ts (sgn * swapped)+ else sort' i (j + 1) n ts (sgn * swapped)++ swap ts i j := do+ let tmpi := readIORef ts_i+ let tmpj := readIORef ts_j+ writeIORef ts_i tmpj+ writeIORef ts_j tmpi
lib/core/string.egi view
@@ -4,7 +4,7 @@ -- -- -string :=+def string := matcher | regexCg #$regexpr $ $ $ as (string, list string, string) with | $tgt -> regexCg regexpr tgt@@ -38,47 +38,45 @@ -- -- String as collection ---S.isEmpty xs := xs = ""+def S.isEmpty xs := xs = "" -S.cons x xs := appendString (pack [x]) xs+def S.cons x xs := appendString (pack [x]) xs -S.head xs :=+def S.head xs := match xs as string with | $x :: _ -> x -S.tail xs :=+def S.tail xs := match xs as string with | _ :: $r -> r -S.last str :=+def S.last str := match str as string with- | _ ++ $c :: [] -> c--S.map f xs := pack (map f (unpack xs))--S.length xs := lengthString xs+ | _ ++ [$c] -> c -S.split sep ls := splitString sep ls+def S.map f xs := pack (map f (unpack xs)) -S.append xs ys := appendString xs ys+def S.length := lengthString+def S.split := splitString+def S.append := appendString -S.concat xss := foldr (\xs rs -> S.append xs rs) "" xss+def S.concat xss := foldr (\xs rs -> S.append xs rs) "" xss -S.intercalate := compose intersperse S.concat+def S.intercalate sep ss := S.concat (intersperse sep ss) -S.replace before after str := S.intercalate after (S.split before str)+def S.replace before after str := S.intercalate after (S.split before str) -- -- Alphabet ---C.between c1 c2 := map itoc (between (ctoi c1) (ctoi c2))+def C.between c1 c2 := map itoc (between (ctoi c1) (ctoi c2)) -C.isBetween c1 c2 c := ctoi c >= ctoi c1 && ctoi c <= ctoi c2+def C.isBetween c1 c2 c := ctoi c >= ctoi c1 && ctoi c <= ctoi c2 -isAlphabet c := C.isBetween 'a' 'z' c || C.isBetween 'A' 'Z' c+def isAlphabet c := C.isBetween 'a' 'z' c || C.isBetween 'A' 'Z' c -isAlphabetString s := all isAlphabet (unpack s)+def isAlphabetString s := all isAlphabet (unpack s) -upperCase c := if C.isBetween 'a' 'z' c then itoc (ctoi c - 32) else c+def upperCase c := if C.isBetween 'a' 'z' c then itoc (ctoi c - 32) else c -lowerCase c := if C.isBetween 'A' 'Z' c then itoc (ctoi c + 32) else c+def lowerCase c := if C.isBetween 'A' 'Z' c then itoc (ctoi c + 32) else c
lib/math/algebra/equations.egi view
@@ -4,49 +4,49 @@ -- -- -solve1 f expr x := inverse expr f x--solve eqs := solve' eqs []+def solve eqs := solve' eqs []+ where+ solve1 f expr x := inverse expr f x -solve' eqs rets :=- match eqs as list (mathExpr, mathExpr, symbolExpr) with- | [] -> rets- | ($f, $expr, $x) :: $rs ->- solve'- rs- (rets ++ [(x, solve1 (substitute rets f) (substitute rets expr) x)])+ solve' eqs rets :=+ match eqs as list (mathExpr, mathExpr, symbolExpr) with+ | [] -> rets+ | ($f, $expr, $x) :: $rs ->+ solve'+ rs+ (rets ++ [(x, solve1 (substitute rets f) (substitute rets expr) x)]) -- -- Quadratic Equations ---quadraticFormula := qF+def quadraticFormula := qF -qF f x :=+def qF f x := match coefficients f x as list mathExpr with | $a_0 :: $a_1 :: $a_2 :: [] -> qF' a_2 a_1 a_0 -qF' a b c :=+def qF' a b c := ( ((- b) + sqrt (b ^ 2 - 4 * a * c)) / 2 * a , ((- b) - sqrt (b ^ 2 - 4 * a * c)) / 2 * a ) -- -- Cubic Equations ---cubicFormula := cF+def cubicFormula := cF -cF f x :=+def cF f x := match coefficients f x as list mathExpr with | $a_0 :: $a_1 :: $a_2 :: $a_3 :: [] -> cF' a_3 a_2 a_1 a_0 -cF' a b c d :=+def cF' a b c d := match (a, b, c, d) as (mathExpr, mathExpr, mathExpr, mathExpr) with | (#1, #0, $p, $q) ->- let (s1, s2) := 2#(rt 3 %1, rt 3 %2) (qF' 1 (27 * q) ((-27) * p ^ 3))+ let (s1, s2) := (\(x, y) -> (rt 3 x, rt 3 y)) (qF' 1 (27 * q) ((-27) * p ^ 3)) in ( (s1 + s2) / 3 -- r1 , (w ^ 2 * s1 + w * s2) / 3 -- r2 , (w * s1 + w ^ 2 * s2) / 3) -- r3 | (#1, _, _, _) ->- 3#(%1 - b / 3, %2 - b / 3, %3 - b / 3)- (withSymbols [x, y]- cF (substitute [(x, y - b / 3)] (x ^ 3 + b * x ^ 2 + c * x + d)) y)+ let (s1, s2, s3) := withSymbols [x, y]+ cF (substitute [(x, y - b / 3)] (x ^ 3 + b * x ^ 2 + c * x + d)) y+ in (s1 - b / 3, s2 - b / 3, s3 - b / 3) | (_, _, _, _) -> cF' 1 (b / a) (c / a) (d / a)
lib/math/algebra/inverse.egi view
@@ -2,7 +2,7 @@ -- Inverse -- -inverse t f x :=+def inverse t f x := match f as mathExpr with | ?isSimpleTerm -> match f as symbolExpr with
lib/math/algebra/matrix.egi view
@@ -2,15 +2,15 @@ -- Matrices -- -M.* %s %t := withSymbols [i, j, k] s~i~j . t_j-M.*' %s %t := withSymbols [i, j, k] s~i~j .' t_j+def M.* %s %t := withSymbols [i, j, k] s~i~j . t_j+def M.*' %s %t := withSymbols [i, j, k] s~i~j .' t_j -M.power %t n := foldl M.* t (take (n - 1) (repeat1 t))+def M.power %t n := foldl M.* t (take (n - 1) (repeat1 t)) --M.power %m n := repeatedSquaring M.* m n -M.comm %m1 %m2 := withSymbols [i, j, k] m1~i~j . m2_j_k - m2~i~j . m1_j_k+def M.comm %m1 %m2 := withSymbols [i, j, k] m1~i~j . m2_j_k - m2~i~j . m1_j_k -M.inverse %m :=+def M.inverse %m := let d := M.det m in generateTensor 2#(match m as matrix with@@ -20,9 +20,9 @@ else - (M.det (M.join A B C D) / d)) (tensorShape m) -trace %t := withSymbols [i] sum (contract t~i_i)+def trace %t := withSymbols [i] sum (contract t~i_i) -matrix :=+def matrix := matcher | quadCons $ $ $ $ as (mathExpr, matrix, matrix, matrix) with | $tgt ->@@ -45,7 +45,7 @@ | $ as (something) with | $tgt -> [tgt] -M.join %A %B %C %D :=+def M.join %A %B %C %D := let ashape := tensorShape A a1 := nth 1 ashape a2 := nth 2 ashape@@ -73,16 +73,16 @@ -- -- Determinant ---evenAndOddPermutations n :=+def evenAndOddPermutations n := let (es, os) := evenAndOddPermutations' n in (map 1#(\i -> nth i %1) es, map 1#(\i -> nth i %1) os) -evenAndOddPermutations0 n :=+def evenAndOddPermutations0 n := let (es, os) := evenAndOddPermutations' n in ( map 1#(\i -> nth (i + 1) (map 1#(%1 - 1) %1)) es , map 1#(\i -> nth (i + 1) (map 1#(%1 - 1) %1)) os ) -evenAndOddPermutations' n :=+def evenAndOddPermutations' n := match n as integer with | #1 -> ([[1]], []) | #2 -> ([[1, 2]], [[2, 1]])@@ -92,47 +92,42 @@ os' := map (++ [n]) os in ( es' ++ concat (map- (\i -> map 1#(permutate i n %1) os')+ (\i -> map (permutate i n) os') (between 1 (n - 1))) , os' ++ concat (map- (\i -> map 1#(permutate i n %1) es')+ (\i -> map (permutate i n) es') (between 1 (n - 1))) ) -permutate x y xs :=+def permutate x y xs := match xs as list eq with | $hs ++ #x :: $ms ++ #y :: $ts -> hs ++ y :: ms ++ x :: ts | $hs ++ #y :: $ms ++ #x :: $ts -> hs ++ x :: ms ++ y :: ts -M.determinant %m :=+def M.determinant %m := match tensorShape m as list integer with- | #0 :: #0 :: [] -> 1- | $n :: #n :: [] ->+ | [#0, #0] -> 1+ | [$n, #n] -> let (es, os) := evenAndOddPermutations' n- in sum- (map- (\e -> product (map2 (\i j -> m_i_j) (between 1 n) e))- es) - sum- (map- (\o -> product (map2 (\i j -> m_i_j) (between 1 n) o))- os)+ in sum (map (\e -> product (map2 (\i j -> m_i_j) (between 1 n) e)) es) -+ sum (map (\o -> product (map2 (\i j -> m_i_j) (between 1 n) o)) os) | _ -> undefined -M.det := M.determinant+def M.det := M.determinant -- -- Eigenvalues and eigenvectors ---M.eigenvalues %m :=+def M.eigenvalues %m := match tensorShape m as list integer with- | #2 :: #2 :: [] ->+ | [#2, #2] -> let (e1, e2) := qF (M.det (T.- m (scalarToTensor x [2, 2]))) x in [e1, e2] | _ -> undefined -M.eigenvectors %m :=+def M.eigenvectors %m := match tensorShape m as list integer with- | #2 :: #2 :: [] ->+ | [#2, #2] -> let (e1, e2) := qF (M.det (T.- m (scalarToTensor x [2, 2]))) x in [ (e1, clearIndex (T.- m (scalarToTensor e1 [2, 2]))_i_1) , (e2, clearIndex (T.- m (scalarToTensor e2 [2, 2]))_i_1) ]@@ -141,9 +136,9 @@ -- -- LU decomposition ---M.LU %x :=+def M.LU %x := match tensorShape x as list integer with- | #2 :: #2 :: [] ->+ | [#2, #2] -> let L := generateTensor 2#(match compare %1 %2 as ordering with | less -> 0@@ -162,7 +157,7 @@ , (m_2_1, x_2_1, b_2_1) , (m_2_2, x_2_2, c_2_2) ] in (substitute ret L, substitute ret U)- | #3 :: #3 :: [] ->+ | [#3, #3] -> let L := generateTensor 2#(match compare %1 %2 as ordering with | less -> 0@@ -191,7 +186,7 @@ -- -- Utility ---generateMatrixFromQuadraticExpr f xs :=+def generateMatrixFromQuadraticExpr f xs := generateTensor 2#(coefficient2 f (nth %1 xs) (nth %2 xs)) [length xs, length xs]
lib/math/algebra/root.egi view
@@ -7,12 +7,12 @@ -- -- Root ---rt n x :=+def rt n x := if isInteger n then match x as mathExpr with | #0 -> 0 | ?isMonomial -> rtMonomial n x- | (poly $xs) / (poly $ys) ->+ | poly $xs / poly $ys -> let xd := reduce gcd xs yd := reduce gcd ys d := rtMonomial n (xd / yd)@@ -20,63 +20,59 @@ | _ -> rt'' n x else rt'' n x -rtMonomial n x :=+def rtMonomial n x := rtTerm n (numerator x * denominator x ^ (n - 1)) / denominator x -rtTerm n x :=+def rtTerm n x := match x as termExpr with | term $a _ ->- if a < 0 then rtm1 n *' rtPositiveTerm n (- x) else rtPositiveTerm n x+ let rtm1 n := match n as integer with+ | #1 -> -1+ | #2 -> i+ | ?isOdd -> -1+ | _ -> undefined+ in if a < 0 then rtm1 n *' rtPositiveTerm n (- x) else rtPositiveTerm n x -rtPositiveTerm n x :=+def rtPositiveTerm n x := match (n, x) as (mathExpr, mathExpr) with | (#3, $a * #i * $r) -> (- i) * rt 3 (a *' r) | (_, $a * #sqrt $b * $r) -> rt (n * 2) (a ^' 2 *' b) *' rt n r | (_, $a * #rt $n' $b * $r) -> rt (n * n') (a ^' n' *' b) *' rt n r | (_, _) -> rtPositiveTerm1 n x--rtPositiveTerm1 n x :=- let f xs :=- match xs as assocMultiset mathExpr with- | [] -> (1, 1)- | ncons $p $k $rs ->- let (a, b) := f rs- in (p ^' quotient k n *' a, p ^' (k % n) *' b)- g n x :=- let d := match x as termExpr with- | term $m $xs ->- gcd n (reduce gcd (map 2#%2 (toAssoc (pF m) ++ xs)))- in rt'' (n / d) (rt d x)- in match x as termExpr with- | term $m $xs ->- match f (toAssoc (pF (abs m)) ++ xs) as (integer, integer) with- | ($a, #1) -> a- | ($a, $b) -> a *' g n b+ where+ rtPositiveTerm1 n x :=+ let f xs :=+ match xs as assocMultiset mathExpr with+ | [] -> (1, 1)+ | ncons $p $k $rs ->+ let (a, b) := f rs+ in (p ^' quotient k n *' a, p ^' (k % n) *' b)+ g n x :=+ let d := match x as termExpr with+ | term $m $xs ->+ gcd n (reduce gcd (map snd (toAssoc (pF m) ++ xs)))+ in rt'' (n / d) (rt d x)+ in match x as termExpr with+ | term $m $xs ->+ match f (toAssoc (pF (abs m)) ++ xs) as (integer, integer) with+ | ($a, #1) -> a+ | ($a, $b) -> a *' g n b -rt'' n x :=+def rt'' n x := match (n, x) as (integer, integer) with | (#2, _) -> `sqrt x | (_, _) -> `rt n x -rtm1 n :=- match n as integer with- | #1 -> -1- | #2 -> i- | ?isOdd -> -1- | _ -> undefined--sqrt x :=+def sqrt x := if isScalar x then let m := numerator x n := denominator x in rt 2 (m * n) / n else b.sqrt x -rtOfUnity := rtu--rtu n := rtu' n+def rtOfUnity := rtu -rtu' n :=+def rtu n := if isInteger n then match n as integer with | #1 -> 1
lib/math/algebra/tensor.egi view
@@ -4,14 +4,17 @@ -- -- -tensorOrder %A := length (tensorShape A)+infixl expression 7 .+infixl expression 7 .' -unitTensor ns := generateTensor kroneckerDelta ns+def tensorOrder %A := length (tensorShape A) -scalarToTensor x ns := x * unitTensor ns+def unitTensor ns := generateTensor kroneckerDelta ns -zeroTensor ns := generateTensor (cambda xs -> 0) ns+def scalarToTensor x ns := x * unitTensor ns -(.') %t1 %t2 := sum' (contract (t1 *' t2))+def zeroTensor ns := generateTensor (\xs -> 0) ns -(.) %t1 %t2 := sum (contract (t1 * t2))+def (.') %t1 %t2 := sum' (contract (t1 *' t2))++def (.) %t1 %t2 := sum (contract (t1 * t2))
lib/math/algebra/vector.egi view
@@ -2,15 +2,15 @@ -- Vectors -- -dotProduct %v1 %v2 := withSymbols [i] v1~i . v2_i+def dotProduct %v1 %v2 := withSymbols [i] v1~i . v2_i -V.* := dotProduct+def V.* := dotProduct -crossProduct/fn fn %a %b :=+def crossProduct/fn fn %a %b := [|fn a_2 b_3 - fn a_3 b_2, fn a_3 b_1 - fn a_1 b_3, fn a_1 b_2 - fn a_2 b_1|] -crossProduct %a %b := crossProduct/fn (*) a b+def crossProduct %a %b := crossProduct/fn (*) a b -div %A %xs := trace (∇ A xs)+def div %A %xs := trace (∇ A xs) -rot %A %xs := crossProduct/fn ∂/∂ A xs+def rot %A %xs := crossProduct/fn ∂/∂ A xs
lib/math/analysis/derivative.egi view
@@ -4,7 +4,7 @@ -- -- -∂/∂ $f *x :=+def ∂/∂ $f *$x := match f as mathExpr with -- symbol | #x -> 1@@ -21,7 +21,7 @@ | #`sin $g -> cos g * ∂/∂ g x | #`arccos $g -> 1 / sqrt (1 - g ^ 2) * ∂/∂ g x | apply $g $args ->- sum (map 2#((capply `(userRefs g [%1]) args) * ∂/∂ %2 x) (zip nats args))+ sum (map2 2#((capply `(userRefs g [%1]) args) * ∂/∂ %2 x) nats args) -- quote | quote $g -> let g' := ∂/∂ g x@@ -43,21 +43,21 @@ p2' := ∂/∂ p2 x in (p1' * p2 - p2' * p1) / p2 ^ 2 -d/d := ∂/∂+def d/d := ∂/∂ -pd/pd := ∂/∂+def pd/pd := ∂/∂ -∇ := ∂/∂+def ∇ := ∂/∂ -nabla := ∇+def nabla := ∇ -grad := ∇+def grad := ∇ -taylorExpansion $f $x $a := multivariateTaylorExpansion f [|x|] [|a|]+def taylorExpansion $f $x $a := multivariateTaylorExpansion f [|x|] [|a|] -maclaurinExpansion := 2#(taylorExpansion %1 %2 0)+def maclaurinExpansion := 2#(taylorExpansion %1 %2 0) -multivariateTaylorExpansion $f %xs %ys :=+def multivariateTaylorExpansion $f %xs %ys := withSymbols [h] let hs := generateTensor 1#h_%1 (tensorShape xs) in map2@@ -69,9 +69,5 @@ 1#(V.substitute hs (withSymbols [i] xs_i - ys_i) %1)) (iterate (compose 1#(∇ %1 xs) 1#(V.* hs %1)) f)) -multivariateMaclaurinExpansion $f %xs :=+def multivariateMaclaurinExpansion $f %xs := multivariateTaylorExpansion f xs (tensorMap 1#0 xs)--addUserScript $f $i :=- let (g, is) := deconsUserScripts f- in appendUserScripts g (sort (is ++ [i]))
lib/math/analysis/integral.egi view
@@ -4,7 +4,7 @@ -- -- -Sd x f :=+def Sd x f := match f as mathExpr with -- symbols | #x -> 1 / 2 * x ^ 2@@ -29,13 +29,13 @@ -- polynomial | poly $ts -> sum (map 1#(Sd x %1) ts) -- quotient- | (plus $ts) / $p2 -> sum (map 1#(Sd x (%1 / p2)) ts)+ | plus $ts / $p2 -> sum (map 1#(Sd x (%1 / p2)) ts) | $p1 / $p2 -> if containSymbol x p2 then `Sd x f else Sd x p1 / p2 -multSd x f g :=+def multSd x f g := let F := Sd x f in F * g - Sd x (F * d/d g x) -dSd x a b f :=+def dSd x a b f := let F := Sd x f in substitute [(x, b)] F - substitute [(x, a)] F
lib/math/common/arithmetic.egi view
@@ -4,59 +4,63 @@ -- -- -toMathExpr arg := mathNormalize (toMathExpr' arg)--(+') $x $y := b.+ x y+def toMathExpr arg := mathNormalize (toMathExpr' arg) -(-') $x $y := b.- x y+infixl expression 6 ++infixl expression 6 -+infixl expression 7 *+infixl expression 7 /+infixl expression 8 ^ -(*') $x $y := b.* x y+infixl expression 6 +'+infixl expression 6 -'+infixl expression 7 *'+infixl expression 7 /'+infixl expression 8 ^' -(/') $x $y := b./ x y+def (+') := b.++def (-') := b.-+def (*') := b.*+def (/') := b./ -(+) $x $y :=+def (+) $x $y := match (isFloat x, isFloat y) as eq with | #(True, True) -> f.+ x y | #(True, False) -> f.+ x (itof y) | #(False, True) -> f.+ (itof x) y | _ -> mathNormalize (x +' y) -(-) $x $y :=+def (-) $x $y := match (isFloat x, isFloat y) as eq with | #(True, True) -> f.- x y | #(True, False) -> f.- x (itof y) | #(False, True) -> f.- (itof x) y | _ -> mathNormalize (x -' y) -(*) $x $y :=+def (*) $x $y := match (isFloat x, isFloat y) as eq with | #(True, True) -> f.* x y | #(True, False) -> f.* x (itof y) | #(False, True) -> f.* (itof x) y | _ -> mathNormalize (x *' y) -(/) $x $y :=+def (/) $x $y := match (isFloat x, isFloat y) as eq with | #(True, True) -> f./ x y | #(True, False) -> f./ x (itof y) | #(False, True) -> f./ (itof x) y | _ -> x /' y -reduceFraction := id--sum xs := foldl (+) 0 xs--sum' xs := foldl (+') 0 xs--product xs := foldl (*) 1 xs--product' xs := foldl (*') 1 xs+def sum xs := foldl (+) 0 xs+def sum' xs := foldl (+') 0 xs -power $x $n := mathNormalize (power' x n)+def product xs := foldl (*) 1 xs+def product' xs := foldl (*') 1 xs -power' $x $n := foldl (*') 1 (take n (repeat1 x))+def power $x $n := mathNormalize (power' x n)+def power' $x $n := foldl (*') 1 (take n (repeat1 x)) -(^) $x $n :=+def (^) $x $n := if x = e then exp n else if isRational n@@ -65,7 +69,7 @@ else 1 / x ^ neg n else `(^) x n -(^') $x $n :=+def (^') $x $n := if x = e then exp n else if isRational n@@ -74,21 +78,21 @@ else 1 /' x ^' neg n else `(^) x n -gcd $x $y :=+def gcd $x $y := match (x, y) as (termExpr, termExpr) with | (_, #0) -> x | (#0, _) -> y | (term $a $xs, term $b $ys) -> gcd' (abs a) (abs b) *' foldl (*') 1 (map (^') (AC.intersect xs ys)) -gcd' $x $y :=+def gcd' $x $y := match (x, y) as (integer, integer) with | (_, #0) -> x | (#0, _) -> y | (_, ?(>= x)) -> gcd' (modulo y x) x | (_, _) -> gcd' y x -P./ fx $gx $x :=+def P./ fx $gx $x := let xs := reverse (coefficients fx x) ys := reverse (coefficients gx x) (zs, rs) := L./ xs ys
lib/math/common/constants.egi view
@@ -2,5 +2,5 @@ -- Mathematical constants -- -MinkowskiMetric :=+def MinkowskiMetric := [|[|-1, 0, 0, 0|], [|0, 1, 0, 0|], [|0, 0, 1, 0|], [|0, 0, 0, 1|]|]
lib/math/common/functions.egi view
@@ -2,11 +2,11 @@ -- Mathematical Functions -- -abs $x := if isRational x then b.abs x else x+def abs $x := if isRational x then b.abs x else x -neg $x := if isRational x then b.neg x else - x+def neg $x := if isRational x then b.neg x else - x -exp $x :=+def exp $x := if isFloat x then b.exp x else if isTerm x@@ -17,7 +17,7 @@ | _ -> `exp x else `exp x -log $x :=+def log $x := if isFloat x then b.log x else match x as mathExpr with@@ -25,7 +25,7 @@ | #e -> 1 | _ -> `log x -cos $x :=+def cos $x := if isFloat x then b.cos x else match x as mathExpr with@@ -34,7 +34,7 @@ | (mult _ #π) / #2 -> 0 | _ -> `cos x -sin $x :=+def sin $x := if isFloat x then b.sin x else match x as mathExpr with@@ -43,56 +43,56 @@ | (mult $n #π) / #2 -> (-1) ^ ((abs n - 1) / 2) | _ -> `sin x -tan $x :=+def tan $x := if isFloat x then b.tan x else match x as mathExpr with | #0 -> 0 | _ -> `tan x -acos := b.acos-asin := b.asin-atan := b.atan+def acos := b.acos+def asin := b.asin+def atan := b.atan -cosh $x :=+def cosh $x := if isFloat x then b.cosh x else match x as mathExpr with | #0 -> 1 | _ -> `cosh x -sinh $x :=+def sinh $x := if isFloat x then b.sinh x else match x as mathExpr with | #0 -> 0 | _ -> `sinh x -tanh $x :=+def tanh $x := if isFloat x then b.tanh x else match x as mathExpr with | #0 -> 0 | _ -> `tanh x -acosh := b.acosh-asinh := b.asinh-atanh := b.atanh+def acosh := b.acosh+def asinh := b.asinh+def atanh := b.atanh -sinc $x :=+def sinc $x := if isFloat x then if x = 0.0 then 1.0 else b.sin x / x else match x as mathExpr with | #0 -> 1 | _ -> sin x / x -sigmoid $z := 1 / (1 + exp (- z))+def sigmoid $z := 1 / (1 + exp (- z)) -kroneckerDelta := cambda js -> if all (= head js) (tail js) then 1 else 0+def kroneckerDelta := cambda js -> if all (= head js) (tail js) then 1 else 0 -eulerTotientFunction $n := n * product (map (\p -> 1 - 1 / p) (unique (pF n)))+def eulerTotientFunction $n := n * product (map (\p -> 1 - 1 / p) (unique (pF n))) -ε :=+def ε := memoizedLambda n -> let (es, os) := evenAndOddPermutations' n in generateTensor@@ -100,7 +100,7 @@ if member is es then 1 else if member is os then -1 else 0) (take n (repeat1 n)) -ε' :=+def ε' := memoizedLambda n k -> let (es, os) := evenAndOddPermutations' n in generateTensor
lib/math/expression.egi view
@@ -4,33 +4,47 @@ -- -- -mathExpr :=+infixr pattern 6 ++infixr pattern 7 *+infix pattern 7 /+infix pattern 8 ^++def mathExpr := matcher | #$val as () with | $tgt -> if val = tgt then [()] else [] | $ as (mathExpr') with | $tgt -> [fromMathExpr tgt] -mathExpr' :=+def mathExpr' := matcher- | div $ $ as (mathExpr, mathExpr) with+ | $ / $ as (mathExpr, mathExpr) with | Div $p1 $p2 -> [(toMathExpr' p1, toMathExpr' p2)] | _ -> [] | poly $ as (multiset mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) -> [map toMathExpr' ts] | _ -> []- | plus $ as (plusExpr) with+ | plus $ as (multiset mathExpr) with | Div (Plus $ts) (Plus [Term 1 []]) ->- [toMathExpr' (Div (Plus ts) (Plus [Term 1 []]))]+ map (\t -> toMathExpr' (Div (Plus [t]) (Plus [Term 1 []]))) ts | _ -> []+ | $ + $ as (mathExpr, mathExpr) with+ | Div (Plus $ts) (Plus [Term 1 []]) ->+ matchAll (map toMathExpr' ts) as multiset something with+ | $t :: $tss -> (t, sum' tss)+ | _ -> [] | term $ $ as (integer, assocMultiset mathExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) ->- [(n, map 2#(toMathExpr' %1, %2) xs)]+ [(n, map (\(x, n) -> (toMathExpr' x, n)) xs)] | _ -> [] | mult $ $ as (integer, multExpr) with | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) ->- [(n, product' (map 2#(toMathExpr' %1 ^' %2) xs))]+ [(n, product' (map (\(x, n) -> toMathExpr' x ^' n) xs))] | _ -> []+ | $ * $ as (integer, multExpr) with+ | Div (Plus [Term $n $xs]) (Plus [Term 1 []]) ->+ [(n, product' (map (\(x, n) -> toMathExpr' x ^' n) xs))]+ | _ -> [] | symbol $ $ as (eq, list indexExpr) with | Div (Plus [Term 1 [(Symbol $v $js, 1)]]) (Plus [Term 1 []]) -> [(v, js)]@@ -44,95 +58,79 @@ [toMathExpr' mexpr] | _ -> [] | func $ $ $ $ as- (mathExpr, list mathExpr, list mathExpr, list indexExpr ) with+ (mathExpr, list mathExpr, list mathExpr, list indexExpr) with | Div (Plus [Term 1 [(Function $name $argnames $args $js, 1)]]) (Plus [Term 1 []]) -> [(name, argnames, args, js)] | _ -> []- | $ as (something) with+ | $ as something with | $tgt -> [toMathExpr' tgt] -indexExpr :=+def indexExpr := algebraicDataMatcher | sub mathExpr | sup mathExpr | user mathExpr -polyExpr := mathExpr--termExpr := mathExpr+def polyExpr := mathExpr -symbolExpr := mathExpr+def termExpr := mathExpr -plusExpr :=- matcher- | [] as () with- | $tgt -> if tgt = 0 then [()] else []- | $ :: $ as (mathExpr, plusExpr) with- | $tgt ->- matchAll tgt as mathExpr with- | poly ($t :: $ts) -> (t, sum' ts)- | $ as (mathExpr) with- | $tgt -> [tgt]+def symbolExpr := mathExpr -multExpr :=+def multExpr := matcher | [] as () with | $tgt -> match tgt as mathExpr with | #0 -> [()] | _ -> []- | $ :: $ as (mathExpr, multExpr) with+ | $ ^ #$k * $ as (mathExpr, multExpr) with | $tgt ->- match tgt as mathExpr with- | term _ $xs ->- matchAll xs as assocMultiset mathExpr with- | $x :: $rs -> (x, product' (map (^') rs))- | _ -> []- | ncons $ #$k $ as (mathExpr, multExpr) with+ matchAll tgt as mathExpr with+ | term _ (ncons $x #k $xs) -> (x, product' (map (uncurry (^')) xs))+ | $ ^ $ * $ as (mathExpr, integer, multExpr) with | $tgt ->- match tgt as mathExpr with- | term _ $xs ->- matchAll xs as list (mathExpr, integer) with- | $hs ++ ($x, ?(>= k) & $n) :: $ts ->- (x, product' (map (^') (hs ++ (x, n - k) :: ts)))- | _ -> []- | ncons $ $ $ as (mathExpr, integer, multExpr) with+ matchAll tgt as mathExpr with+ | term _ (ncons $x $n $xs) -> (x, n, product' (map (uncurry (^')) xs))+ | $ ^ $ as (mathExpr, integer) with | $tgt -> match tgt as mathExpr with- | term _ $xs ->- matchAll xs as list (mathExpr, integer) with- | $hs ++ ($x, $n) :: $ts -> (x, n, product' (map (^') (hs ++ ts)))+ | term _ (ncons $x $n []) -> [(x, n)] | _ -> []- | $ as (mathExpr) with+ | $ * $ as (mathExpr, multExpr) with+ | $tgt ->+ matchAll tgt as mathExpr with+ | term _ ($x :: $rs) -> (x, product' (map (uncurry (^')) rs))+ | $ as mathExpr with | $tgt -> [tgt] -isSymbol %mexpr :=+def isSymbol %mexpr := match mexpr as mathExpr with | symbol _ _ -> True | _ -> False -isApply %mexpr :=+def isApply %mexpr := match mexpr as mathExpr with | apply _ _ -> True | _ -> False -isSimpleTerm := 1#(isSymbol %1 || isApply %1)+def isSimpleTerm mexpr := isSymbol mexpr || isApply mexpr -isTerm %mexpr :=+def isTerm %mexpr := match mexpr as mathExpr with | term _ _ -> True | #0 -> True | _ -> False -isPolynomial %mexpr :=+def isPolynomial %mexpr := match mexpr as mathExpr with | poly _ -> True | #0 -> True | _ -> False -isMonomial %mexpr :=+def isMonomial %mexpr := match mexpr as mathExpr with | poly [term _ _] / poly [term _ _] -> True | #0 -> True@@ -141,168 +139,94 @@ -- -- Accessor ---symbolIndices $mexpr :=- match mexpr as mathExpr with- | symbol _ $js -> js- | _ -> undefined--fromMonomial $mexpr :=+def fromMonomial $mexpr := match mexpr as mathExpr with- | (term $a $xs) / (term $b $ys) ->- (a / b, foldl (*') 1 (map (^') xs) / foldl (*') 1 (map (^') ys))+ | term $a $xs / term $b $ys ->+ (a / b, foldl (*') 1 (map (uncurry (^')) xs) / foldl (*') 1 (map (uncurry (^')) ys)) -- -- Map ---mapPolys $fn $mexpr :=+def mapPolys $fn $mexpr := match mexpr as mathExpr with | $p1 / $p2 -> fn p1 /' fn p2 -fromPoly $mexpr :=+def fromPoly $mexpr := match mexpr as mathExpr with | poly $ts1 / $q -> map (\t1 -> t1 /' q) ts1 -mapPoly $fn $mexpr :=+def mapPoly $fn $mexpr := match mexpr as mathExpr with | poly $ts1 / $q -> foldl (+') 0 (map (\t1 -> fn (t1 /' q)) ts1) -mapTerms $fn $mexpr :=+def mapTerms $fn $mexpr := match mexpr as mathExpr with | poly $ts1 / poly $ts2 -> foldl (+') 0 (map fn ts1) /' foldl (+') 0 (map fn ts2) -mapSymbols $fn $mexpr :=+def mapSymbols $fn $mexpr := mapTerms- (\term ->- match term as termExpr with- | term $a $xs ->- a *' foldl- (*')- 1- (map- 2#(match %1 as symbolExpr with- | symbol _ _ -> fn %1 ^' %2- | apply $g $args ->- let args' := map 1#(mapSymbols fn %1) args- in if args = args'- then %1 ^' %2- else fn (capply g args') ^' %2)- xs))+ (\match as termExpr with+ | term $a $xs ->+ a *' foldl+ (*')+ 1+ (map+ (\(x, n) -> match x as symbolExpr with+ | symbol _ _ -> fn x ^' n+ | apply $g $args ->+ let args' := map (mapSymbols fn) args+ in if args = args'+ then x ^' n+ else fn (capply g args') ^' n)+ xs)) mexpr -containSymbol $x $mexpr :=- any- id- (match mexpr as mathExpr with- | poly $ts1 / poly $ts2 ->- map- (\term ->- match term as termExpr with- | term _ $xs ->- any- id- (map- 2#(match %1 as symbolExpr with- | #x -> True- | apply _ $args ->- any id (map 1#(containSymbol x %1) args)- | _ -> False)- xs))- (ts1 ++ ts2))--containFunction $f $mexpr :=- any- id- (match mexpr as mathExpr with- | poly $ts1 / poly $ts2 ->- map- (\term ->- match term as termExpr with- | term _ $xs ->- any- id- (map- 2#(match %1 as symbolExpr with- | apply $g $args ->- if f = g- then True- else any id (map 1#(containFunction f %1) args)- | _ -> False)- xs))- (ts1 ++ ts2))--containFunctionWithOrder $f $n $mexpr :=- any- id- (match mexpr as mathExpr with- | poly $ts1 / poly $ts2 ->- map- (\term ->- match term as termExpr with- | term _ $xs ->- any- id- (map- 2#(match %1 as symbolExpr with- | apply $g $args ->- if f = g && %2 >= n- then True- else any- id- (map- 1#(containFunctionWithOrder f n %1)- args)- | _ -> False)- xs))- (ts1 ++ ts2))+def scanAllTerms $mexpr $f :=+ match mexpr as mathExpr with+ | poly $ts1 / poly $ts2 -> any f (ts1 ++ ts2) -containFunctionWithIndex $mexpr :=- any- id- (match mexpr as mathExpr with- | poly $ts1 / poly $ts2 ->- map- (\term ->- match term as termExpr with- | term _ $xs ->- any- id- (map- 2#(match %1 as symbolExpr with- | apply (?isScalar & $f) $args ->- match f as mathExpr with- | symbol _ ![] -> True- | _ ->- any id (map 1#(containFunctionWithIndex %1) args)- | apply _ $args ->- any id (map 1#(containFunctionWithIndex %1) args)- | _ -> False)- xs))- (ts1 ++ ts2))+def containSymbol $x $mexpr :=+ scanAllTerms mexpr+ (\match as termExpr with+ | term _ $xs ->+ any+ (\(y, _) -> match y as symbolExpr with+ | #x -> True+ | apply _ $args -> any (containSymbol x) args+ | _ -> False)+ xs) -findSymbolsFromPoly $poly :=- matchAll poly as mathExpr with- | poly (term _ ((symbol _ _ & $s) :: _) :: _) -> s+def containFunction $f $mexpr :=+ scanAllTerms mexpr+ (\match as termExpr with+ | term _ $xs ->+ any+ (\(y, _) -> match y as symbolExpr with+ | apply #f _ -> True+ | apply $g $args -> any (containFunction f) args+ | _ -> False)+ xs) -- -- Substitute ---substitute %ls $mexpr :=+def substitute %ls $mexpr := match ls as list (symbolExpr, mathExpr) with- | [] -> mexpr+ | [] -> mathNormalize mexpr | ($x, $a) :: $rs -> substitute rs (substitute' x a mexpr) -substitute' $x %a $mexpr := mapSymbols 1#(rewriteSymbol x a %1) mexpr+def substitute' $x %a $mexpr := mapSymbols (rewriteSymbol x a) mexpr -rewriteSymbol $x $a $sexpr :=+def rewriteSymbol $x $a $sexpr := match sexpr as symbolExpr with | #x -> a | _ -> sexpr -V.substitute %xs %ys $mexpr :=+def V.substitute %xs %ys $mexpr := substitute (zip (tensorToList xs) (tensorToList ys)) mexpr -expandAll $mexpr :=+def expandAll $mexpr := match mexpr as mathExpr with | ?isSymbol -> mexpr -- function application@@ -310,16 +234,13 @@ -- quote | quote $g -> g -- term (multiplication)- | term $a $ps -> a * product (map 2#(expandAll %1 ^ expandAll %2) ps)+ | term $a $ps -> a * product (map (\(x, n) -> expandAll x ^ expandAll n) ps) -- polynomial | poly $ts -> sum (map expandAll ts) -- quotient- | $p1 / $p2 ->- let p1' := expandAll p1- p2' := expandAll p2- in p1' / p2'+ | $p1 / $p2 -> expandAll p1 / expandAll p2 -expandAll' $mexpr :=+def expandAll' $mexpr := match mexpr as mathExpr with | ?isSymbol -> mexpr -- function application@@ -327,40 +248,37 @@ -- quote | quote $g -> g -- term (multiplication)- | term $a $ps -> a *' product' (map 2#(expandAll' %1 ^' expandAll' %2) ps)+ | term $a $ps -> a *' product' (map (\(x, n) -> expandAll' x ^' expandAll' n) ps) -- polynomial | poly $ts -> sum' (map expandAll' ts) -- quotient- | $p1 / $p2 ->- let p1' := expandAll' p1- p2' := expandAll' p2- in p1' /' p2'+ | $p1 / $p2 -> expandAll' p1 / expandAll' p2 -- -- Coefficient ---coefficients $f $x :=+def coefficients $f $x := let m := maximum (0 :: (matchAll f as mathExpr with | poly (term $a (ncons #x $k $ts) :: _) / _ -> k))- in map 1#(coefficient f x %1) (between 0 m)+ in map (coefficient f x) (between 0 m) -coefficient $f $x $m :=+def coefficient $f $x $m := if m = 0 then sum (matchAll f as mathExpr with | poly (term $a (!(#x :: _) & $ts) :: _) / _ ->- foldl (*') a (map (^') ts)) / denominator f+ foldl (*') a (map (uncurry (^')) ts)) / denominator f else coefficient' f x m -coefficient' $f $x $m :=+def coefficient' $f $x $m := sum (matchAll f as mathExpr with- | poly (term $a (ncons #x $k $ts) :: _) / _ ->- if m = k then foldl (*') a (map (^') ts) else 0) / denominator f+ | poly (term $a (ncons #x #m (!(#x :: _) & $ts)) :: _) / _ ->+ foldl (*') a (map (uncurry (^')) ts)) / denominator f -coefficient2 $f $x $y :=+def coefficient2 $f $x $y := sum (matchAll f as mathExpr with | poly (term $a (#x :: #y :: $ts) :: _) / _ ->- foldl (*') a (map (^') ts)) / denominator f+ foldl (*') a (map (uncurry (^')) ts)) / denominator f
lib/math/geometry/3d-euclidean-space.egi view
@@ -1,6 +1,6 @@-coordinates := [x, y, z]+def coordinates := [x, y, z] -metric :=+def metric := generateTensor (\match as (integer, integer) with | ($n, #n) -> 1
lib/math/geometry/4d-euclidean-space.egi view
@@ -1,6 +1,6 @@-coordinates := [x, y, z, w]+def coordinates := [x, y, z, w] -metric :=+def metric := generateTensor (\match as (integer, integer) with | ($n, #n) -> 1
lib/math/geometry/differential-form.egi view
@@ -1,4 +1,4 @@-dfNormalize %X :=+def dfNormalize %X := let p := dfOrder X (es, os) := evenAndOddPermutations p in withSymbols [i]@@ -6,15 +6,15 @@ - sum (map (\σ -> subrefs X (map 1#i_(σ %1) (between 1 p))) os)) / fact p -antisymmetrize := dfNormalize+def antisymmetrize := dfNormalize -wedge %X %Y := X !. Y+def wedge %X %Y := X !. Y -Lie.wedge %X %Y := X !. Y - Y !. X+def Lie.wedge %X %Y := X !. Y - Y !. X -ι %X %Y := withSymbols [i] dfOrder Y * (X...~i . dfNormalize Y..._i)+def ι %X %Y := withSymbols [i] dfOrder Y * (X...~i . dfNormalize Y..._i) -Lie %X %Y :=+def Lie %X %Y := match dfOrder Y as integer with | #0 -> ι X (d Y) | #N -> d (ι X Y)
lib/math/geometry/minkowski-space.egi view
@@ -1,6 +1,6 @@-coordinates := [t, x, y, z]+def coordinates := [t, x, y, z] -metric :=+def metric := generateTensor (\match as (integer, integer) with | (#1, #1) -> -1
+ lib/math/no-normalize.egi view
@@ -0,0 +1,7 @@+--+--+-- Term Rewriting+--+--++def mathNormalize := id
lib/math/normalize.egi view
@@ -4,236 +4,23 @@ -- -- ---mathNormalize := id-mathNormalize $x :=+def mathNormalize $x := if isInteger x then x- else (foldr compose id (map 2#%1 (filter 2#(%2 x) rewriteRules))) x--rewriteRules :=- [ (rewriteRuleForI, 1#(containSymbol i %1))- , (rewriteRuleForWTerm, 1#(containSymbol w %1))- , (rewriteRuleForRtuTerm, 1#(containFunction `rtu %1))- , (rewriteRuleForPower, 1#(containFunction `(^) %1))- , (rewriteRuleForExp, 1#(containFunction `exp %1))- , (rewriteRuleForWPoly, 1#(containSymbol w %1))- , (rewriteRuleForRtuPoly, 1#(containFunction `rtu %1))- , (rewriteRuleForSqrt, 1#(containFunction `sqrt %1))- , (rewriteRuleForRt, 1#(containFunction `rt %1))- , (rewriteRuleForSin, 1#(containFunction `sin %1))- , (rewriteRuleForCos, 1#(containFunction `cos %1))- , (rewriteRuleForLog, 1#(containFunction `log %1))- , (rewriteRuleForCosToSin, 1#(containFunctionWithOrder `cos 2 %1))- , (rewriteRuleForD/d, 1#True) ]------- i----rewriteRuleForI := rewriteRuleForITerm--rewriteRuleForITerm := 1#(mapTerms rewriteRuleForITerm' %1)--rewriteRuleForITerm' term :=- match term as mathExpr with- | $a * #i ^ (?isEven & $k) * $r -> a *' (-1) ^' quotient k 2 *' r- | $a * #i ^ $k * $r -> a *' (-1) ^' quotient k 2 *' r *' i- | _ -> term------- w----rewriteRuleForW := 1#(compose rewriteRuleForWTerm rewriteRuleForWPoly %1)--rewriteRuleForWTerm := 1#(mapTerms rewriteRuleForWTerm' %1)--rewriteRuleForWPoly := 1#(mapPolys rewriteRuleForWPoly' %1)--rewriteRuleForWTerm' term :=- match term as mathExpr with- | $a * #w ^ (?(>= 3) & $k) * $r -> a *' r *' w ^' (k % 3)- | _ -> term--rewriteRuleForWPoly' poly :=- match poly as mathExpr with- | $a * #w ^ #2 * $mr + $b * #w * #mr + $pr ->- rewriteRuleForWPoly' (pr +' (-1) *' a *' mr +' (b - a) *' mr *' w)- | _ -> poly+ else if containFunction `rtu x+ then rewriteRuleForRtu (symbolNormalize x)+ else symbolNormalize x -- -- rtu (include i and w) ---rewriteRuleForRtu :=- compose- 1#(mapTerms rewriteRuleForRtuTerm %1)- 1#(mapPolys rewriteRuleForRtuPoly %1)--rewriteRuleForRtuTerm := 1#(mapTerms rewriteRuleForRtuTerm' %1)--rewriteRuleForRtuPoly := 1#(mapPolys rewriteRuleForRtuPoly' %1)--rewriteRuleForRtuTerm' term :=- match term as mathExpr with- | $a * #`rtu $n ^ (?(>= n) & $k) * $r -> a *' rtu n ^' (k % n) *' r- | _ -> term--rewriteRuleForRtuPoly' poly :=- match poly as mathExpr with- | $a * #rtu $n ^ #1 * $mr + (loop $i (2, #(n - 1))- (#a * #(rtu n) ^ #i * #mr + ...)- $pr) ->- rewriteRuleForRtuPoly' (pr +' (-1) *' a *' mr)- | _ -> poly------- sqrt----rewriteRuleForSqrt := 1#(mapTerms rewriteRuleForSqrtTerm %1)--rewriteRuleForSqrtTerm term :=- match term as mathExpr with- | $a * #`sqrt $x * #`sqrt #x * $r -> rewriteRuleForSqrt (a *' x *' r)- | $a * #`sqrt (?isTerm & $x) * #`sqrt (?isTerm & $y) * $r ->- let d := gcd x y- (a1, x1) := fromMonomial (x / d)- (a2, y1) := fromMonomial (y / d)- in a *' d *' sqrt (a1 *' a2) *' sqrt x1 *' sqrt y1 *' r- | _ -> term------- rt (include sqrt)----rewriteRuleForRt := 1#(mapTerms rewriteRuleForRtTerm %1)--rewriteRuleForRtTerm term :=- match term as mathExpr with- | $a * #`rt $n $x ^ (?(>= n) & $k) * $r ->- a *' x ^' quotient k n *' rt n x ^' (k % n) *' r- | _ -> term------- exp----rewriteRuleForExp := 1#(mapTerms rewriteRuleForExpTerm %1)--rewriteRuleForExpTerm term :=- match term as mathExpr with- | $a * #`exp #0 * $r -> a *' r- | $a * #`exp #1 * $r -> a *' e *' r- | $a * #`exp (mult $x #(i * π)) * $r -> a *' (-1) ^ x *' r- | $a * #`exp $x ^ (?(>= 2) & $n) * $r ->- rewriteRuleForExp (a *' exp (x * n) *' r)- | $a * #`exp $x * #`exp $y * $r -> rewriteRuleForExp (a *' exp (x + y) *' r)- | _ -> term------- log----rewriteRuleForLog mExpr := mapTerms f mExpr- where- f term :=- match term as mathExpr with- | _ * #`log #1 * _ -> 0- | $a * #`log #e * $mr -> a *' mr- | _ -> term------- power----rewriteRuleForPower := 1#(mapTerms rewriteRuleForPowerTerm %1)--rewriteRuleForPowerTerm term :=- match term as mathExpr with- | $a * #`(^) #1 _ ^ _ * $r -> rewriteRuleForPower (a *' r)- | $a * #`(^) $x $y ^ (?(>= 2) & $n) * $r ->- rewriteRuleForPower (a *' x ^ (y * n) *' r)- | $a * #`(^) $x $y * #`(^) #x $z * $r ->- rewriteRuleForPower (a *' x ^ (y + z) *' r)- | _ -> term------- cos, sin----rewriteRuleForCosAndSin := 1#(mapPolys rewriteRuleForCosAndSinPoly %1)--rewriteRuleForCosAndSinExpr expr :=- match (expr, expr) as (mathExpr, mathExpr) with- | ( ($a * #`cos $x * $mr + $pr1) / $pr2- , ( _ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) / _- | _ / (_ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) ) ->- rewriteRuleForCosAndSinExpr- ((a *' (cos (x / 2) ^ 2 -' sin (x / 2) ^ 2) *' mr +' pr1) /' pr2)- | ( ($a * #`sin $x * $mr + $pr1) / $pr2- , ( _ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) / _- | _ / (_ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) ) ->- rewriteRuleForCosAndSinExpr- ((a *' 2 *' cos (x / 2) *' sin (x / 2) *' mr +' pr1) /' pr2)- | ( $pr2 / ($a * #`cos $x * $mr + $pr1)- , ( _ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) / _- | _ / (_ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) ) ->- rewriteRuleForCosAndSinExpr- (pr2 /' (a *' (cos (x / 2) ^ 2 -' sin (x / 2) ^ 2) *' mr +' pr1))- | ( $pr2 / ($a * #`sin $x * $mr + $pr1)- , ( _ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) / _- | _ / (_ * (#`cos #(x / 2) | #`sin #(x / 2)) * _ + _) ) ->- rewriteRuleForCosAndSinExpr- (pr2 /' (a *' 2 *' cos (x / 2) *' sin (x / 2) *' mr +' pr1))- | _ -> expr--rewriteRuleForCosAndSinPoly poly :=- match poly as mathExpr with- | $a * #`cos $x ^ #2 * $mr + #a * #`sin #x ^ #2 * #mr + $pr ->- rewriteRuleForCosAndSinPoly (pr +' a *' mr)- | $a * $mr + #(- a) * #`sin $x ^ #2 * #mr + $pr ->- rewriteRuleForCosAndSinPoly (pr +' a *' cos x ^ 2 *' mr)- | $a * $mr + #(- a) * #`cos $x ^ #2 * #mr + $pr ->- rewriteRuleForCosAndSinPoly (pr +' a *' sin x ^ 2 *' mr)- | _ -> poly--rewriteRuleForCosToSin := 1#(mapTerms rewriteRuleForCosToSinTerm' %1)--rewriteRuleForCosToSinTerm' term :=- match term as mathExpr with- | $a * #`cos $x ^ #2 * $mr ->- a *' (1 -' sin x ^ 2) *' rewriteRuleForCosToSinTerm' mr- | _ -> term--rewriteRuleForSin mExpr := mapTerms f mExpr- where- f term :=- match term as mathExpr with- | _ * #`sin #0 * _ -> 0- | _ * #`sin (mult _ #π) * _ -> 0- | $a * #`sin (mult $n #π / #2) * $mr ->- a *' (-1) ^ ((abs n - 1) / 2) *' mr- | _ -> term--rewriteRuleForCos mExpr := mapTerms f mExpr+def rewriteRuleForRtu := mapPolys rewriteRuleForRtuPoly where- f term :=- match term as mathExpr with- | $a * #`cos #0 * $mr -> a *' mr- | $a * #`cos (term $n [#π]) * $mr -> a *' (-1) ^ abs n *' mr- | _ * #`cos (mult _ #π / #2) * _ -> 0- | _ -> term------- d----rewriteRuleForD := 1#(mapTerms rewriteRuleForDTerm %1)--rewriteRuleForDTerm term :=- match term as mathExpr with- | _ * #d _ * #d _ * _ -> 0- | _ -> term------- d/d----rewriteRuleForD/d := 1#(mapPolys rewriteRuleForD/dPoly %1)--rewriteRuleForD/dPoly poly :=- match poly as mathExpr with- | $a * ($f & (func $g _ $arg $js)) ^ $n * $mr +- $b * func #g _ #arg ?1#(eqAs (multiset something) js %1) ^ #n * #mr + $pr ->- rewriteRuleForD/dPoly ((a + b) *' f ^ n *' mr +' pr)- | _ -> poly+ rewriteRuleForRtuPoly := mapPolys rewriteRuleForRtuPoly'+ rewriteRuleForRtuPoly' poly :=+ match poly as mathExpr with+ | $a * #rtu $n ^ #1 * $mr + (loop $i (2, #(n - 1))+ (#a * #(rtu n) ^ #i * #mr + ...)+ $pr) ->+ rewriteRuleForRtuPoly' (pr +' (-1) *' a *' mr)+ | _ -> poly
+ sample/bellman-ford.egi view
@@ -0,0 +1,20 @@+-- initiate a distance graph+def A :=+ [|[|0, 19, 36, 66, 99, 65|]+ , [|19, 0, 25, 59, 64, 31|]+ , [|36, 25, 0, 84, 48, 28|]+ , [|66, 59, 84, 0, 59, 29|]+ , [|99, 64, 48, 59, 0, 9|]+ , [|65, 31, 28, 29, 9, 0|]|]++def G.* t1 t2 := withSymbols [i]+ reduce min (contract (t1~#_i + t2~i_#))++match iterate (\P -> G.* P A) A as list something with+ | _ ++ $P :: #P :: _ -> P+-- [|[| 0, 19, 36, 66, 59, 50 |]+-- [| 19, 0, 25, 59, 40, 31 |]+-- [| 36, 25, 0, 57, 37, 28 |]+-- [| 66, 59, 57, 0, 38, 29 |]+-- [| 59, 40, 37, 38, 0, 9 |]+-- [| 50, 31, 28, 29, 9, 0 |]|]
sample/chopsticks.egi view
@@ -1,4 +1,4 @@-assocMultiset a := matcher+def assocMultiset a := matcher | [] as () with | [] -> [()] | _ -> []@@ -28,30 +28,30 @@ | $x :: $rs -> (x,rs)) [(2, [(1, 2), (3, 3)]), (1, [(1, 1), (2, 1), (3, 3)]), (3, [(1, 2), (2, 1), (3, 2)])] -assocToList xs := concat (matchAllDFS xs as list (something, integer) with+def assocToList xs := concat (matchAllDFS xs as list (something, integer) with | _ ++ ($x, $n) :: _ -> take n (repeat1 x)) assertEqual "assocToList" (assocToList [(1,2),(2,1),(3,3)]) [1, 1, 2, 3, 3, 3] -N := 5+def N := 5 -tree a := matcher+def tree a := matcher | node $ $ as (a, multiset (tree a)) with | Node $x $ts -> [(x, ts)] | $ as something with | $tgt -> [tgt] -state := (integer, assocMultiset integer, assocMultiset integer)+def state := (integer, assocMultiset integer, assocMultiset integer) -fOrS s := match s as state with+def fOrS s := match s as state with | ($h, _, _) -> h -transformState s := match s as state with+def transformState s := match s as state with | ($h, $x, $y) -> (h, assocToList x, assocToList y) -move s := matchAllDFS s as state with+def move s := matchAllDFS s as state with -- equal or less than N | (#1, ($s1 & $x :: _), (?(\y -> x + y < N + 1) & $y) :: $rs') -> (2, s1, add (x + y) rs')@@ -71,7 +71,7 @@ | (#2, $x :: (![] & $rs'), (?(\y -> x + y > N) :: _) & $s2) -> (1, rs', s2) -add x xs := matchDFS xs as list (integer, integer) with+def add x xs := matchDFS xs as list (integer, integer) with | $hs ++ (#x, $n) :: $ts -> hs ++ (x, n + 1) :: ts | $hs ++ (!((?(\y -> x > y), _) :: _) & $ts) -> hs ++ (x, 1) :: ts | _ -> (x, 1) :: xs@@ -90,13 +90,13 @@ (add 2 [(1,3),(3,1)]) [(1, 3), (2, 1), (3, 1)] -init := (1, [(1,2)], [(1,2)])+def init := (1, [(1,2)], [(1,2)]) assertEqual "move" (move init) [(2, [(1, 2)], [(1, 1), (2, 1)])] -makeTree x := Node x (map makeTree (move x))+def makeTree x := Node x (map makeTree (move x)) assertEqual "makeTree" (makeTree (1, [(2, 1)], [(1, 1)]))@@ -106,7 +106,7 @@ [Node (-1, [(5, 1)], []) []]]]) -topTree s n :=+def topTree s n := matchAllDFS makeTree s as tree state with | loop $i (1, [1..n], $m) (node $x_i (... :: _))@@ -114,7 +114,7 @@ -> map (\i -> x_i) [1..m] -paths :=+def paths := matchAllDFS makeTree init as tree state with | loop $i (1, $n) (node $x_i (... :: _))@@ -123,7 +123,7 @@ --io (each (compose show print) (head paths)) -winningRec s :=+def winningRec s := matchAll makeTree s as tree state with | (node ($h, _, _) ((node ($t & ((#(neg h), _, _)@@ -131,7 +131,7 @@ :: _)) -> t -winningNot s :=+def winningNot s := matchAllDFS makeTree s as tree state with | node ($h, _, _) (loop $i (1, [1..], _)@@ -139,7 +139,7 @@ (node (#(neg h), _, _) _ :: _)) -> t -winning c :=+def winning c := matchAllDFS makeTree c as tree state with | node ($h, _, _) (loop $i (1, $n)
sample/chopsticks2.egi view
@@ -1,4 +1,4 @@-paths :=+def paths := [[(1, [1, 1], [1, 1]), (2, [1, 1], [1, 2]), (1, [1, 2], [1, 2]), (2, [1, 2], [2, 2]), (1, [1, 4], [2, 2]), (2, [1, 4], [2]), (1, [1], [2]), (2, [1], [3]), (1, [4], [3]), (-1, [4], [])] ,[(1, [1, 1], [1, 1]), (2, [1, 1], [1, 2]), (1, [1, 2], [1, 2]), (2, [1, 2], [2, 2]), (1, [1, 4], [2, 2]), (2, [1, 4], [2]), (1, [3, 4], [2]), (-1, [3, 4], [])] ,[(1, [1, 1], [1, 1]), (2, [1, 1], [1, 2]), (1, [1, 2], [1, 2]), (2, [1, 2], [2, 2]), (1, [1, 4], [2, 2]), (2, [1, 4], [2]), (1, [3, 4], [2]), (2, [3, 4], [5]), (1, [3], [5]), (-1, [3], [])]@@ -23,9 +23,9 @@ ,[(1, [1, 1], [1, 1]), (2, [1, 1], [1, 2]), (1, [1, 3], [1, 2]), (2, [1, 3], [2, 2]), (1, [3, 3], [2, 2]), (2, [3, 3], [2, 5]), (1, [3, 5], [2, 5]), (2, [3, 5], [5]), (1, [5], [5]), (-1, [5], [])] ,[(1, [1, 1], [1, 1]), (2, [1, 1], [1, 2]), (1, [1, 3], [1, 2]), (2, [1, 3], [2, 2]), (1, [3, 3], [2, 2]), (2, [3, 3], [2, 5]), (1, [3], [2, 5]), (2, [3], [2]), (1, [5], [2]), (-1, [5], [])]] -paths2 := map (\p -> take 3 p) paths+def paths2 := map (\p -> take 3 p) paths -listToTree ps := matchDFS ps as list (list eq) with+def listToTree ps := matchDFS ps as list (list eq) with | [] :: [] -> [] | loop $i (1, $m) (($x_i :: $r_i_1) :: (loop $j (2, $n_i)
sample/demo1-ja.egi view
@@ -1,5 +1,5 @@ -- 素数の無限リストから全ての双子素数をパターンマッチにより抽出-twinPrimes :=+def twinPrimes := matchAll primes as list integer with | _ ++ $p :: #(p + 2) :: _ -> (p, p + 2)
sample/demo1.egi view
@@ -1,5 +1,5 @@ -- Extract all twin primes from the infinite list of prime numbers with pattern matching!-twinPrimes :=+def twinPrimes := matchAll primes as list integer with | _ ++ $p :: #(p + 2) :: _ -> (p, p + 2)
sample/generalized-sequential-pattern-mining.egi view
@@ -6,32 +6,32 @@ -- Configuration -- -items := [a, b, c, d, e, f]+def items := [a, b, c, d, e, f] -ISDB :=+def ISDB := [[[(0, [a]), (86400, [a, b, c]), (259200, [a, c])]] ,[[(0, [a, d]), (259200, [c])]] ,[[(0, [a, e, f]), (172800, [a, b])]]] -N := length ISDB-minSup := ceiling (0.5 * N)+def N := length ISDB+def minSup := ceiling (0.5 * N) -C1 := 0 -- min_interval-C2 := 172800 -- max_interval-C3 := 0 -- min_whole_interval-C4 := 300000 -- max_whole_interval+def C1 := 0 -- min_interval+def C2 := 172800 -- max_interval+def C3 := 0 -- min_whole_interval+def C4 := 300000 -- max_whole_interval -I t := floor (rtof (t / (60 * 60 * 24)))+def I t := floor (rtof (t / (60 * 60 * 24))) -- -- Utils -- -query := list (integer, eq)+def query := list (integer, eq) -sequence := list (time, list eq)+def sequence := list (time, list eq) -time := matcher+def time := matcher | interval $ $ as (integer, integer) with | $t -> [(I t, t)] | $ as something with@@ -43,13 +43,13 @@ -- -- calculate ISDB|α-project α ISDB := match α as query with+def project α ISDB := match α as query with | (#0, $x) :: $α' -> project' α' (map (\xss -> matchAllDFS xss as set sequence with | (_ ++ ($t, _ ++ #x :: $cs) :: $ls) :: _ -> (0, cs) :: (map (\t' xs -> (t' - t, xs)) ls)) ISDB) -project' α ISDB := match α as query with+def project' α ISDB := match α as query with | [] -> ISDB | ($a, $x) :: $α' -> project' (map (\b y -> (b - a, y)) α') (map (\xss -> matchAllDFS xss as set sequence with@@ -58,7 +58,7 @@ ISDB) -- main function-gspm items ISDB I minSup C1 C2 C3 C4 :=+def gspm items ISDB I minSup C1 C2 C3 C4 := let φ := [] in let R := [] in let fs := filter (\α ISDB' -> match ISDB' as multiset sequence with@@ -68,7 +68,7 @@ let iss := map (\α ISDB' -> α) fs in iss ++ concat (map (\α ISDB' -> projection α ISDB' I minSup C1 C2 C3 C4) fs) -projection α ISDB' I minSup C1 C2 C3 C4 :=+def projection α ISDB' I minSup C1 C2 C3 C4 := let fs := filter (\a t x -> C1 <= t && t <= C2) (freqItem ISDB' minSup C1 C2 C3 C4) in let iss' := map (\a t x -> α ++ [(a, x)]) fs in -- TODO: apply C4@@ -76,7 +76,7 @@ iss' ++ concat (map (\α' -> projection α' (project α' ISDB) I minSup C1 C2 C3 C4) iss') -freqItem ISDB minSup C1 C2 C3 C4 :=+def freqItem ISDB minSup C1 C2 C3 C4 := matchAll ISDB as list (list sequence) with | first (interval $a $t) $x (loop $i (2, minSup)@@ -84,7 +84,7 @@ !(first (interval #a _) #x _)) -> (a, t, x) -first := \pt px ps =>+def first := \pt px ps => {@ ++ (@ ++ (@ ++ ((interval $t _ & ~pt), _ ++ ($x & ~px) :: _) :: _) :: _) :: @, (!(_ ++ (_ ++ (_ ++ (interval #t _, _ ++ #x :: _) :: _) :: _) :: _), !(_ ++ (_ ++ (interval #t _, _ ++ #x :: _) :: _) :: _),
+ sample/graph.egi view
@@ -0,0 +1,60 @@+--+--+-- Graph demonstration+--+--++--+-- Matcher definition+--+def graph $a := set (edge a)++def edge $a :=+ algebraicDataMatcher+ | edge a a++--+-- Sample data+--+def graphData1 :=+ [Edge 1 4, Edge 2 1, Edge 3 1, Edge 3 2, Edge 4 3, Edge 5 1, Edge 5 4]++def graphData2 :=+ [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 edge from 's' but not have an edge to 's'+let s := 1+ in matchAll graphData1 as graph integer with+ | edge #s $x :: !(edge #x #s :: _) -> x++-- find all nodes in two paths from 's'+let s := 1+ in matchAll graphData1 as graph integer with+ | edge (#s & $x_1) $x_2 :: edge #x_2 $x_3 :: _ -> x++-- enumerate first 5 paths from 's' to 'e'+take+ 5+ (let s := 1+ e := 2+ in matchAll graphData2 as graph integer with+ | edge (#s & $x_1) $x_2 :: (loop $i (4, $n)+ (edge #x_(i - 2) $x_(i - 1) :: ...)+ (edge #x_(n - 1) (#e & $x_n) :: _)) -> x)++-- find all cliques whose size is 'n'+let n := 3+ in matchAll graphData2 as graph integer with+ | edge $x_1 $x_2 :: (loop $i (3, n, _)+ (edge #x_1 $x_i :: (loop $j (2, i - 1, _)+ (edge #x_j #x_i :: ...)+ ...))+ _) -> x
sample/ioRef.egi view
@@ -1,4 +1,4 @@-refTest x y :=+def refTest x y := do let w := newIORef () writeIORef w x let w1 := readIORef w@@ -8,4 +8,4 @@ print (show w2) flush () -main args := refTest 1 2+def main args := refTest 1 2
sample/mahjong.egi view
@@ -7,13 +7,13 @@ -- -- Matcher definitions ---suit :=+def suit := algebraicDataMatcher | wan | pin | sou -honor :=+def honor := algebraicDataMatcher | ton | nan@@ -23,7 +23,7 @@ | hatsu | chun -tile :=+def tile := algebraicDataMatcher | num suit integer | hnr honor@@ -31,18 +31,18 @@ -- -- Pattern modularization ---twin := \pat1 pat2 => ($pat & ~pat1) :: #pat :: ~pat2+def twin := \pat1 pat2 => ($pat & ~pat1) :: #pat :: ~pat2 -shuntsu :=+def shuntsu := \pat1 pat2 => (num $s $n & ~pat1) :: num #s #(n + 1) :: num #s #(n + 2) :: ~pat2 -kohtsu := \pat1 pat2 => ($pat & ~pat1) :: #pat :: #pat :: ~pat2+def kohtsu := \pat1 pat2 => ($pat & ~pat1) :: #pat :: #pat :: ~pat2 -- -- A function that determines whether the hand is completed or not. ---complete? :=+def complete? := \match as multiset tile with | twin $th_1
sample/math/geometry/curvature-form.egi view
@@ -1,16 +1,16 @@ -- Parameters and metric tensor-x := [| θ, φ |]+def x := [| θ, φ |] -g_i_j := [| [| r^2, 0 |], [| 0, r^2 * (sin θ)^2 |] |]_i_j-g~i~j := [| [| 1 / r^2, 0 |], [| 0, 1 / (r^2 * (sin θ)^2) |] |]~i~j+def g_i_j := [| [| r^2, 0 |], [| 0, r^2 * (sin θ)^2 |] |]_i_j+def g~i~j := [| [| 1 / r^2, 0 |], [| 0, 1 / (r^2 * (sin θ)^2) |] |]~i~j -- Christoffel symbols-Γ_j_l_k := (1 / 2) * (∂/∂ g_j_l x~k + ∂/∂ g_j_k x~l - ∂/∂ g_k_l x~j)+def Γ_j_l_k := (1 / 2) * (∂/∂ g_j_l x~k + ∂/∂ g_j_k x~l - ∂/∂ g_k_l x~j) -Γ~i_k_l := withSymbols [j] g~i~j . Γ_j_l_k+def Γ~i_k_l := withSymbols [j] g~i~j . Γ_j_l_k -- Riemann curvature-R~i_j_k_l := withSymbols [m]+def R~i_j_k_l := withSymbols [m] ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l assertEqual "Riemann curvature" R~#_#_1_1 [| [| 0, 0 |], [| 0, 0 |] |]~#_#@@ -19,18 +19,18 @@ assertEqual "Riemann curvature" R~#_#_2_2 [| [| 0, 0 |], [| 0, 0 |] |]~#_# -- Exterior derivative-d %t := !(flip ∂/∂) x t+def d %t := !(flip ∂/∂) x t -- Wedge product infixl expression 7 ∧ -(∧) %x %y := x !. y+def (∧) %x %y := x !. y -- Connection form-ω~i_j := Γ~i_j_#+def ω~i_j := Γ~i_j_# -- Curvature form-Ω~i_j := withSymbols [k]+def Ω~i_j := withSymbols [k] antisymmetrize (d ω~i_j + ω~i_k ∧ ω~k_j) assertEqual "Curvature form" Ω~#_#_1_1 [| [| 0, 0 |], [| 0, 0 |] |]~#_#
sample/math/geometry/hodge-laplacian-polar.egi view
@@ -1,34 +1,34 @@ -- Parameters and metrics -N := 2+def N := 2 -x := [|r, θ|]+def x := [|r, θ|] -g_i_j := [| [| 1, 0 |], [| 0, r^2 |] |]_i_j-g~i~j := [| [| 1, 0 |], [| 0, 1 / r^2 |] |]~i~j+def g_i_j := [| [| 1, 0 |], [| 0, r^2 |] |]_i_j+def g~i~j := [| [| 1, 0 |], [| 0, 1 / r^2 |] |]~i~j -- Hodge Laplacian -d %A := !(flip ∂/∂) x A+def d %A := !(flip ∂/∂) x A -hodge %A :=+def hodge %A := let k := dfOrder A in withSymbols [i, j] (sqrt (abs (M.det g_#_#))) * (foldl (.) ((ε' N k)_(i_1)..._(i_N) . A..._(j_1)..._(j_k)) (map 1#g~(i_%1)~(j_%1) [1..k])) -δ %A :=+def δ %A := let k := dfOrder A in -1^(N * (k + 1) + 1) * (hodge (d (hodge A))) -Δ %A :=+def Δ %A := match (dfOrder A) as integer with | #0 -> δ (d A) | #N -> d (δ A) | _ -> d (δ A) + δ (d A) -f := function (r, θ)+def f := function (r, θ) assertEqual "exterior derivative" (d f) [| ∂/∂ f r, ∂/∂ f θ |]
sample/math/geometry/riemann-curvature-tensor-of-S2.egi view
@@ -1,16 +1,16 @@ -- Parameters-x := [| θ, φ |]+def x := [| θ, φ |] -X := [| r * sin θ * cos φ -- x- , r * sin θ * sin φ -- y- , r * cos θ -- z- |]+def X := [| r * sin θ * cos φ -- x+ , r * sin θ * sin φ -- y+ , r * cos θ -- z+ |] -e_i_j := ∂/∂ X_j x~i+def e_i_j := ∂/∂ X_j x~i -- Metric tensors-g_i_j := generateTensor (\x y -> V.* e_x_# e_y_#) [2, 2]-g~i~j := M.inverse g_#_#+def g_i_j := generateTensor (\x y -> V.* e_x_# e_y_#) [2, 2]+def g~i~j := M.inverse g_#_# assertEqual "Metric tensor" g_#_#@@ -20,7 +20,7 @@ [| [| 1 / r^2, 0 |], [| 0, 1 / (r^2 * (sin θ)^2) |] |]~#~# -- Christoffel symbols-Γ_i_j_k := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i)+def Γ_i_j_k := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i) assertEqual "Christoffel symbols of the first kind" Γ_1_#_#@@ -29,7 +29,7 @@ Γ_2_#_# [| [| 0, r^2 * (sin θ) * (cos θ) |], [| r^2 * (sin θ) * (cos θ), 0 |] |]_#_# -Γ~i_j_k := withSymbols [m]+def Γ~i_j_k := withSymbols [m] g~i~m . Γ_m_j_k assertEqual "Christoffel symbols of the second kind"@@ -40,7 +40,7 @@ [| [| 0, (cos θ) / (sin θ) |], [| (cos θ) / (sin θ), 0 |] |]_#_# -- Riemann curvature-R~i_j_k_l := withSymbols [m]+def R~i_j_k_l := withSymbols [m] ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l assertEqual "riemann curvature"@@ -57,11 +57,11 @@ [| [| 0, 0 |], [| 0, 0 |] |]~#_# -- Ricci curvature-Ric_i_j := withSymbols [m]+def Ric_i_j := withSymbols [m] sum (contract R~m_i_m_j) -- Scalar curvature-scalarCurvature := withSymbols [i, j]+def scalarCurvature := withSymbols [i, j] g~i~j . Ric_i_j assertEqual "scalar curvature"
+ sample/math/geometry/riemann-curvature-tensor-of-S5-non-sym.egi view
@@ -0,0 +1,54 @@+-- Parameters+def x := [|θ, φ, ψ, η, δ|]++def X := [| r * (cos θ),+ r * (sin θ) * (cos φ),+ r * (sin θ) * (sin φ) * (cos ψ),+ r * (sin θ) * (sin φ) * (sin ψ) * (cos η),+ r * (sin θ) * (sin φ) * (sin ψ) * (sin η) * (cos δ),+ r * (sin θ) * (sin φ) * (sin ψ) * (sin η) * (sin δ) |]++-- Local basis+def e_i_j := ∂/∂ X_j x~i++-- Metric tensors+def g_i_j := generateTensor (\x y -> V.* e_x_# e_y_#) [5, 5]+def g~i~j := M.inverse g_#_#++-- Christoffel symbols+def Γ_i_j_k := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i)++def Γ~i_j_k := withSymbols [m]+ g~i~m . Γ_m_j_k++-- Riemann curvature+def R~i_j_k_l := withSymbols [m]+ ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l++--R~#_#_#_#++--def R_a_b_c_d := withSymbols [i] g_a_i . R~i_b_c_d++-- Ricci curvature+def Ric_a_b := withSymbols [m, n]+ sum (contract (R~m_a_m_b))++Ric_#_#++-- Scalar curvature+def scalarCurvature := withSymbols [i, j]+ g~i~j . Ric_i_j++-- Conformal curvature tensor+def C_i_k_l_m := R_i_k_l_m ++ (Ric_i_m . g_k_l - Ric_i_l . g_k_m + Ric_k_l . g_i_m - Ric_k_m . g_i_l) ++ (scalarCurvature / 2) * (g_i_l . g_k_m - g_i_m . g_k_l)+--C_#_#_#_#++-- Wodzicki-Chern-Simons class+def S :=+ let (es, os) := evenAndOddPermutations 5 in+ sum (map (\σ -> R~u_1_s_(σ 1) . R~s_t_(σ 3)_(σ 2) . R~t_u_(σ 5)_(σ 4)) es) -+ sum (map (\σ -> R~u_1_s_(σ 1) . R~s_t_(σ 3)_(σ 2) . R~t_u_(σ 5)_(σ 4)) os)++--S
+ sample/math/geometry/riemann-curvature-tensor-of-S5.egi view
@@ -0,0 +1,54 @@+-- Parameters+def x := [|θ, φ, ψ, η, δ|]++def X := [| r * (cos θ),+ r * (sin θ) * (cos φ),+ r * (sin θ) * (sin φ) * (cos ψ),+ r * (sin θ) * (sin φ) * (sin ψ) * (cos η),+ r * (sin θ) * (sin φ) * (sin ψ) * (sin η) * (cos δ),+ r * (sin θ) * (sin φ) * (sin ψ) * (sin η) * (sin δ) |]++-- Local basis+def e_i_j := ∂/∂ X_j x~i++-- Metric tensors+def g{_i_j} := generateTensor (\x y -> V.* e_x_# e_y_#) [5, 5]+def g{~i~j} := M.inverse g_#_#++-- Christoffel symbols+def Γ_i[_j_k] := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i)++def Γ~i[_j_k] := withSymbols [m]+ g~i~m . Γ_m_j_k++-- Riemann curvature+def R~i_j[_k_l] := withSymbols [m]+ ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l++--R~#_#_#_#++--def R{[_a_b][_c_d]} := withSymbols [i] g_a_i . R~i_b_c_d++-- Ricci curvature+def Ric[_a_b] := withSymbols [m, n]+ sum (contract (R~m_a_m_b))++Ric_#_# -- 7.422 sec++-- Scalar curvature+def scalarCurvature := withSymbols [i, j]+ g~i~j . Ric_i_j++-- Conformal curvature tensor+def C_i_k_l_m := R_i_k_l_m ++ (Ric_i_m . g_k_l - Ric_i_l . g_k_m + Ric_k_l . g_i_m - Ric_k_m . g_i_l) ++ (scalarCurvature / 2) * (g_i_l . g_k_m - g_i_m . g_k_l)+--C_#_#_#_#++-- Wodzicki-Chern-Simons class+def S :=+ let (es, os) := evenAndOddPermutations 5 in+ sum (map (\σ -> R~u_1_s_(σ 1) . R~s_t_(σ 3)_(σ 2) . R~t_u_(σ 5)_(σ 4)) es) -+ sum (map (\σ -> R~u_1_s_(σ 1) . R~s_t_(σ 3)_(σ 2) . R~t_u_(σ 5)_(σ 4)) os)++--S -- 0 -- 16.957 sec
+ sample/math/geometry/riemann-curvature-tensor-of-T2-non-sym.egi view
@@ -0,0 +1,85 @@+-- Parameters+def x := [| θ, φ |]++def X := [| '(a * cos θ + b) * cos φ -- x+ , '(a * cos θ + b) * sin φ -- y+ , a * sin θ -- z+ |]++def e_i_j := ∂/∂ X_j x~i++-- Metric tensors+def g_i_j := generateTensor (\x y -> V.* e_x_# e_y_#) [2, 2]+def g~i~j := M.inverse g_#_#++assertEqual "Metric tensor"+ g_#_#+ [| [| a^2, 0 |], [| 0, '(a * cos θ + b)^2 |] |]_#_#+assertEqual "Metric tensor"+ g~#~#+ [| [| 1 / a^2, 0 |], [| 0, 1 / '(a * cos θ + b)^2 |] |]~#~#++-- Christoffel symbols+def Γ_i_j_k := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i)++assertEqual "Christoffel symbols of the first kind"+ Γ_1_#_#+ [| [| 0, 0 |], [| 0, '(a * cos θ + b) * a * sin θ |] |]_#_#+assertEqual "Christoffel symbols of the first kind"+ Γ_2_#_#+ [| [| 0, -1 * '(a * cos θ + b) * a * sin θ |], [| -1 * '(a * cos θ + b) * a * sin θ, 0 |] |]_#_#++def Γ~i_j_k := withSymbols [m]+ g~i~m . Γ_m_j_k++assertEqual "Christoffel symbols of the second kind"+ Γ~1_#_#+ [| [| 0, 0 |], [| 0, '(a * cos θ + b) * sin θ / a |] |]_#_#+assertEqual "Christoffel symbols of the second kind"+ Γ~2_#_#+ [| [| 0, -1 * a * sin θ / '(a * cos θ + b) |], [| -1 * a * sin θ / '(a * cos θ + b), 0 |] |]_#_#++-- Riemann curvature+def R~i_j_k_l := withSymbols [m]+ ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l++assertEqual "riemann curvature"+ R~#_#_1_1+ [| [| 0, 0 |], [| 0, 0 |] |]~#_#+assertEqual "riemann curvature"+ R~#_#_1_2+ [| [| 0, '(a * cos θ + b) * cos θ / a |], [| -1 * a * cos θ / '(a * cos θ + b), 0 |] |]~#_#+assertEqual "riemann curvature"+ R~#_#_2_1+ [| [| 0, -1 * '(a * cos θ + b) * cos θ / a |], [| a * cos θ / '(a * cos θ + b), 0 |] |]~#_#+assertEqual "riemann curvature"+ R~#_#_2_2+ [| [| 0, 0 |], [| 0, 0 |] |]~#_#++-- Riemann curvature 2+def R_i_j_k_l := withSymbols [m] g_i_m . R~m_j_k_l++assertEqual "riemann curvature"+ R_#_#_1_1+ [| [| 0, 0 |], [| 0, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_1_2+ [| [| 0, a * '(a * cos θ + b) * cos θ |], [| - '(a * cos θ + b) * a * cos θ, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_2_1+ [| [| 0, - a * '(a * cos θ + b) * cos θ |], [| '(a * cos θ + b) * a * cos θ, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_2_2+ [| [| 0, 0 |], [| 0, 0 |] |]_#_#++-- Ricci curvature+def Ric_i_j := withSymbols [m]+ sum (contract R~m_i_m_j)++-- Scalar curvature+def scalarCurvature := withSymbols [i, j]+ g~i~j . Ric_i_j++assertEqual "scalar curvature"+ scalarCurvature+ (2 * cos θ / (a * '(a * cos θ + b)))
sample/math/geometry/riemann-curvature-tensor-of-T2.egi view
@@ -1,16 +1,16 @@ -- Parameters-x := [| θ, φ |]+def x := [| θ, φ |] -X := [| '(a * cos θ + b) * cos φ -- x- , '(a * cos θ + b) * sin φ -- y- , a * sin θ -- z- |]+def X := [| '(a * cos θ + b) * cos φ -- x+ , '(a * cos θ + b) * sin φ -- y+ , a * sin θ -- z+ |] -e_i_j := ∂/∂ X_j x~i+def e_i_j := ∂/∂ X_j x~i -- Metric tensors-g_i_j := generateTensor (\x y -> V.* e_x_# e_y_#) [2, 2]-g~i~j := M.inverse g_#_#+def g{_i_j} := generateTensor (\x y -> V.* e_x_# e_y_#) [2, 2]+def g{~i~j} := M.inverse g_#_# assertEqual "Metric tensor" g_#_#@@ -20,7 +20,7 @@ [| [| 1 / a^2, 0 |], [| 0, 1 / '(a * cos θ + b)^2 |] |]~#~# -- Christoffel symbols-Γ_i_j_k := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i)+def Γ_i{_j_k} := (1 / 2) * (∂/∂ g_i_k x~j + ∂/∂ g_i_j x~k - ∂/∂ g_j_k x~i) assertEqual "Christoffel symbols of the first kind" Γ_1_#_#@@ -29,7 +29,7 @@ Γ_2_#_# [| [| 0, -1 * '(a * cos θ + b) * a * sin θ |], [| -1 * '(a * cos θ + b) * a * sin θ, 0 |] |]_#_# -Γ~i_j_k := withSymbols [m]+def Γ~i{_j_k} := withSymbols [m] g~i~m . Γ_m_j_k assertEqual "Christoffel symbols of the second kind"@@ -40,7 +40,7 @@ [| [| 0, -1 * a * sin θ / '(a * cos θ + b) |], [| -1 * a * sin θ / '(a * cos θ + b), 0 |] |]_#_# -- Riemann curvature-R~i_j_k_l := withSymbols [m]+def R~i_j_k_l := withSymbols [m] ∂/∂ Γ~i_j_l x~k - ∂/∂ Γ~i_j_k x~l + Γ~m_j_l . Γ~i_m_k - Γ~m_j_k . Γ~i_m_l assertEqual "riemann curvature"@@ -56,12 +56,28 @@ R~#_#_2_2 [| [| 0, 0 |], [| 0, 0 |] |]~#_# +-- Riemann curvature 2+def R{[_i_j][_k_l]} := withSymbols [m] g_i_m . R~m_j_k_l++assertEqual "riemann curvature"+ R_#_#_1_1+ [| [| 0, 0 |], [| 0, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_1_2+ [| [| 0, a * '(a * cos θ + b) * cos θ |], [| - '(a * cos θ + b) * a * cos θ, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_2_1+ [| [| 0, - a * '(a * cos θ + b) * cos θ |], [| '(a * cos θ + b) * a * cos θ, 0 |] |]_#_#+assertEqual "riemann curvature"+ R_#_#_2_2+ [| [| 0, 0 |], [| 0, 0 |] |]_#_#+ -- Ricci curvature-Ric_i_j := withSymbols [m]+def Ric[_i_j] := withSymbols [m] sum (contract R~m_i_m_j) -- Scalar curvature-scalarCurvature := withSymbols [i, j]+def scalarCurvature := withSymbols [i, j] g~i~j . Ric_i_j assertEqual "scalar curvature"
+ sample/math/geometry/thurston-non-sym.egi view
@@ -0,0 +1,89 @@+---+--- Calculation of the WCS Invariant on the Thurston Example (Section 4)+---++def x~i := [| θ₁, θ₂, θ₃, θ₄ |]~i++def g_i_j :=+ [|[| 1, 0, 0, 0 |],+ [| 0, 1, 0, 0 |],+ [| 0, 0, κ / (sqrt β), (-1 * θ₂ * κ) / (sqrt β) |],+ [| 0, 0, (-1 * θ₂ * κ) / (sqrt β), ('(1 + θ₂) * κ) / (sqrt β) |]|]++def g~i~j :=+ [|[| 1, 0, 0, 0 |],+ [| 0, 1, 0, 0 |],+ [| 0, 0, '(1 + θ₂) / (κ * (sqrt β)), θ₂ / ((sqrt β) * κ) |],+ [| 0, 0, θ₂ / ((sqrt β) * κ), 1 / ((sqrt β) * κ) |]|]++def β := '(1 + θ₂ - θ₂^2)++def Γ~c_a_b := withSymbols [e]+ (1 / 2) * g~c~e . (∂/∂ g_b_e x~a + ∂/∂ g_a_e x~b - ∂/∂ g_a_b x~e)++def R_i_j_k~l := withSymbols [a]+ ∂/∂ Γ~l_j_k x~i - ∂/∂ Γ~l_i_k x~j + Γ~l_i_a . Γ~a_j_k - Γ~l_j_a . Γ~a_i_k++def R_i_j_k_l := withSymbols [a] R_i_j_k~a . g_a_l++def J_a_b :=+ [|[| 0, 1, 0, 0 |],+ [| -1, 0, 0, 0 |],+ [| 0, 0, 0, κ |],+ [| 0, 0, -1 * κ, 0 |]|]++def J_a~c := J_a_b . g~b~c++def ∇J_m_a_b :=+ withSymbols [n]+ ∂/∂ J_a_b x~m + Γ~n_m_a . J_n_b + Γ~n_m_b . J_a_n++def ∇J~m_a_b :=+ withSymbols [t]+ ∇J_t_a_b . g~t~m++def ∇J_m~a_b :=+ withSymbols [t]+ ∇J_m_t_b . g~t~a++def ∇J_m_a~b :=+ withSymbols [t]+ ∇J_m_a_t . g~t~b++def δ :=+ generateTensor+ (\x y -> match (x, y) as (integer, integer) with+ | ($n, #n) -> 1+ | (_, _) -> 0)+ [5, 5]++def R'_i_j_k~l :=+ generateTensor+ (\x y z w -> match (x, y, z, w) as (integer, integer, integer, integer) with+ | (#1, #1, _, _) -> 0+ | (_, _, #1, #1) -> 0+ | (#1, $b, #1, $d) -> -1 * p^2 * δ~(b - 1)_(d - 1)+ | ($a, #1, #1, $d) -> p^2 * δ~(a - 1)_(d - 1)+ | (#1, $b, $c, #1) -> p^2 * g_(b - 1)_(c - 1)+ | ($a, #1, $c, #1) -> -1 * p^2 * g_(a - 1)_(c - 1)+ | (#1, $b, $c, $d) -> -1 * p * ∇J_(b - 1)_(c - 1)~(d - 1)+ | ($a, #1, $c, $d) -> p * ∇J_(a - 1)_(c - 1)~(d - 1)+ | ($a, $b, #1, $d) -> -1 * p * ∇J~(d - 1)_(a - 1)_(b - 1)+ | ($a, $b, $c, #1) -> p * ∇J_(c - 1)_(a - 1)_(b - 1)+ | ($a, $b, $c, $d) -> R_(a - 1)_(b - 1)_(c - 1)~(d - 1)+ + -1 * p^2 * J_(b - 1)_(c - 1) * J_(a - 1)~(d - 1)+ + p^2 * J_(a - 1)_(c - 1) * J_(b - 1)~(d - 1)+ + 2 * p^2 * J_(a - 1)_(b - 1) * J_(c - 1)~(d - 1))+ [5, 5, 5, 5]++def S :=+ withSymbols [i, j, k]+ let (es, os) := evenAndOddPermutations 5 in+ sum (map (\$σ -> R'_(σ 1)_j_1~i . R'_(σ 2)_(σ 3)_k~j . R'_(σ 4)_(σ 5)_i~k) es) -+ sum (map (\$σ -> R'_(σ 1)_j_1~i . R'_(σ 2)_(σ 3)_k~j . R'_(σ 4)_(σ 5)_i~k) os)++S+-- After 10 seconds calculation, we can get the following result:+-- (1536 p^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^16 - 1536 p^6 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^14 - 576 p^4 (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^12 + 1536 p^6 (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^14 + 8 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^3 θ₂^2 κ - 88 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 48 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 12 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^2 θ₂^4 κ - 24 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 + 288 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 - 160 p^2 (1 - 2 θ₂) (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ + 128 p^2 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 48 p^2 (1 - 2 θ₂)^3 (1 + θ₂) θ₂^5 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 80 p^2 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 768 p^4 (1 - 2 θ₂) (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ + 8 p^2 (1 - 2 θ₂)^4 (1 + θ₂) θ₂^6 κ + 24 p^2 (1 - 2 θ₂)^3 (1 + θ₂) θ₂^4 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 - 288 p^4 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^4 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 + 112 p^2 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 κ + 20 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^2 κ - 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^4 κ + 96 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^5 (1 - 2 θ₂) κ - 56 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^6 (1 - 2 θ₂)^2 κ - 80 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^4 (1 - 2 θ₂) κ + 384 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^4 κ + 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂^7 (1 - 2 θ₂)^3 κ + 40 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^5 (1 - 2 θ₂)^2 κ - 384 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^5 (1 - 2 θ₂) κ + 32 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^3 κ + 24 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^3 (1 - 2 θ₂) κ - 448 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^3 κ - 2 p^2 (1 - 2 θ₂)^4 θ₂^8 κ - 8 p^2 (1 - 2 θ₂)^3 θ₂^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 + 96 p^4 (1 - 2 θ₂)^2 θ₂^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 - 10 p^2 (1 - 2 θ₂)^2 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 16 p^2 (1 + θ₂)^3 (1 - 2 θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂ κ + 64 p^2 (1 + θ₂)^2 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ κ + 40 p^2 (1 + θ₂)^2 (1 - 2 θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂ κ - 384 p^4 (1 + θ₂)^2 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 κ θ₂ + 96 p^2 (1 + θ₂) θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ - 32 p^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂ κ - 24 p^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ (1 - 2 θ₂) κ + 448 p^4 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^10 κ θ₂ - 32 p^2 (1 - 2 θ₂) (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 10 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 8 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ + 16 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^3 κ Sqrt[(1 + θ₂ - θ₂^2)]^4 - 2 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^4 κ - 96 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^3 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 + 4 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 (1 + θ₂) (1 - 2 θ₂) κ + 8 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 (1 + θ₂) κ - 112 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 + θ₂) - 8 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^2 κ - 4 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 (1 - 2 θ₂) κ + 112 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^2 κ - 48 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ κ + 40 p^2 (1 - 2 θ₂)^3 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^2 κ + 12 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 20 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 112 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 κ + 32 p^2 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 κ - 32 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ + 40 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂ κ - 21 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂^2 κ + 7 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 80 p^2 (1 - 2 θ₂)^3 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^3 κ + 21 p^2 (1 - 2 θ₂)^4 (1 + θ₂) θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 32 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^2 (1 - 2 θ₂) κ + 48 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^3 (1 - 2 θ₂)^2 κ - 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^2 κ + 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^3 (1 - 2 θ₂) κ - 80 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^4 (1 - 2 θ₂)^2 κ + 40 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^5 (1 - 2 θ₂)^3 κ - 20 p^2 (1 - 2 θ₂)^3 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 12 p^2 (1 - 2 θ₂)^2 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 7 p^2 (1 - 2 θ₂)^4 θ₂^6 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 64 p^4 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ - 32 p^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ + 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 (1 + θ₂) κ - 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 (1 - 2 θ₂) θ₂ (1 + θ₂) κ + 576 p^4 θ₂ Sqrt[(1 + θ₂ - θ₂^2)]^12 κ - 144 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^12 κ - 224 p^4 (1 - 2 θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^10 (1 + θ₂) - 384 p^4 κ (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^12 θ₂ + 224 p^4 (1 - 2 θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^10 + 192 p^4 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^12 κ + 128 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^14 κ - 320 p^4 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 + θ₂) + 128 p^4 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^10 κ - 128 p^4 θ₂^2 (1 - 2 θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^10 + 192 p^4 (1 + θ₂)^2 (1 - 2 θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^8 - 384 p^4 θ₂^2 (1 - 2 θ₂) (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^8 + 192 p^4 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ (1 - 2 θ₂) - 256 p^4 θ₂ Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 - 2 θ₂) (1 + θ₂) + 256 p^4 θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 - 2 θ₂) + 128 p^4 θ₂^2 (1 - 2 θ₂)^2 κ (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 - 64 p^4 θ₂^4 (1 - 2 θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^8 - 64 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^8)/(16 Sqrt[(1 + θ₂ - θ₂^2)]^16)+-- The above result is simplified using the Wolfam language as follows:+-- (p^2 (-25 - 640 p^2 (1 + θ₂- θ₂^2)^2 + 3072 p^4 (1 + θ₂ - θ₂^2)^4) κ) / (16 (1 + θ₂ - θ₂^2)^4)
+ sample/math/geometry/thurston.egi view
@@ -0,0 +1,89 @@+---+--- Calculation of the WCS Invariant on the Thurston Example (Section 4)+---++def x~i := [| θ₁, θ₂, θ₃, θ₄ |]~i++def g_i_j :=+ [|[| 1, 0, 0, 0 |],+ [| 0, 1, 0, 0 |],+ [| 0, 0, κ / (sqrt β), (-1 * θ₂ * κ) / (sqrt β) |],+ [| 0, 0, (-1 * θ₂ * κ) / (sqrt β), ('(1 + θ₂) * κ) / (sqrt β) |]|]++def g~i~j :=+ [|[| 1, 0, 0, 0 |],+ [| 0, 1, 0, 0 |],+ [| 0, 0, '(1 + θ₂) / (κ * (sqrt β)), θ₂ / ((sqrt β) * κ) |],+ [| 0, 0, θ₂ / ((sqrt β) * κ), 1 / ((sqrt β) * κ) |]|]++def β := '(1 + θ₂ - θ₂^2)++def Γ~c_a_b := withSymbols [e]+ (1 / 2) * g~c~e . (∂/∂ g_b_e x~a + ∂/∂ g_a_e x~b - ∂/∂ g_a_b x~e)++def R_i_j_k~l := withSymbols [a]+ ∂/∂ Γ~l_j_k x~i - ∂/∂ Γ~l_i_k x~j + Γ~l_i_a . Γ~a_j_k - Γ~l_j_a . Γ~a_i_k++def R_i_j_k_l := withSymbols [a] R_i_j_k~a . g_a_l++def J_a_b :=+ [|[| 0, 1, 0, 0 |],+ [| -1, 0, 0, 0 |],+ [| 0, 0, 0, κ |],+ [| 0, 0, -1 * κ, 0 |]|]++def J_a~c := J_a_b . g~b~c++def ∇J_m_a_b :=+ withSymbols [n]+ ∂/∂ J_a_b x~m + Γ~n_m_a . J_n_b + Γ~n_m_b . J_a_n++def ∇J~m_a_b :=+ withSymbols [t]+ ∇J_t_a_b . g~t~m++def ∇J_m~a_b :=+ withSymbols [t]+ ∇J_m_t_b . g~t~a++def ∇J_m_a~b :=+ withSymbols [t]+ ∇J_m_a_t . g~t~b++def δ :=+ generateTensor+ (\x y -> match (x, y) as (integer, integer) with+ | ($n, #n) -> 1+ | (_, _) -> 0)+ [5, 5]++def R'[_i_j]_k~l :=+ generateTensor+ (\x y z w -> match (x, y, z, w) as (integer, integer, integer, integer) with+ | (#1, #1, _, _) -> 0+ | (_, _, #1, #1) -> 0+ | (#1, $b, #1, $d) -> -1 * p^2 * δ~(b - 1)_(d - 1)+ | ($a, #1, #1, $d) -> p^2 * δ~(a - 1)_(d - 1)+ | (#1, $b, $c, #1) -> p^2 * g_(b - 1)_(c - 1)+ | ($a, #1, $c, #1) -> -1 * p^2 * g_(a - 1)_(c - 1)+ | (#1, $b, $c, $d) -> -1 * p * ∇J_(b - 1)_(c - 1)~(d - 1)+ | ($a, #1, $c, $d) -> p * ∇J_(a - 1)_(c - 1)~(d - 1)+ | ($a, $b, #1, $d) -> -1 * p * ∇J~(d - 1)_(a - 1)_(b - 1)+ | ($a, $b, $c, #1) -> p * ∇J_(c - 1)_(a - 1)_(b - 1)+ | ($a, $b, $c, $d) -> R_(a - 1)_(b - 1)_(c - 1)~(d - 1)+ + -1 * p^2 * J_(b - 1)_(c - 1) * J_(a - 1)~(d - 1)+ + p^2 * J_(a - 1)_(c - 1) * J_(b - 1)~(d - 1)+ + 2 * p^2 * J_(a - 1)_(b - 1) * J_(c - 1)~(d - 1))+ [5, 5, 5, 5]++def S :=+ withSymbols [i, j, k]+ let (es, os) := evenAndOddPermutations 5 in+ sum (map (\$σ -> R'_(σ 1)_j_1~i . R'_(σ 2)_(σ 3)_k~j . R'_(σ 4)_(σ 5)_i~k) es) -+ sum (map (\$σ -> R'_(σ 1)_j_1~i . R'_(σ 2)_(σ 3)_k~j . R'_(σ 4)_(σ 5)_i~k) os)++S+-- After 10 seconds calculation, we can get the following result:+-- (1536 p^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^16 - 1536 p^6 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^14 - 576 p^4 (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^12 + 1536 p^6 (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^14 + 8 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^3 θ₂^2 κ - 88 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 48 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 12 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^2 θ₂^4 κ - 24 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 + 288 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 - 160 p^2 (1 - 2 θ₂) (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ + 128 p^2 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 48 p^2 (1 - 2 θ₂)^3 (1 + θ₂) θ₂^5 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 80 p^2 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 768 p^4 (1 - 2 θ₂) (1 + θ₂) θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ + 8 p^2 (1 - 2 θ₂)^4 (1 + θ₂) θ₂^6 κ + 24 p^2 (1 - 2 θ₂)^3 (1 + θ₂) θ₂^4 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 - 288 p^4 (1 - 2 θ₂)^2 (1 + θ₂) θ₂^4 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 + 112 p^2 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 κ + 20 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^2 κ - 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^4 κ + 96 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^5 (1 - 2 θ₂) κ - 56 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^6 (1 - 2 θ₂)^2 κ - 80 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^4 (1 - 2 θ₂) κ + 384 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^4 κ + 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂^7 (1 - 2 θ₂)^3 κ + 40 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^5 (1 - 2 θ₂)^2 κ - 384 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^5 (1 - 2 θ₂) κ + 32 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^3 κ + 24 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^3 (1 - 2 θ₂) κ - 448 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^3 κ - 2 p^2 (1 - 2 θ₂)^4 θ₂^8 κ - 8 p^2 (1 - 2 θ₂)^3 θ₂^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^2 + 96 p^4 (1 - 2 θ₂)^2 θ₂^6 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 - 10 p^2 (1 - 2 θ₂)^2 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 16 p^2 (1 + θ₂)^3 (1 - 2 θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂ κ + 64 p^2 (1 + θ₂)^2 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ κ + 40 p^2 (1 + θ₂)^2 (1 - 2 θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂ κ - 384 p^4 (1 + θ₂)^2 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 κ θ₂ + 96 p^2 (1 + θ₂) θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ - 32 p^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂ κ - 24 p^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ (1 - 2 θ₂) κ + 448 p^4 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^10 κ θ₂ - 32 p^2 (1 - 2 θ₂) (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 10 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 8 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ + 16 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^3 κ Sqrt[(1 + θ₂ - θ₂^2)]^4 - 2 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^4 κ - 96 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^3 κ Sqrt[(1 + θ₂ - θ₂^2)]^6 + 4 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 (1 + θ₂) (1 - 2 θ₂) κ + 8 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 (1 + θ₂) κ - 112 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 + θ₂) - 8 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^2 κ - 4 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 (1 - 2 θ₂) κ + 112 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^2 κ - 48 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂ κ + 40 p^2 (1 - 2 θ₂)^3 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^2 κ + 12 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 20 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ + 112 p^2 (1 - 2 θ₂)^2 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^2 κ + 32 p^2 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 κ - 32 p^2 (1 - 2 θ₂)^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ + 40 p^2 (1 - 2 θ₂)^3 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂ κ - 21 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^2 θ₂^2 κ + 7 p^2 (1 - 2 θ₂)^4 (1 + θ₂)^3 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 80 p^2 (1 - 2 θ₂)^3 (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^3 κ + 21 p^2 (1 - 2 θ₂)^4 (1 + θ₂) θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 32 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^2 (1 - 2 θ₂) κ + 48 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^3 (1 - 2 θ₂)^2 κ - 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 θ₂^2 κ + 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 θ₂^3 (1 - 2 θ₂) κ - 80 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 θ₂^4 (1 - 2 θ₂)^2 κ + 40 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^4 θ₂^5 (1 - 2 θ₂)^3 κ - 20 p^2 (1 - 2 θ₂)^3 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^4 κ - 12 p^2 (1 - 2 θ₂)^2 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^6 κ - 7 p^2 (1 - 2 θ₂)^4 θ₂^6 Sqrt[(1 + θ₂ - θ₂^2)]^2 κ - 64 p^4 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ - 32 p^2 (1 + θ₂)^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ + 16 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 (1 + θ₂) κ - 64 p^2 Sqrt[(1 + θ₂ - θ₂^2)]^8 (1 - 2 θ₂) θ₂ (1 + θ₂) κ + 576 p^4 θ₂ Sqrt[(1 + θ₂ - θ₂^2)]^12 κ - 144 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^12 κ - 224 p^4 (1 - 2 θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^10 (1 + θ₂) - 384 p^4 κ (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^12 θ₂ + 224 p^4 (1 - 2 θ₂)^2 θ₂^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^10 + 192 p^4 (1 - 2 θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^12 κ + 128 p^4 Sqrt[(1 + θ₂ - θ₂^2)]^14 κ - 320 p^4 θ₂^2 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 + θ₂) + 128 p^4 (1 - 2 θ₂) (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^10 κ - 128 p^4 θ₂^2 (1 - 2 θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^10 + 192 p^4 (1 + θ₂)^2 (1 - 2 θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^8 - 384 p^4 θ₂^2 (1 - 2 θ₂) (1 + θ₂) κ Sqrt[(1 + θ₂ - θ₂^2)]^8 + 192 p^4 θ₂^4 Sqrt[(1 + θ₂ - θ₂^2)]^8 κ (1 - 2 θ₂) - 256 p^4 θ₂ Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 - 2 θ₂) (1 + θ₂) + 256 p^4 θ₂^3 Sqrt[(1 + θ₂ - θ₂^2)]^10 κ (1 - 2 θ₂) + 128 p^4 θ₂^2 (1 - 2 θ₂)^2 κ (1 + θ₂) Sqrt[(1 + θ₂ - θ₂^2)]^8 - 64 p^4 θ₂^4 (1 - 2 θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^8 - 64 p^4 (1 - 2 θ₂)^2 (1 + θ₂)^2 κ Sqrt[(1 + θ₂ - θ₂^2)]^8)/(16 Sqrt[(1 + θ₂ - θ₂^2)]^16)+-- The above result is simplified using the Wolfam language as follows:+-- (p^2 (-25 - 640 p^2 (1 + θ₂- θ₂^2)^2 + 3072 p^4 (1 + θ₂ - θ₂^2)^4) κ) / (16 (1 + θ₂ - θ₂^2)^4)
sample/math/number/17th-root-of-unity.egi view
@@ -1,56 +1,56 @@-z := rtu 17+def z := rtu 17 -a1 := z ^ 1 + z ^ 16-a2 := z ^ 2 + z ^ 15-a3 := z ^ 3 + z ^ 14-a4 := z ^ 4 + z ^ 13-a5 := z ^ 5 + z ^ 12-a6 := z ^ 6 + z ^ 11-a7 := z ^ 7 + z ^ 10-a8 := z ^ 8 + z ^ 9+def a1 := z ^ 1 + z ^ 16+def a2 := z ^ 2 + z ^ 15+def a3 := z ^ 3 + z ^ 14+def a4 := z ^ 4 + z ^ 13+def a5 := z ^ 5 + z ^ 12+def a6 := z ^ 6 + z ^ 11+def a7 := z ^ 7 + z ^ 10+def a8 := z ^ 8 + z ^ 9 -b11 := a1 + a4-b12 := a1 - a4+def b11 := a1 + a4+def b12 := a1 - a4 -b21 := a2 + a8-b22 := a2 - a8+def b21 := a2 + a8+def b22 := a2 - a8 -b31 := a3 + a5-b32 := a3 - a5+def b31 := a3 + a5+def b32 := a3 - a5 -b41 := a6 + a7-b42 := a6 - a7+def b41 := a6 + a7+def b42 := a6 - a7 -c11 := b11 + b21-c12 := b11 - b21+def c11 := b11 + b21+def c12 := b11 - b21 -c21 := b31 + b41-c22 := b31 - b41+def c21 := b31 + b41+def c22 := b31 - b41 -d10 := c11 + c21-d11 := c11 - c21-d12 := c21 - c11+def d10 := c11 + c21+def d11 := c11 - c21+def d12 := c21 - c11 -d10' := -1+def d10' := -1 -d11' := sqrt 17+def d11' := sqrt 17 -c11' := (d10' + d11') / 2-c21' := (d10' - d11') / 2-c12' := sqrt (8 + (- c11'))-c22' := sqrt (8 + (- c21'))+def c11' := (d10' + d11') / 2+def c21' := (d10' - d11') / 2+def c12' := sqrt (8 + (- c11'))+def c22' := sqrt (8 + (- c21')) -b11' := (c11' + c12') / 2-b21' := (c11' - c12') / 2-b31' := (c21' + c22') / 2-b41' := (c21' - c22') / 2+def b11' := (c11' + c12') / 2+def b21' := (c11' - c12') / 2+def b31' := (c21' + c22') / 2+def b41' := (c21' - c22') / 2 -b12' := sqrt (4 + b21' + (-2) * b31')-b22' := sqrt (4 + b21' + (-2) * b41')-b32' := sqrt (4 + b41' + (-2) * b21')-b42' := sqrt (4 + b31' + (-2) * b21')+def b12' := sqrt (4 + b21' + (-2) * b31')+def b22' := sqrt (4 + b21' + (-2) * b41')+def b32' := sqrt (4 + b41' + (-2) * b21')+def b42' := sqrt (4 + b31' + (-2) * b21') -a1' := (b11' + b12') / 2+def a1' := (b11' + b12') / 2 assertEqual "17th-root-of-unity"
sample/math/number/tribonacci.egi view
@@ -1,8 +1,8 @@-m := 3+def m := 3 -A :=+def A := generateTensor- (\match as (integer, integer) with+ (\x y -> match (x, y) as (integer, integer) with | (#1, _) -> 1 | ($x, #(x - 1)) -> 1 | (_, _) -> 0)@@ -11,11 +11,9 @@ A -- [| [| 1, 1, 1 |], [| 1, 0, 0 |], [| 0, 1, 0 |] |] -B :=+def B := generateTensor- (\match as integer with- | #1 -> 1- | _ -> 0)+ (\x -> if x = 1 then 1 else 0) [m] B
sample/n-queens.egi view
@@ -1,29 +1,30 @@-fourQueens := matchAll [1,2,3,4] as multiset integer with-| $a_1 ::- (!#(a_1 - 1) & !#(a_1 + 1) & $a_2) ::- (!#(a_1 - 2) & !#(a_1 + 2) & !#(a_2 - 1) & !#(a_2 + 1) & $a_3) ::- (!#(a_1 - 3) & !#(a_1 + 3) & !#(a_2 - 2) & !#(a_2 + 2) & !#(a_3 - 1) & !#(a_3 + 1) & $a_4) ::- []- -> [a_1,a_2,a_3,a_4]+def fourQueens := matchAll [1,2,3,4] as multiset integer with+ | $a_1 ::+ (!#(a_1 - 1) & !#(a_1 + 1) & $a_2) ::+ (!#(a_1 - 2) & !#(a_1 + 2) & !#(a_2 - 1) & !#(a_2 + 1) & $a_3) ::+ (!#(a_1 - 3) & !#(a_1 + 3) & !#(a_2 - 2) & !#(a_2 + 2) & !#(a_3 - 1) & !#(a_3 + 1) & $a_4) ::+ []+ -> [a_1,a_2,a_3,a_4] fourQueens -- [[2,4,1,3],[3,1,4,2]] -nQueens n := matchAll [1..n] as multiset integer with-| $a_1 ::- (loop $i (2, n)- ((loop $j (1, i - 1)- (!#(a_j - (i - j)) & !#(a_j + (i - j)) & ...)- $a_i) :: ...)- [])--> map (\i -> a_i) [1..n]+def nQueens n := matchAll [1..n] as multiset integer with+ | $a_1 ::+ (loop $i (2, n)+ ((loop $j (1, i - 1)+ (!#(a_j - (i - j)) & !#(a_j + (i - j)) & ...)+ $a_i) :: ...)+ [])+ -> map (\i -> a_i) [1..n] nQueens 4 -- [[2,4,1,3],[3,1,4,2]] -fourQueens2 := matchAll [1,2,3,4] as multiset integer with-| $a_1 ::- (!#(a_1 - 1) & !#(a_1 + 1) & $a_2) ::- (!#(a_1 - 2) & !#(a_1 + 2) & !#(a_2 - 1) & !#(a_2 + 1) & $a_3) ::- (!#(a_1 - 3) & !#(a_1 + 3) & !#(a_2 - 2) & !#(a_2 + 2) & !#(a_3 - 1) & !#(a_3 + 1) & $a_4) ::- []- -> a+def fourQueens2 := matchAll [1,2,3,4] as multiset integer with+ | $a_1 ::+ (!#(a_1 - 1) & !#(a_1 + 1) & $a_2) ::+ (!#(a_1 - 2) & !#(a_1 + 2) & !#(a_2 - 1) & !#(a_2 + 1) & $a_3) ::+ (!#(a_1 - 3) & !#(a_1 + 3) & !#(a_2 - 2) & !#(a_2 + 2) & !#(a_3 - 1) & !#(a_3 + 1) & $a_4) ::+ []+ -> a+ fourQueens2
sample/poker-hands-with-joker.egi view
@@ -1,10 +1,10 @@-suit := algebraicDataMatcher+def suit := algebraicDataMatcher | spade | heart | club | diamond -card := matcher+def card := matcher | card $ $ as (suit, mod 13) with | Card $x $y -> [(x, y)] | Joker -> matchAll ([Spade, Heart, Club, Diamnond], [1..13]) as (set something, set something) with@@ -12,7 +12,7 @@ | $ as something with | $tgt -> [tgt] -poker cs :=+def poker cs := match cs as multiset card with | card $s $n :: card #s #(n-1) :: card #s #(n-2) :: card #s #(n-3) :: card #s #(n-4) :: _ -> "Straight flush"
sample/poker-hands.egi view
@@ -1,13 +1,13 @@-suit := algebraicDataMatcher+def suit := algebraicDataMatcher | spade | heart | club | diamond -card := algebraicDataMatcher+def card := algebraicDataMatcher | card suit (mod 13) -poker cs :=+def poker cs := match cs as multiset card with | [card $s $n, card #s #(n-1), card #s #(n-2), card #s #(n-3), card #s #(n-4)] -> "Straight flush"
sample/primes.egi view
@@ -5,7 +5,7 @@ -- -- Extract all twin primes from the infinite list of prime numbers with pattern-matching!-twinPrimes :=+def twinPrimes := matchAll primes as list integer with | _ ++ $p :: #(p + 2) :: _ -> (p, p + 2) @@ -24,7 +24,7 @@ , (107, 109) ] -- Extract all prime-triplets from the infinite list of prime numbers with pattern-matching!-primeTriplets :=+def primeTriplets := matchAll primes as list integer with | _ ++ $p :: ($m & (#(p + 2) | #(p + 4))) :: #(p + 6) :: _ -> (p, m, p + 6)
sample/sat/cdcl.egi view
@@ -1,10 +1,10 @@-literal := integer+def literal := integer -stage := integer+def stage := integer -taggedLiteral := (literal, stage)+def taggedLiteral := (literal, stage) -assignment :=+def assignment := matcher | deduced $ $ as (taggedLiteral, multiset taggedLiteral) with | Deduced $e $es -> [(e, es)]@@ -21,55 +21,55 @@ -- Data structure for CNF -toCnf cs := map (\c -> (c, c)) cs+def toCnf cs := map (\c -> (c, c)) cs -fromCnf cs := map 2#%1 cs+def fromCnf cs := map fst cs -- VSIDS -initVars vs := map (\v -> (neg v, 0)) vs ++ map (\v -> (v, 0)) vs+def initVars vs := map (\v -> (neg v, 0)) vs ++ map (\v -> (v, 0)) vs -addVars vs vars :=+def addVars vs vars := matchDFS (vs, vars) as (list literal, list (literal, integer)) with- | ([], _) -> sort/fn (\xc yc -> compare (2#%2 yc) (2#%2 xc)) vars+ | ([], _) -> sort/fn (\xc yc -> compare (snd yc) (snd xc)) vars | ($v :: $vs', $hs ++ (#v, $c) :: $ts) -> addVars vs' (hs ++ (v, c + 1) :: ts) -deleteVar v vars :=+def deleteVar v vars := matchDFS vars as multiset (literal, integer) with | (#v, _) :: (#(neg v), _) :: $vars' -> vars2 | _ -> "error: not matched in delete-var" -- Utility functions for literlas and cnfs -getStage l trail :=+def getStage l trail := matchDFS trail as list assignment with | _ ++ whichever (#(neg l), $s) :: _ -> s | _ -> "error: not matched in get-stage" -deleteLiteral l cnf :=+def deleteLiteral l cnf := map (\c ->- ( matchAllDFS 2#%1 c as multiset literal with+ ( matchAllDFS fst c as multiset literal with | (!#l & $m) :: _ -> m- , 2#%2 c ))+ , snd c )) cnf -deleteClausesWith l cnf :=+def deleteClausesWith l cnf := matchAllDFS cnf as multiset (multiset literal, multiset literal) with | ((!(#l :: _), _) & $c) :: _ -> c -assignTrue l cnf := deleteLiteral (neg l) (deleteClausesWith l cnf)+def assignTrue l cnf := deleteLiteral (neg l) (deleteClausesWith l cnf) -unitPropagate stage cnf trail := unitPropagate' stage cnf trail trail+def unitPropagate stage cnf trail := unitPropagate' stage cnf trail trail -unitPropagate' stage cnf trail otrail :=+def unitPropagate' stage cnf trail otrail := matchDFS trail as list assignment with | whichever ($l, _) :: $trail' -> unitPropagate' stage (assignTrue l cnf) trail' otrail | [] -> unitPropagate'' stage (assignTrue l cnf) otrail -unitPropagate'' stage cnf trail :=+def unitPropagate'' stage cnf trail := matchDFS cnf as multiset (multiset literal, multiset literal) with -- empty literal | ([], _) :: _ -> (cnf, trail)@@ -82,27 +82,27 @@ -- otherwise | _ -> (cnf, trail) -learn stage cl trail :=+def learn stage cl trail := matchDFS (trail, cl) as (list assignment, multiset taggedLiteral) with -- not more than 2 literals from the current stage | (_, !((_, #stage) :: (_, #stage) :: _)) ->- (minimum (map 2#%2 cl), map 2#%1 cl)+ (minimum (map snd cl), map fst cl) -- otherwise | (_ ++ deduced ($l, #stage) $ds :: $trail', (#(neg l), #stage) :: $rs) -> learn stage (union rs ds) trail' -backjump stage trail :=+def backjump stage trail := matchDFS trail as list assignment with | _ ++ (guessed (_, #stage) :: _ & $trail') -> trail' | _ -> trail -guess vars trail :=+def guess vars trail := matchDFS (vars, trail) as (list (literal, integer), list assignment) with | (_ ++ ($l, _) :: _, !(_ ++ whichever (#l | #(neg l), _) :: _)) -> neg l -cdcl vars cnf := cdcl' 0 0 (initVars vars) (toCnf cnf) []+def cdcl vars cnf := cdcl' 0 0 (initVars vars) (toCnf cnf) [] -cdcl' count stage vars cnf trail :=+def cdcl' count stage vars cnf trail := let (cnf', trail') := unitPropagate stage cnf trail in matchDFS cnf' as multiset (multiset literal, multiset literal) with | [] -> True@@ -130,7 +130,7 @@ cnf (Guessed (g, stage + 1) :: trail') -problem20 :=+def problem20 := [[4, -18, 19], [3, 18, -5], [-5, -8, -15], [-20, 7, -16], [10, -13, -7], [-12, -9, 17], [17, 19, 5], [-16, 9, 15], [11, -5, -14], [18, -10, 13], [-3, 11, 12], [-6, -17, -8], [-18, 14, 1], [-19, -15, 10], [12, 18, -19],@@ -151,7 +151,7 @@ [-5, -17, -19], [-20, -18, 11], [-9, 1, -5], [-19, 9, 17], [12, -2, 17], [4, -16, -5]] -problem50 :=+def problem50 := [[18, -8, 29], [-16, 3, 18], [-36, -11, -30], [-50, 20, 32], [-6, 9, 35], [42, -38, 29], [43, -15, 10], [-48, -47, 1], [-45, -16, 33], [38, 42, 22], [-49, 41, -34], [12, 17, 35], [22, -49, 7], [-10, -11, -39], [-28, -36, -37],
sample/sat/dp.egi view
@@ -2,25 +2,25 @@ -- This file has been auto-generated by egison-translator. -- -deleteLiteral l cnf :=+def deleteLiteral l cnf := map (\c -> matchAll c as multiset integer with | ((!#l) & $x) :: _ -> x) cnf -deleteClausesWith l cnf :=+def deleteClausesWith l cnf := matchAll cnf as multiset (multiset integer) with | ((!(#l :: _)) & $c) :: _ -> c -assignTrue l cnf := deleteLiteral (neg l) (deleteClausesWith l cnf)+def assignTrue l cnf := deleteLiteral (neg l) (deleteClausesWith l cnf) -resolveOn v cnf :=+def resolveOn v cnf := matchAll cnf as multiset (multiset integer) with | {(#v :: (@ & $xs)) :: (#(neg v) :: (@ & $ys)) :: _, !( $l :: _, #(neg l) :: _ )} -> unique (xs ++ ys) -dp vars cnf :=+def dp vars cnf := match (vars, cnf) as (multiset integer, multiset (multiset integer)) with | (_, []) -> True | (_, [] :: _) -> False
sample/tree.egi view
@@ -1,4 +1,4 @@-tree a := matcher+def tree a := matcher | leaf $ as a with | Leaf $x -> [x] | Node _ _ -> []@@ -15,7 +15,7 @@ | $ as something with | $tgt -> [tgt] -treeData :=+def treeData := Node "Programming language" [Node "pattern-match-oriented" [Leaf "Egison"], Node "Functional language"@@ -24,7 +24,7 @@ Node "Logic programming" [Leaf "Prolog", Leaf "Curry"], Node "Object oriented" [Leaf "C++", Leaf "Java", Leaf "Ruby", Leaf "Python", Leaf "OCaml"]] -ancestors x t :=+def ancestors x t := matchAllDFS t as tree eq with | $hs ++ leaf #x -> hs @@ -32,7 +32,7 @@ (ancestors "Egison" treeData) [["Programming language", "pattern-match-oriented"], ["Programming language", "Functional language", "Dynamically typed"]] -descendants x t :=+def descendants x t := matchAllDFS t as tree eq with | _ ++ #x :: _ ++ leaf $y -> y
test/Test.hs view
@@ -1,29 +1,20 @@ module Main where -import Control.Applicative-import Control.Monad-import Control.Monad.IO.Class-import Data.IORef-import Data.List+import Control.Monad.Trans.Class (lift) -import System.FilePath (replaceDirectory, splitPath,- takeDirectory)-import System.FilePath.Glob (glob) import Test.Framework (defaultMain) import Test.Framework.Providers.HUnit (hUnitTestToTests) import Test.HUnit import Language.Egison-import Language.Egison.Core-import Language.Egison.CmdOptions+import Language.Egison.Eval+import Language.Egison.MathOutput import Language.Egison.Parser-import Language.Egison.Pretty-import Language.Egison.Primitives-import Language.Egison.Types main :: IO ()-main =- defaultMain . hUnitTestToTests . test $ map runTestCase testCases+main = do+ t <- evalRuntimeT defaultOption mathOutputTest+ defaultMain . hUnitTestToTests . test $ t : map runTestCase testCases testCases :: [FilePath] testCases =@@ -55,20 +46,32 @@ ] runTestCase :: FilePath -> Test-runTestCase file = TestLabel file . TestCase $ do- env <- initialEnv defaultOption- assertEvalM $ do- exprs <- loadFile file- let (bindings, tests) = foldr collectDefsAndTests ([], []) exprs- env' <- recursiveBind env bindings- forM_ tests $ evalExprDeep env'- where- assertEvalM :: EvalM a -> Assertion- assertEvalM m = fromEvalM m >>= assertString . either show (const "")+runTestCase file = TestLabel file . TestCase . assertEvalM $ do+ env <- lift $ lift initialEnv+ exprs <- loadFile file+ evalTopExprsNoPrint env exprs+ where+ assertEvalM :: EvalM a -> Assertion+ assertEvalM m = fromEvalM defaultOption m >>= assertString . either show (const "") -collectDefsAndTests :: EgisonTopExpr -> ([(Var, EgisonExpr)], [EgisonExpr]) -> ([(Var, EgisonExpr)], [EgisonExpr])-collectDefsAndTests (Define name expr) (bindings, tests) =- ((name, expr) : bindings, tests)-collectDefsAndTests (Test expr) (bindings, tests) =- (bindings, expr : tests)-collectDefsAndTests _ r = r+mathOutputTest :: RuntimeM Test+mathOutputTest = do+ env <- initialEnv+ latexTest <- mathOutputTestLatex env+ return $ TestList [latexTest]++mathOutputTestLatex :: Env -> RuntimeM Test+mathOutputTestLatex env = do+ TestLabel "math output: latex" . TestList <$>+ mapM (\(x, y, z) -> makeTest x y z)+ [ ("div", "x / y", "\\frac{x}{y}")+ ]+ where+ makeTest = makeMathOutputTest env "latex"++makeMathOutputTest :: Env -> String -> String -> String -> String -> RuntimeM Test+makeMathOutputTest env lang label expr expectedOutput = do+ res <- fromEvalT (runExpr env expr)+ case res of+ Left _ -> return . TestCase $ assertFailure "Failed to evaluate the expression"+ Right res -> return . TestCase $ assertEqual label ("#" ++ lang ++ "|" ++ expectedOutput ++ "|#") (prettyMath lang res)
test/lib/core/collection.egi view
@@ -249,6 +249,18 @@ (splitAs integer [0] [1, 2, 0, 3, 3, 0, 4, 0]) [[1, 2], [3, 3], [4], []] +assertEqual "splitAt"+ (splitAt 0 [1, 2, 3])+ ([], [1, 2, 3])++assertEqual "splitAt"+ (splitAt 2 [1, 2, 3])+ ([1, 2], [3])++assertEqual "splitAt"+ (splitAt 4 [1, 2, 3])+ ([1, 2, 3], [])+ assertEqual "findCycle" (findCycle [1, 3, 4, 5, 2, 7, 5, 2, 7, 5, 2, 7]) ([1, 3, 4], [5, 2, 7])
test/lib/core/number.egi view
@@ -70,7 +70,7 @@ assertEqual "nAdic" (nAdic 2 10) [1, 0, 1, 0] assertEqual "rtod"- (2#(%1, take 10 %2) (rtod (6 / 35)))+ ((\(x, y) -> (x, take 10 y)) (rtod (6 / 35))) (0, [1, 7, 1, 4, 2, 8, 5, 7, 1, 4]) assertEqual "rtod'" (rtod' (6 / 35)) (0, [1], [7, 1, 4, 2, 8, 5])@@ -106,12 +106,12 @@ assertEqual "regularContinuedFractionOfSqrt case 1"- (2#(%1, take 10 %2) (regularContinuedFractionOfSqrt 2))+ ((\(x, y) -> (x, take 10 y)) (regularContinuedFractionOfSqrt 2)) (1, [2, 2, 2, 2, 2, 2, 2, 2, 2, 2]) assertEqual "regularContinuedFractionOfSqrt case 2" (rtof- (regularContinuedFraction- (2#(%1, take 100 %2) (regularContinuedFractionOfSqrt 2))))+ (let (x, y) := regularContinuedFractionOfSqrt 2+ in regularContinuedFraction x (take 100 y))) 1.4142135623730951
test/lib/math/tensor.egi view
@@ -56,22 +56,18 @@ in f A_i) [|[|1, 1|], [|1, 1|]|]_i_j -g_i_j := (generateTensor- (\match as (integer, integer) with- | ($n, #n) -> function (x, y, z)- | (_, _) -> 0)- [3, 3])_i_j- assertEqual "generate_tensor by using function expr"- (show (withSymbols [i, j] d/d g_i_j x))+ (let g_i_j := (generateTensor+ (\n m -> if n = m then function (x, y, z) else 0)+ [3, 3])_i_j+ in show (withSymbols [i, j] d/d g_i_j x)) "[| [| g_1_1|x, 0, 0 |], [| 0, g_2_2|x, 0 |], [| 0, 0, g_3_3|x |] |]" -h_i_j := [|[|function (x, y, z), 0, 0|]- , [|0, function (x, y, z), 0|]- , [|0, 0, function (x, y, z)|]|]_i_j- assertEqual "define tensor having value of function expr"- (show (withSymbols [i, j] d/d h_i_j x))+ (let h_i_j := [|[|function (x, y, z), 0, 0|]+ , [|0, function (x, y, z), 0|]+ , [|0, 0, function (x, y, z)|]|]_i_j+ in show (withSymbols [i, j] d/d h_i_j x)) "[| [| h_1_1|x, 0, 0 |], [| 0, h_2_2|x, 0 |], [| 0, 0, h_3_3|x |] |]"
test/primitive.egi view
@@ -6,7 +6,7 @@ assertEqual "quotient" (quotient (-21) 13) (-1) -assertEqual "remainder" (remainder (-21) 13) (-8)+assertEqual "remainder" ((-21) % 13) (-8) assertEqual "neg" (neg (-89)) 89 @@ -113,10 +113,8 @@ assertEqual "regexCg" (regexCg "([0-9]+),([0-9]+)" "abc,123,45,defg") [("abc,", ["123", "45"], ",defg")] --- addPrime -- addSubscript -- addSuperscript--- readProcess assertEqual "read" (read "3") 3 assertEqual "read" (read "3.14") 3.14
test/syntax.egi view
@@ -66,10 +66,10 @@ (let { x := 1; y := x + 1 } in y) 2 -io do print "io and do expression"- return 0+io $ do print "io and do expression"+ return 0 -io do { print "io and do expression without newline"; return 0 }+io $ do { print "io and do expression without newline"; return 0 } assertEqual "where" (f 0 + y + 1@@ -107,14 +107,18 @@ ((\x y -> x + y) 1 2 + 3) 6 -assertEqual "lambda with 0 argument"+assertEqual "lambda with case" ((\() -> 1) ()) 1 -assertEqual "lambda with tuple argument"- ((\(x, y, z) -> x + y + z) 1 2 3)- 6+assertEqual "lambda with case"+ ((\(x, y, z) -> x - y - z) (1, 2, 3))+ (-4) +assertEqual "lambda with case"+ ((\_ -> 1) 2)+ 1+ assertEqual "append op" ([1] ++ [2]) [1, 2] assertEqual "append op" ((++) [1] [2]) [1, 2] @@ -133,20 +137,20 @@ -- user-defined infix infixl expression 5 @-(@) x y := x - y+def (@) x y := x - y assertEqual "user defined infix" (4 @ 3 @ 5) (-4) infixl expression 5 @@-(@@) %x y := x - y+def (@@) %x y := x - y assertEqual "user defined infix with tensor arg" (4 @@ 3 @@ 2) (-1) -findFactor :=+def findFactor := memoizedLambda n -> match takeWhile (<= floor (sqrt (itof n))) primes as list integer with | _ ++ (?(\m -> divisor n m) & $x) :: _ -> x@@ -156,7 +160,7 @@ (map findFactor [1..10]) [1, 2, 3, 2, 5, 2, 7, 2, 3, 2] -twinPrimes :=+def twinPrimes := matchAll primes as list integer with | _ ++ $p :: #(p + 2) :: _ -> (p, p + 2) @@ -164,7 +168,7 @@ (take 10 twinPrimes) [(3, 5), (5, 7), (11, 13), (17, 19), (29, 31), (41, 43), (59, 61), (71, 73), (101, 103), (107, 109)] -primeTriplets :=+def primeTriplets := matchAll primes as list integer with | _ ++ $p :: ((#(p + 2) | #(p + 4)) & $m) :: #(p + 6) :: _ -> (p, m, p + 6)@@ -173,21 +177,21 @@ (take 10 primeTriplets) [(5, 7, 11), (7, 11, 13), (11, 13, 17), (13, 17, 19), (17, 19, 23), (37, 41, 43), (41, 43, 47), (67, 71, 73), (97, 101, 103), (101, 103, 107)] -someFunction x y z :=+def someFunction x y z := x + y * z assertEqual "function definition" (someFunction 1 2 3) 7 -someFunctionWithDollar $x $y $z :=+def someFunctionWithDollar $x $y $z := x + y + z assertEqual "function definition with '$' scalar arg" (someFunctionWithDollar 1 2 3) 6 -gcd m n :=+def gcd m n := if m >= n then if n = 0 then m else gcd n (m % n)@@ -197,7 +201,7 @@ (gcd 143 22) 11 -A x := 1+def A x := 1 assertEqual "definition of upper-case identifier" (A 2)@@ -207,15 +211,15 @@ (capply (+) [1, 2]) 3 -f0 () := 1-f2 (x, y) := x + y+def f0 () := 1+def f2 (x, y) := x + y assertEqual "nullary function definition" (f0 ()) 1 assertEqual "function definition with tupled argument"- (f2 1 2)+ (f2 (1, 2)) 3 {-@@ -437,11 +441,11 @@ | $x :: $y :: _ -> (x, y)) [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)] -tree a := algebraicDataMatcher+def tree a := algebraicDataMatcher | leaf | node (tree a) a (tree a) -treeInsert n t :=+def treeInsert n t := match t as tree integer with | leaf -> Node Leaf n Leaf | node $t1 $m $t2 -> match (compare n m) as ordering with@@ -449,7 +453,7 @@ | equal -> Node t1 n t2 | greater -> Node t1 m (treeInsert n t2) -treeMember n t :=+def treeMember n t := match t as tree integer with | leaf -> False | node $t1 $m $t2 -> match (compare n m) as ordering with@@ -535,13 +539,37 @@ in x_(i_1)..._(i_3)) 6 -TestT := generateTensor 3#x_%1_%2_%3 [2,3,4]-TestC_c_a_b := TestT_a_b_c+def TestT := generateTensor 3#x_%1_%2_%3 [2,3,4]+def TestC_c_a_b := TestT_a_b_c assertEqual "transpose" TestC_#_#_#- (tensor [4, 2, 3] [x_1_1_1, x_1_2_1, x_1_3_1, x_2_1_1, x_2_2_1, x_2_3_1, x_1_1_2, x_1_2_2, x_1_3_2, x_2_1_2, x_2_2_2, x_2_3_2, x_1_1_3, x_1_2_3, x_1_3_3, x_2_1_3, x_2_2_3, x_2_3_3, x_1_1_4, x_1_2_4, x_1_3_4, x_2_1_4, x_2_2_4, x_2_3_4] )_#_#_#+ (tensor [4, 2, 3]+ [x_1_1_1, x_1_2_1, x_1_3_1, x_2_1_1, x_2_2_1, x_2_3_1,+ x_1_1_2, x_1_2_2, x_1_3_2, x_2_1_2, x_2_2_2, x_2_3_2,+ x_1_1_3, x_1_2_3, x_1_3_3, x_2_1_3, x_2_2_3, x_2_3_3,+ x_1_1_4, x_1_2_4, x_1_3_4, x_2_1_4, x_2_2_4, x_2_3_4])_#_#_# +def symmT{_i_j} :=+ [| [| 0, 1, 2 |],+ [| 1, 0, 3 |],+ [| 2, 3, 0 |] |]++def asymmT[_i_j] :=+ [| [| 0, 1, 2 |],+ [| -1, 0, 3 |],+ [| -2, -3, 0 |] |]++assert "symmetric tensor"+ (symmT_1_1 = 0 && symmT_1_2 = 1 && symmT_1_3 = 2 &&+ symmT_2_1 = 1 && symmT_2_2 = 0 && symmT_2_3 = 3 &&+ symmT_3_1 = 2 && symmT_3_2 = 3 && symmT_3_3 = 0)++assert "symmetric tensor"+ (asymmT_1_1 = 0 && asymmT_1_2 = 1 && asymmT_1_3 = 2 &&+ asymmT_2_1 = -1 && asymmT_2_2 = 0 && asymmT_2_3 = 3 &&+ asymmT_3_1 = -2 && asymmT_3_2 = -3 && asymmT_3_3 = 0)+ -- -- Hash --@@ -558,10 +586,14 @@ {| (1, 11), (2, 12), (3, 13), (4, 14), (5, 15), |}_3 13 --- assertEqual "string hash access"--- {| ("1", 11), ("2", 12), ("3", 13), ("4", 14), ("5", 15) |}_"3"--- 13+assertEqual "string hash access"+ {| ("1", 11), ("2", 12), ("3", 13), ("4", 14), ("5", 15) |}_"3"+ 13 +assertEqual "char hash access"+ {| ('a', 11), ('b', 12), ('c', 13), ('d', 14), ('e', 15) |}_'c'+ 13+ -- -- Partial Application --@@ -574,13 +606,13 @@ (take 10 (1#(%1 :: (%0 (%1 * 2))) 2)) [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] -f *x *y := x + y+def f *$x *$y := x + y assertEqual "double inverted index" (f [|1, 2, 3|]_i [|10, 20, 30|]_j) [| [| 11, 21, 31, |], [| 12, 22, 32, |], [| 13, 23, 33, |], |]~i~j -g $x *y := x + y+def g $x *$y := x + y assertEqual "single inverted index" (g [|1, 2, 3|]_i [|10, 20, 30|]_j)@@ -590,7 +622,7 @@ -- matcherExpr -- -list a := matcher+def list a := matcher | [] as () with | [] -> [()] | _ -> []@@ -616,7 +648,7 @@ | $ as something with | $tgt -> [tgt] -multiset a := matcher+def multiset a := matcher | [] as () with | $tgt -> match tgt as (mutiset a) with | [] -> [()]@@ -637,7 +669,7 @@ | $x :: _ -> x) [1, 2, 3] -nishiwakiIf b e1 e2 :=+def nishiwakiIf b e1 e2 := head (matchAll b as (matcher | $ as something with | True -> [e1]@@ -653,7 +685,7 @@ infixl pattern 7 <> infixl pattern 4 <?> -- '?' is allowed from the 2nd character -dummyMatcher := matcher+def dummyMatcher := matcher | $ <> $ as (integer, integer) with | $x :: $y :: [] -> [(x, y)] | _ -> []@@ -668,3 +700,20 @@ assertEqual "user-defined pattern infix" (match [1, 2] as dummyMatcher with $x <?> $y :: _ -> x + y) 3++-- Primitive data pattern match with let expression+assertEqual "let pattern match"+ (let (x :: xs) := [1, 2, 3] in (x, xs))+ (1, [2, 3])++assertEqual "let pattern match"+ (let (snoc xs x) := [1, 2, 3] in (x, xs))+ (3, [1, 2])++assertEqual "let pattern match"+ (let (Just x) := Just 1 in x)+ 1++assertEqual "let pattern match"+ (let (x, y) := (2, 3) in x + y)+ 5