å æ¥ã®ã¤ã¥ãã
æ°æã¡ã¨ãã¦ã¯ãç¿æ¥ã«ãã¢ãããããã£ããã®ã®ãäºæ³ä»¥ä¸ã«ã¯ã¾ããã¨ã«ãªããã¨ããããHaskellå¿ããããè³ã®Haskelléã®æ´»åãå¼±ããªã£ã¦ã¾ãã
ä¸çªããã£ãã®ãã·ã³ãã«ã«ãªã¹ãã¨å®å¼æ°ã®ãªã¹ããããè¾æ¸ãä½ãå¼ã
ss = [SYMBOL "x", SYMBOL "y", SYMBOL "z"]
ã¨
vs = [1, 2, 3]
ãã
[("x",1),("y",2),("z",3)]
ãä½ãããã£ããã§ãããæåã«æ¸ããå¼ãããã
[(s, v) | SYMBOL s <- ss, v <- vs]
ãã¾è¦ãã¨åæ©çãªééãããã¦é ããããããªãã¾ãããããè©ä¾¡ããã¨ss
ã¨vs
ã®ç´ç©ãä½ã£ã¦ãã¾ãã¾ããå½ç¶ã
æ£ããã¯ããã§ããã
[(s, v) | (SYMBOL s, v) <- zip ss vs]
ããã«æ°ä»ãã®ã«ä¸¸ä¸æ¥ä»¥ä¸ããã£ããªãã¦ãã©ãã ãå¼±ã£ã¦ããã ãªã¬ã®Haskelléãã¨ããæ°å
以ä¸ã³ã¼ãã
ããããããããªæãããã¾ããããããã¦ããã¾ãã
ï¼ãã¡ãã«ãæ ¼ç´ï¼gist:775233 · GitHubï¼
module Main where import IO type Function = [Atom] -> Atom type Env = [(String, Atom)] data Atom = INT Integer | REAL Double | BOOL Bool | SYMBOL String | LIST [Atom] | PROC Atom Atom | FUNCTION Function toString (INT i) = show i toString (REAL r) = show r toString (BOOL b) = show b toString (SYMBOL s) = s toString (LIST xs) = '(':' ':(toString' xs) where toString' [] = ")" toString' (x:xs) = (toString x) ++ ' ':(toString' xs) toString (PROC vars exp) = "proc " ++ (toString vars) ++ " " ++ (toString exp) toString (FUNCTION _) = "function" lisp_add [INT x, INT y] = INT (x + y) lisp_add [INT x, REAL y] = REAL (fromInteger x + y) lisp_add [REAL x, INT y] = REAL (x + fromInteger y) lisp_add [REAL x, REAL y] = REAL (x + y) lisp_sub [INT x, INT y] = INT (x - y) lisp_sub [INT x, REAL y] = REAL (fromInteger x - y) lisp_sub [REAL x, INT y] = REAL (x - fromInteger y) lisp_sub [REAL x, REAL y] = REAL (x - y) lisp_mul [INT x, INT y] = INT (x * y) lisp_mul [INT x, REAL y] = REAL (fromInteger x * y) lisp_mul [REAL x, INT y] = REAL (x * fromInteger y) lisp_mul [REAL x, REAL y] = REAL (x * y) lisp_div [INT x, INT y] = INT (x `div` y) lisp_div [INT x, REAL y] = REAL (fromInteger x / y) lisp_div [REAL x, INT y] = REAL (x / fromInteger y) lisp_div [REAL x, REAL y] = REAL (x / y) lisp_not [BOOL x] = BOOL (not x) lisp_gt [INT x, INT y] = BOOL (x > y) lisp_gt [INT x, REAL y] = BOOL (fromInteger x > y) lisp_gt [REAL x, INT y] = BOOL (x > fromInteger y) lisp_gt [REAL x, REAL y] = BOOL (x > y) lisp_gt [BOOL x, BOOL y] = BOOL (x > y) lisp_gt [SYMBOL x, SYMBOL y] = BOOL (x > y) lisp_lt [INT x, INT y] = BOOL (x < y) lisp_lt [INT x, REAL y] = BOOL (fromInteger x < y) lisp_lt [REAL x, INT y] = BOOL (x < fromInteger y) lisp_lt [REAL x, REAL y] = BOOL (x < y) lisp_lt [SYMBOL x, SYMBOL y] = BOOL (x < y) lisp_ge [INT x, INT y] = BOOL (x >= y) lisp_ge [INT x, REAL y] = BOOL (fromInteger x >= y) lisp_ge [REAL x, INT y] = BOOL (x >= fromInteger y) lisp_ge [REAL x, REAL y] = BOOL (x >= y) lisp_ge [BOOL x, BOOL y] = BOOL (x >= y) lisp_ge [SYMBOL x, SYMBOL y] = BOOL (x >= y) lisp_le [INT x, INT y] = BOOL (x <= y) lisp_le [INT x, REAL y] = BOOL (fromInteger x <= y) lisp_le [REAL x, INT y] = BOOL (x <= fromInteger y) lisp_le [REAL x, REAL y] = BOOL (x <= y) lisp_le [SYMBOL x, SYMBOL y] = BOOL (x <= y) lisp_eq [INT x, INT y] = BOOL (x == y) lisp_eq [INT x, REAL y] = BOOL (fromInteger x == y) lisp_eq [REAL x, INT y] = BOOL (x == fromInteger y) lisp_eq [REAL x, REAL y] = BOOL (x == y) lisp_eq [SYMBOL x, SYMBOL y] = BOOL (x == y) lisp_length [LIST x] = INT (toInteger $ length x) lisp_cons [x, LIST xs] = LIST (x:xs) lisp_car [LIST (x:xs)] = x lisp_cdr [LIST (x:xs)] = LIST xs lisp_append [LIST x, LIST y] = LIST (x ++ y) lisp_list x = LIST x lisp_islist [LIST x] = BOOL True lisp_islist _ = BOOL False lisp_isnull [LIST []] = BOOL True lisp_isnull [LIST _] = BOOL False lisp_issymbol [SYMBOL _] = BOOL True lisp_issymbol _ = BOOL False toAtom fn = FUNCTION fn global_env :: Env global_env = [ ("+", toAtom lisp_add), ("-", toAtom lisp_sub), ("*", toAtom lisp_mul), ("/", toAtom lisp_div), ("not", toAtom lisp_not), (">", toAtom lisp_gt), ("<", toAtom lisp_lt), (">=", toAtom lisp_ge), ("<=", toAtom lisp_le), ("=", toAtom lisp_eq), ("equal?", toAtom lisp_eq), ("length", toAtom lisp_length), ("cons", toAtom lisp_cons), ("car", toAtom lisp_car), ("cdr", toAtom lisp_cdr), ("append", toAtom lisp_append), ("list", toAtom lisp_list), ("list?", toAtom lisp_islist), ("null?", toAtom lisp_isnull), ("symbol?", toAtom lisp_issymbol) ] lisp_if (BOOL True, _) conseq _ = conseq lisp_if (BOOL False, _) _ alt = alt eval (INT i) env = (INT i, env) eval (REAL r) env = (REAL r, env) eval (BOOL b) env = (BOOL b, env) eval (SYMBOL s) env = (case (lookup s env) of Just a -> (a, env)) eval (LIST ((SYMBOL "quote"):a:[])) env = (a, env) eval (LIST ((SYMBOL "if"):t:c:a:[])) env = eval (lisp_if (eval t env) c a) env eval (LIST ((SYMBOL "set!"):(SYMBOL s):v:[])) env = case (lookup s env) of Just _ -> let (r, _) = eval v env in (r, (s, r):env) eval (LIST ((SYMBOL "define"):(SYMBOL s):v:[])) env = let (r, _) = eval v env in (r, (s, r):env) eval (LIST ((SYMBOL "lambda"):a:e:[])) env = (PROC a e, env) eval (LIST ((SYMBOL "begin"):as)) env = foldl (\(_, e) a -> (eval a e)) (LIST [], env) as eval (LIST as) env = case v of PROC as exp -> (evalProc as vs exp env, env) FUNCTION fn -> (fn vs, env) _ -> error $ "ERROR:" ++ (toString v) where ((v:vs), e) = eval' [] as env eval' r [] env = (r, env) eval' r (a:as) env = let (v, new_env) = eval a env in eval' (r ++ [v]) as new_env evalProc (LIST ss) ps exp env = fst $ eval exp ([(s, p) | (SYMBOL s, p) <- zip ss ps] ++ env) atom token = catch (do { i <- readIO token :: IO Integer; return $ INT i }) (\_ -> catch (do { r <- readIO token :: IO Double; return $ REAL r}) (\_ -> return $ SYMBOL token)) read_from :: [String] -> IO Atom read_from ts = do (result, _) <- read_from' ts return result read_from' :: [String] -> IO (Atom, [String]) read_from' ("(":ts) = read_list [] ts read_from' (")":ts) = error "unexpected" read_from' (t:ts) = do { a <- atom t; return (a, ts) } read_list :: [Atom] -> [String] -> IO (Atom, [String]) read_list as (")":ts) = return (LIST as, ts) read_list as ts = do (atom, rest) <- read_from' ts read_list (as ++ [atom]) rest tokenize s = words $ tokenize_ s where tokenize_ "" = "" tokenize_ ('(':ss) = ' ':'(':' ':(tokenize_ ss) tokenize_ (')':ss) = ' ':')':' ':(tokenize_ ss) tokenize_ (s:ss) = s:(tokenize_ ss) parse :: String -> IO Atom parse s = read_from $ tokenize s repl prompt env = do putStr prompt hFlush stdout atom <- parse =<< getLine let (result, new_env) = eval atom env putStrLn $ toString result repl prompt new_env main = repl "lis.hs> " global_env
å®è¡çµæã
$ ./lis lis.hs> (+ 1 2) 3 lis.hs> (- 2 3) -1 lis.hs> (* (+ 3 4) (/ 9 3)) 21 lis.hs> (quote (1 2 3)) ( 1 2 3 ) lis.hs> (< 1 2) True lis.hs> (> 1 2) False lis.hs> (list 1 2 3) ( 1 2 3 ) lis.hs> (car (quote (1 2 3))) 1 lis.hs> (cdr (quote (1 2 3))) ( 2 3 ) lis.hs> (cons 1 (quote (2 3))) ( 1 2 3 ) lis.hs> (define x2 (lambda (x) (* x 2))) proc ( x ) ( * x 2 ) lis.hs> (x2 10) 20 lis.hs> (define add (lambda (x y) (+ x y))) proc ( x y ) ( + x y ) lis.hs> (add 1 10) 11