packages feed

egison 3.9.0 → 3.9.1

raw patch · 7 files changed

+478/−72 lines, 7 files

Files

egison.cabal view
@@ -1,5 +1,5 @@ Name:                egison-Version:             3.9.0+Version:             3.9.1 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.@@ -85,7 +85,7 @@                    Language.Egison.Util                    Language.Egison.MathOutput   Other-modules:   Paths_egison-  build-tools:     happy, alex+  build-tools:     happy >= 1.17.1, alex   ghc-options:  -O3  Test-Suite test
hs-src/Language/Egison/Core.hs view
@@ -107,12 +107,13 @@ evalTopExpr' _ st (Test expr) = do   pushFuncName "<stdin>"   val <- evalStateT st [] >>= flip evalExprDeep expr+  popFuncName   return (Just (show val), st) evalTopExpr' _ st (Execute expr) = do   pushFuncName "<stdin>"   io <- evalStateT st [] >>= flip evalExpr expr   case io of-    Value (IOFunc m) -> m >> return (Nothing, st)+    Value (IOFunc m) -> m >> popFuncName >> return (Nothing, st)     _                -> throwError =<< TypeMismatch "io" io <$> getFuncNameStack evalTopExpr' opts st (Load file) = do   exprs <- if optSExpr opts then Parser.loadLibraryFile file else ParserNonS.loadLibraryFile file
hs-src/Language/Egison/Lexer.x view
@@ -1,63 +1,159 @@ {-{-# OPTIONS -w  #-}+{-# OPTIONS -w #-}++{- |+Module      : Language.Egison.Lexer+Copyright   : Satoshi Egi+Licence     : MIT++This module provides new Egison lexer.+-}+ module Language.Egison.Lexer-  ( Token(..)-  , AlexPosn(..)-  , TokenClass(..)-  , Alex(..)-  , runAlex'-  , alexMonadScan'-  , alexError'-  ) where-import Prelude       hiding (lex)-import Control.Monad (liftM)+       ( Token(..)+       , AlexPosn(..)+       , TokenClass(..)+       , Alex(..)+       , runAlex'+       , alexMonadScan'+       , alexError+       , alexError'+       ) where++import           Prelude               hiding (lex)+import           Control.Monad         (liftM)++import           Language.Egison.Types+ }+ %wrapper "monadUserState" $digit = 0-9 $alpha = [A-Za-z] tokens :-   $white+                        ;-  $digit+                        { lex (TokenInt . read) }-  $alpha [$alpha $digit \_ \']*  { lex  TokenVar         }-  \=                             { lex' TokenEq          }-  \<                             { lex' TokenLT          }-  \>                             { lex' TokenGT          }-  \<\=                           { lex' TokenLE          }-  \>\=                           { lex' TokenGE          }-  \+                             { lex' TokenPlus        }-  \-                             { lex' TokenMinus       }-  \*                             { lex' TokenAsterisk    }-  \/                             { lex' TokenDiv         }-  \(                             { lex' TokenLParen      }-  \)                             { lex' TokenRParen      }-  \[                             { lex' TokenLBracket    }-  \]                             { lex' TokenRBracket    } +  -- Keywords+  True                           { lex' TokenTrue           }+  False                          { lex' TokenFalse          }+  test                           { lex' TokenTest           }+  match                          { lex' TokenMatch          }+  matchDFS                       { lex' TokenMatchDFS       }+  matchAll                       { lex' TokenMatchAll       }+  matchAllDFS                    { lex' TokenMatchAllDFS    }+  matchLambda                    { lex' TokenMatchLambda    }+  matchAllLambda                 { lex' TokenMatchAllLambda }+  as                             { lex' TokenAs             }+  with                           { lex' TokenWith           }+  something                      { lex' TokenSomething      }+  if                             { lex' TokenIf             }+  then                           { lex' TokenThen           }+  else                           { lex' TokenElse           }++  -- Data+  $digit+                        { lex (TokenInt . read)    }+  $alpha [$alpha $digit \']*     { lex  TokenVar            }++  -- Operators+  \=\=                           { lex' TokenEqEq           }+  \<                             { lex' TokenLT             }+  \>                             { lex' TokenGT             }+  \<\=                           { lex' TokenLE             }+  \>\=                           { lex' TokenGE             }+  \+                             { lex' TokenPlus           }+  \-                             { lex' TokenMinus          }+  \%                             { lex' TokenPercent        }+  \*                             { lex' TokenAsterisk       }+  \/                             { lex' TokenDiv            }+  \^                             { lex' TokenCaret          }+  \&\&                           { lex' TokenAndAnd         }+  \|\|                           { lex' TokenBarBar         }+  \:                             { lex' TokenColon          }+  \.\.                           { lex' TokenDotDot         }+  \+\+                           { lex' TokenPlusPlus       }++  \|                             { lex' TokenBar            }+  \-\>                           { lex' TokenArrow          }+  \$                             { lex' TokenDollar         }+  \_                             { lex' TokenUnderscore     }+  \#                             { lex' TokenSharp          }+  \,                             { lex' TokenComma          }+  \\                             { lex' TokenBackSlash      }+  \*\$                           { lex' TokenAstDollar      }+  \=                             { lex' TokenEq             }++  \(                             { lex' TokenLParen         }+  \)                             { lex' TokenRParen         }+  \[                             { lex' TokenLBracket       }+  \]                             { lex' TokenRBracket       }+ { -- To improve error messages, We keep the path of the file we are -- lexing in our own state. data AlexUserState = AlexUserState { filePath :: FilePath }+ alexInitUserState :: AlexUserState alexInitUserState = AlexUserState "<unknown>"+ getFilePath :: Alex FilePath getFilePath = liftM filePath alexGetUserState+ setFilePath :: FilePath -> Alex () setFilePath = alexSetUserState . AlexUserState+ -- The token type, consisting of the source code position and a token class. data Token = Token AlexPosn TokenClass   deriving ( Show )+ data TokenClass-  = TokenInt Integer+  -- Keywords+  = TokenTrue+  | TokenFalse+  | TokenTest+  | TokenMatch+  | TokenMatchDFS+  | TokenMatchAll+  | TokenMatchAllDFS+  | TokenMatchLambda+  | TokenMatchAllLambda+  | TokenAs+  | TokenWith+  | TokenSomething+  | TokenIf+  | TokenThen+  | TokenElse++  -- Data and Variables+  | TokenInt Integer   | TokenVar String-  | TokenEq++  | TokenEqEq   | TokenLT   | TokenGT   | TokenLE   | TokenGE   | TokenPlus   | TokenMinus+  | TokenPercent   | TokenAsterisk   | TokenDiv+  | TokenCaret+  | TokenAndAnd+  | TokenBarBar+  | TokenColon+  | TokenDotDot+  | TokenPlusPlus++  | TokenBar+  | TokenArrow+  | TokenDollar+  | TokenUnderscore+  | TokenSharp+  | TokenComma+  | TokenBackSlash+  | TokenAstDollar+  | TokenEq+   | TokenLParen   | TokenRParen   | TokenLBracket@@ -66,17 +162,52 @@  -- For nice parser error messages. instance Show TokenClass where+  show TokenTrue = "True"+  show TokenFalse = "False"+  show TokenTest = "test"+  show TokenMatch = "match"+  show TokenMatchDFS = "matchDFS"+  show TokenMatchAll = "matchAll"+  show TokenMatchAllDFS = "matchAllDFS"+  show TokenMatchLambda = "matchLambda"+  show TokenMatchAllLambda = "matchAllLambda"+  show TokenAs = "as"+  show TokenWith = "with"+  show TokenSomething = "something"+  show TokenIf = "if"+  show TokenThen = "then"+  show TokenElse = "else"+   show (TokenInt i) = show i   show (TokenVar s) = show s-  show TokenEq = "="++  show TokenEqEq = "=="   show TokenLT = "<"   show TokenGT = ">"   show TokenLE = "<="   show TokenGE = ">="   show TokenPlus = "+"   show TokenMinus = "-"+  show TokenPercent = "%"   show TokenAsterisk = "*"   show TokenDiv = "/"+  show TokenCaret = "^"+  show TokenAndAnd = "&&"+  show TokenBarBar = "||"+  show TokenColon = ":"+  show TokenDotDot = ".."+  show TokenPlusPlus = "++"++  show TokenBar = "|"+  show TokenArrow = "->"+  show TokenDollar = "$"+  show TokenUnderscore = "_"+  show TokenSharp = "#"+  show TokenComma = ","+  show TokenBackSlash = "\\"+  show TokenAstDollar = "*$"+  show TokenEq = "="+   show TokenLParen = "("   show TokenRParen = ")"   show TokenLBracket = "["@@ -87,14 +218,17 @@ alexEOF = do   (p,_,_,_) <- alexGetInput   return $ Token p TokenEOF+ -- Unfortunately, we have to extract the matching bit of string -- ourselves... lex :: (String -> TokenClass) -> AlexAction Token lex f = \(p,_,_,s) i -> return $ Token p (f (take i s))+ -- For constructing tokens that do not depend on -- the input lex' :: TokenClass -> AlexAction Token lex' = lex . const+ -- We rewrite alexMonadScan' to delegate to alexError' when lexing fails -- (the default implementation just returns an error message). alexMonadScan' :: Alex Token@@ -111,12 +245,17 @@     AlexToken inp' len action -> do         alexSetInput inp'         action (ignorePendingBytes inp) len+ -- Signal an error, including a commonly accepted source code position. alexError' :: AlexPosn -> String -> Alex a alexError' (AlexPn _ l c) msg = do   fp <- getFilePath   alexError (fp ++ ":" ++ show l ++ ":" ++ show c ++ ": " ++ msg)+ -- A variant of runAlex, keeping track of the path of the file we are lexing.-runAlex' :: Alex a -> String -> Either String a-runAlex' a input = runAlex input (setFilePath "<stdin>" >> a)+runAlex' :: Alex a -> String -> Either EgisonError a+runAlex' a input =+  case runAlex input (setFilePath "<stdin>" >> a) of+    Left msg -> Left $ Parser msg+    Right r  -> Right r }
hs-src/Language/Egison/ParserNonS2.y view
@@ -1,5 +1,14 @@ { {-# OPTIONS -w #-}++{- |+Module      : Language.Egison.ParserNonS2+Copyright   : Satoshi Egi+Licence     : MIT++This module provides new Egison parser.+-}+ module Language.Egison.ParserNonS2        (        -- * Parse a string@@ -12,85 +21,284 @@        , parseExprs        , parseExpr        -- * Parse a file-       , loadFile        , loadLibraryFile+       , loadFile        ) where -import Language.Egison.Lexer-import Language.Egison.Types+import           Control.Monad.Except    hiding (mapM) +import           Data.Either+import qualified Data.Set                as Set++import           System.Directory        (doesFileExist, getHomeDirectory)++import           Language.Egison.Desugar+import           Language.Egison.Lexer+import           Language.Egison.Types+import           Paths_egison            (getDataFileName)+ } -%name parse+-- %name parseTopExprs_ TopExprs+%name parseTopExpr_ TopExpr+%name parseExpr_ Expr %tokentype { Token } %monad { Alex } %lexer { lexwrap } { Token _ TokenEOF } -- Without this we get a type error %error { happyError } -%right let in-%left '<' '>' '=' "<=" ">="-%left '+' '-'+%right '|'+%right "++"+%right "||"+%right "&&"+%right ':'+%left '<' '>' "==" "<=" ">="+%left '+' '-' '%' %left '*' '/'+%left '^'+%right TENSOR  %token-      int      { Token _ (TokenInt $$) }-      var      { Token _ (TokenVar $$) }-      '='      { Token _ TokenEq }-      '<'      { Token _ TokenLT }-      '>'      { Token _ TokenGT }-      "<="     { Token _ TokenLE }-      ">="     { Token _ TokenGE }-      '+'      { Token _ TokenPlus }-      '-'      { Token _ TokenMinus }-      '*'      { Token _ TokenAsterisk }-      '/'      { Token _ TokenDiv }-      '('      { Token _ TokenLParen }-      ')'      { Token _ TokenRParen }-      '['      { Token _ TokenLBracket }-      ']'      { Token _ TokenRBracket }+      True           { Token _ TokenTrue           }+      False          { Token _ TokenFalse          }+      test           { Token _ TokenTest           }+      match          { Token _ TokenMatch          }+      matchDFS       { Token _ TokenMatchDFS       }+      matchAll       { Token _ TokenMatchAll       }+      matchAllDFS    { Token _ TokenMatchAllDFS    }+      matchLambda    { Token _ TokenMatchLambda    }+      matchAllLambda { Token _ TokenMatchAllLambda }+      as             { Token _ TokenAs             }+      with           { Token _ TokenWith           }+      something      { Token _ TokenSomething      }+      if             { Token _ TokenIf             }+      then           { Token _ TokenThen           }+      else           { Token _ TokenElse           } +      int            { Token _ (TokenInt $$)       }+      var            { Token _ (TokenVar $$)       }++      "=="           { Token _ TokenEqEq           }+      '<'            { Token _ TokenLT             }+      '>'            { Token _ TokenGT             }+      "<="           { Token _ TokenLE             }+      ">="           { Token _ TokenGE             }+      '+'            { Token _ TokenPlus           }+      '-'            { Token _ TokenMinus          }+      '%'            { Token _ TokenPercent        }+      '*'            { Token _ TokenAsterisk       }+      '/'            { Token _ TokenDiv            }+      '^'            { Token _ TokenCaret          }+      "&&"           { Token _ TokenAndAnd         }+      "||"           { Token _ TokenBarBar         }+      ':'            { Token _ TokenColon          }+      ".."           { Token _ TokenDotDot         }+      "++"           { Token _ TokenPlusPlus       }++      '|'            { Token _ TokenBar            }+      "->"           { Token _ TokenArrow          }+      '$'            { Token _ TokenDollar         }+      '_'            { Token _ TokenUnderscore     }+      '#'            { Token _ TokenSharp          }+      ','            { Token _ TokenComma          }+      '\\'           { Token _ TokenBackSlash      }+      "*$"           { Token _ TokenAstDollar      }+      '='            { Token _ TokenEq             }++      '('            { Token _ TokenLParen         }+      ')'            { Token _ TokenRParen         }+      '['            { Token _ TokenLBracket       }+      ']'            { Token _ TokenRBracket       }+ %% -EgisonExpr :-    int      { IntegerExpr $1 }+-- TopExprs :+--     TopExpr           { [$1] }+--   | TopExpr TopExprs  { $1 : $2 } +TopExpr :: { EgisonTopExpr }+  : var '=' Expr            { Define (stringToVar $1) $3 }+  | var list1(Arg) '=' Expr { Define (stringToVar $1) (LambdaExpr $2 $4) }+  | Expr                    { Test $1 }+  | test '(' Expr ')'       { Test $3 }++Expr :: { EgisonExpr }+  : Expr1                       { $1 }+  | MatchExpr                   { $1 }+  | '\\' list1(Arg) "->" Expr   { LambdaExpr $2 $4 }+  | if Expr then Expr else Expr { IfExpr $2 $4 $6 }++Expr1 :: { EgisonExpr }+  : Atoms             { $1 }+  | '-' Atom          { makeApply (VarExpr $ stringToVar "*") [IntegerExpr(-1), $2] }+  | BinOpExpr         { $1 }++BinOpExpr :: { EgisonExpr }+  : Expr1 "==" Expr1  { makeApply (VarExpr $ stringToVar "eq?")       [$1, $3] }+  | Expr1 "<=" Expr1  { makeApply (VarExpr $ stringToVar "lte?")      [$1, $3] }+  | Expr1 '<'  Expr1  { makeApply (VarExpr $ stringToVar "lt?")       [$1, $3] }+  | Expr1 ">=" Expr1  { makeApply (VarExpr $ stringToVar "gte?")      [$1, $3] }+  | Expr1 '>'  Expr1  { makeApply (VarExpr $ stringToVar "gt?")       [$1, $3] }+  | Expr1 '+'  Expr1  { makeApply (VarExpr $ stringToVar "+")         [$1, $3] }+  | Expr1 '-'  Expr1  { makeApply (VarExpr $ stringToVar "-")         [$1, $3] }+  | Expr1 '%'  Expr1  { makeApply (VarExpr $ stringToVar "remainder") [$1, $3] }+  | Expr1 '*'  Expr1  { makeApply (VarExpr $ stringToVar "*")         [$1, $3] }+  | Expr1 '/'  Expr1  { makeApply (VarExpr $ stringToVar "/")         [$1, $3] }+  | Expr1 '^'  Expr1  { makeApply (VarExpr $ stringToVar "**")        [$1, $3] }+  | Expr1 "&&" Expr1  { makeApply (VarExpr $ stringToVar "and")       [$1, $3] }+  | Expr1 "||" Expr1  { makeApply (VarExpr $ stringToVar "or")        [$1, $3] }+  | Expr1 ':'  Expr1  { makeApply (VarExpr $ stringToVar "cons")      [$1, $3] }+  | Expr1 "++" Expr1  { makeApply (VarExpr $ stringToVar "append")    [$1, $3] }++Atoms :: { EgisonExpr }+  : Atom              { $1 }+  | Atom list1(Atom)  { makeApply $1 $2 }++MatchExpr :: { EgisonExpr }+  : match       Expr as Expr with '|' MatchClauses { MatchExpr $2 $4 $7 }+  | matchDFS    Expr as Expr with '|' MatchClauses { MatchDFSExpr $2 $4 $7 }+  | matchAll    Expr as Expr with '|' MatchClauses { MatchAllExpr $2 $4 $7 }+  | matchAllDFS Expr as Expr with '|' MatchClauses { MatchAllDFSExpr $2 $4 $7 }+  | matchLambda      as Expr with '|' MatchClauses { MatchLambdaExpr $3 $6 }+  | matchAllLambda   as Expr with '|' MatchClauses { MatchAllLambdaExpr $3 $6 }++MatchClauses :: { [MatchClause] }+  : Pattern "->" Expr                               { [($1, $3)] }+  | MatchClauses '|' Pattern "->" Expr              { $1 ++ [($3, $5)] }++-- FIXME :+--   Uncommenting these 2 rules will yield shift/reduce conflict at+--       TopExpr -> var . '=' Expr+--       TopExpr -> var . list1__Arg__ '=' Expr+--       Atom -> var .+Arg :: { Arg }+  : '$' var                  { ScalarArg $2 }+  -- | var                      { ScalarArg $1 }+  | "*$" var                 { InvertedScalarArg $2 }+  -- | '%' var %prec TENSOR     { TensorArg $2 }++Atom :: { EgisonExpr }+  : int                      { IntegerExpr $1 }+  | var                      { VarExpr $ stringToVar $1 }+  | True                     { BoolExpr True }+  | False                    { BoolExpr False }+  | something                { SomethingExpr }+  | '(' sep2(Expr, ',') ')'  { TupleExpr $2 }+  | '[' sep(Expr, ',') ']'   { CollectionExpr (map ElementExpr $2) }+  | '(' Expr ')'             { $2 }+  | '[' Expr ".." Expr ']'   { makeApply (VarExpr $ stringToVar "between") [$2, $4] }++--+-- Patterns+--++Pattern :: { EgisonPattern }+  : '_'                        { WildCard }+  | '$' var                    { PatVar (stringToVar $2) }+  | '#' Atom                   { ValuePat $2 }+  | '(' sep2(Pattern, ',') ')' { TuplePat $2 }+  | Pattern ':' Pattern        { InductivePat "cons" [$1, $3] }+  | Pattern "++" Pattern       { InductivePat "join" [$1, $3] }++--+-- Helpers (Parameterized Products)+--++sep2(p, q)    : p q sep1(p, q)     { $1 : $3 }+sep1(p, q)    : p list(snd(q, p))  { $1 : $2 }+sep(p, q)     : sep1(p, q)         { $1 }+              |                    { [] }++snd(p, q)     : p q                { $2 }++list1(p)      : rev_list1(p)       { reverse $1 }+list(p)       : list1(p)           { $1 }+              |                    { [] }++rev_list1(p)  : p                  { [$1] }+              | rev_list1(p) p     { $2 : $1 }+ {+makeApply :: EgisonExpr -> [EgisonExpr] -> EgisonExpr+makeApply func xs = do+  let args = map (\x -> case x of+                          LambdaArgExpr s -> Left s+                          _               -> Right x) xs+  let vars = lefts args+  case vars of+    [] -> ApplyExpr func . TupleExpr $ rights args+    _ | all null vars ->+        let args' = rights args+            args'' = zipWith (curry f) args (annonVars 1 (length args))+            args''' = map (VarExpr . stringToVar . either id id) args''+        in ApplyExpr (LambdaExpr (map ScalarArg (rights args'')) (LambdaExpr (map ScalarArg (lefts args'')) $ ApplyExpr func $ TupleExpr args''')) $ TupleExpr args'+      | all (not . null) vars ->+        let n = Set.size $ Set.fromList vars+            args' = rights args+            args'' = zipWith (curry g) args (annonVars (n + 1) (length args))+            args''' = map (VarExpr . stringToVar . either id id) args''+        in ApplyExpr (LambdaExpr (map ScalarArg (rights args'')) (LambdaExpr (map ScalarArg (annonVars 1 n)) $ ApplyExpr func $ TupleExpr args''')) $ TupleExpr args'+ where+  annonVars m n = take n $ map ((':':) . show) [m..]+  f (Left _, var)  = Left var+  f (Right _, var) = Right var+  g (Left arg, _)  = Left (':':arg)+  g (Right _, var) = Right var+ lexwrap :: (Token -> Alex a) -> Alex a lexwrap = (alexMonadScan' >>=)  happyError :: Token -> Alex a-happyError (Token p t) =-  alexError' p ("parse error at token '" ++ show t ++ "'")+happyError (Token _ TokenEOF) = alexError "unexpected end of input"+happyError (Token p t) = alexError' p ("parse error at token '" ++ show t ++ "'")  readTopExprs :: String -> EgisonM [EgisonTopExpr]-readTopExprs = undefined+readTopExprs = either throwError (mapM desugarTopExpr) . parseTopExprs  readTopExpr :: String -> EgisonM EgisonTopExpr-readTopExpr = undefined+readTopExpr = either throwError desugarTopExpr . parseTopExpr  readExprs :: String -> EgisonM [EgisonExpr]-readExprs = undefined+readExprs = liftEgisonM . runDesugarM . either throwError (mapM desugar) . parseExprs  readExpr :: String -> EgisonM EgisonExpr-readExpr = undefined+readExpr = liftEgisonM . runDesugarM . either throwError desugar . parseExpr  parseTopExprs :: String -> Either EgisonError [EgisonTopExpr]-parseTopExprs = undefined+parseTopExprs = undefined -- runAlex' parseTopExprs_  parseTopExpr :: String -> Either EgisonError EgisonTopExpr-parseTopExpr = undefined+parseTopExpr = runAlex' parseTopExpr_  parseExprs :: String -> Either EgisonError [EgisonExpr] parseExprs = undefined  parseExpr :: String -> Either EgisonError EgisonExpr-parseExpr = undefined--- parseExpr = runAlex' parse--loadFile :: FilePath -> EgisonM [EgisonTopExpr]-loadFile = undefined+parseExpr = runAlex' parseExpr_ +-- |Load a libary file loadLibraryFile :: FilePath -> EgisonM [EgisonTopExpr]-loadLibraryFile = undefined+loadLibraryFile file = do+  homeDir <- liftIO getHomeDirectory+  doesExist <- liftIO $ doesFileExist $ homeDir ++ "/.egison/" ++ file+  if doesExist+    then loadFile $ homeDir ++ "/.egison/" ++ file+    else liftIO (getDataFileName file) >>= loadFile++-- |Load a file+loadFile :: FilePath -> EgisonM [EgisonTopExpr]+loadFile file = do+  doesExist <- liftIO $ doesFileExist file+  unless doesExist $ throwError $ Default ("file does not exist: " ++ file)+  input <- liftIO $ readUTF8File file+  exprs <- readTopExprs $ shebang input+  concat <$> mapM  recursiveLoad exprs+ where+  recursiveLoad (Load file)     = loadLibraryFile file+  recursiveLoad (LoadFile file) = loadFile file+  recursiveLoad expr            = return [expr]+  shebang :: String -> String+  shebang ('#':'!':cs) = ';':'#':'!':cs+  shebang cs           = cs }
hs-src/Language/Egison/Primitives.hs view
@@ -659,6 +659,7 @@                , ("read-file", readFile')                 , ("rand", randRange)+               , ("f.rand", randRangeDouble) --               , ("sqlite", sqlite)                ] @@ -749,6 +750,13 @@ randRange = twoArgs' $ \val val' -> do   i <- fromEgison val :: EgisonM Integer   i' <- fromEgison val' :: EgisonM Integer+  n <- liftIO $ getStdRandom $ randomR (i, i')+  return $ makeIO $ return $ toEgison n++randRangeDouble :: PrimitiveFunc+randRangeDouble = twoArgs' $ \val val' -> do+  i <- fromEgison val :: EgisonM Double+  i' <- fromEgison val' :: EgisonM Double   n <- liftIO $ getStdRandom $ randomR (i, i')   return $ makeIO $ return $ toEgison n 
lib/core/random.egi view
@@ -73,3 +73,11 @@        [$ [something]         {[$tgt {tgt}]}]        })))++(define $f.rands+  (lambda [$s $e]+    {(f.pure-rand s e) @(f.rands s e)}))++(define $f.pure-rand+  (lambda [$s $e]+    (io (f.rand s e))))
+ sample/five-color.egi view
@@ -0,0 +1,42 @@+;;;+;;; 5-color+;;;+++(define $node [integer (maybe integer)])+(define $graph (set [node (multiset node)]))++(define $colors (between 1 5))++(define $graph-data+  {[[1 Nothing] {[2 Nothing]}]+   [[2 Nothing] {[1 Nothing]}]})++(define $main+  (lambda [$graph-data]+    (match [colors graph-data] [(set integer) graph]+      {; 周りのノードでまだ5色全部使われていない場合.+       [[<cons $c _> <cons [[$id (nothing)] !<cons [_ (just ,c)] _>] _>]+        (main (assign-color id c graph-data))]+       ; 次数が5で周りで5色全部使われているノードしか残っていない場合.+       [[_ <cons [[$id (nothing)] <cons [$nid_1 (just $c_1)] <cons [$nid_2 (just $c_2)] <cons [$nid_3 (just $c_3)] <cons [$nid_4 (just $c_4)] <cons [$nid_5 (just $c_5)] <nil>>>>>>] _>]+        undefined]+       ; すべてのノードに色付け完了.+       [_ graph-data]+       })))++(define $assign-color+  (lambda [$id $c $graph-data]+    (map (lambda [$n]+           [(rewrite-node id c (2#%1 n)) (map (lambda [$n] (rewrite-node id c n)) (2#%2 n))])+         graph-data)))++(define $rewrite-node+  (lambda [$id $c $n]+    (match n node+      {[[,id (nothing)] [id (Just c)]]+       [_ n]})))++(rewrite-node 1 5 [1 Nothing]) ; [1 {5}]+(assign-color 1 5 graph-data) ; {[[1 {5}] {[2 {}]}] [[2 {}] {[1 {5}]}]}+(main graph-data) ; {[[1 {1}] {[2 {2}]}] [[2 {2}] {[1 {1}]}]}