added num and bool ops

This commit is contained in:
Yann Esposito (Yogsototh) 2017-02-25 23:05:01 +01:00
parent bd36b02931
commit d7feabece0
Signed by untrusted user who does not match committer: yogsototh
GPG key ID: 7B19A4C650D59646
4 changed files with 59 additions and 18 deletions

View file

@ -45,7 +45,7 @@ mainLoop env = do
Just "exit" -> outputStrLn "bye bye!" Just "exit" -> outputStrLn "bye bye!"
Just "logout" -> outputStrLn "bye bye!" Just "logout" -> outputStrLn "bye bye!"
Just line -> do Just line -> do
newenv <- eval env (parseCmd ("(" <> line <> ")")) newenv <- eval env (parseCmd ("(" <> toS line <> ")"))
mainLoop newenv mainLoop newenv
-- | Eval the reduced form -- | Eval the reduced form

View file

@ -90,6 +90,19 @@ atom ((Atom a):[]) = return $ Atom a
atom ((Str s):[]) = return $ Atom s atom ((Str s):[]) = return $ Atom s
atom _ = evalErr "atom need an atom or a string" atom _ = evalErr "atom need an atom or a string"
-- | Numbers Ops
binop :: (Integer -> Integer -> Integer) -> Command
binop f ((Num x):(Num y):[]) = return $ Num (f x y)
binop _ _ = evalErr "binary operator needs two numbers"
bbinop :: (Bool -> Bool -> Bool) -> Command
bbinop f ((Bool x):(Bool y):[]) = return $ Bool (f x y)
bbinop _ _ = evalErr "boolean binary operator need two booleans arguments"
lnot :: Command
lnot ((Bool x):[]) = return ( Bool (not x))
lnot _ = evalErr "not need a boolean"
toWaitingStream :: Command toWaitingStream :: Command
toWaitingStream (Stream (Just h) :[]) = return (WaitingStream (Just h)) toWaitingStream (Stream (Just h) :[]) = return (WaitingStream (Just h))
toWaitingStream _ = return Void toWaitingStream _ = return Void
@ -106,6 +119,16 @@ internalCommands = [ ("prn", prn)
, ("$",getenv) , ("$",getenv)
, ("str",str) , ("str",str)
, ("atom",atom) , ("atom",atom)
-- binary operators
, ("+",binop (+))
, ("-",binop (-))
, ("*",binop (*))
, ("/",binop div)
, ("^",binop (^))
-- boolean bin ops
, ("and", bbinop (&&))
, ("or", bbinop (||))
, ("not", lnot)
] & Map.fromList ] & Map.fromList
lookup :: Text -> Maybe Command lookup :: Text -> Maybe Command

View file

@ -5,36 +5,45 @@ module Lish.Parser
(parseCmd) (parseCmd)
where where
import Prelude (String) import Protolude hiding (for, many, (<|>), optional)
import Protolude hiding (for, many, (<|>))
import Text.Parsec import Text.Parsec
import Text.Parsec.Text
import Lish.Types import Lish.Types
parseCmd :: String -> Either ParseError SExp parseCmd :: Text -> Either ParseError SExp
parseCmd = parse parseExpr "S-Expr" parseCmd = parse parseExpr "S-Expr"
parseExpr :: Parsec String () SExp parseExpr :: Parser SExp
parseExpr = parseLambda parseExpr = parseLambda
<|> parseList <|> parseList
<|> parseBool
<|> parseNumber
<|> parseAtom <|> parseAtom
<|> parseString <|> parseString
parseAtom :: Parsec String () SExp parseNumber :: Parser SExp
parseNumber = (Num . fromMaybe 0 . readMaybe) <$> many1 digit
parseBool :: Parser SExp
parseBool = Bool <$> ((string "true" >> return True)
<|> (string "false" >> return False))
parseAtom :: Parser SExp
parseAtom = Atom <$> do frst <- (noneOf " \t()[]\"") parseAtom = Atom <$> do frst <- (noneOf " \t()[]\"")
rest <- many (noneOf " \t()[]") rest <- many (noneOf " \t()[]")
return $ toS (frst:rest) return $ toS (frst:rest)
parseString :: Parsec String () SExp parseString :: Parser SExp
parseString = (Str . toS) <$> between (char '"') parseString = (Str . toS) <$> between (char '"')
(char '"') (char '"')
(many (noneOf "\"")) (many (noneOf "\""))
parseSExps :: Parsec String () [SExp] parseSExps :: Parser [SExp]
parseSExps = sepEndBy parseExpr spaces parseSExps = sepEndBy parseExpr spaces
parseLambda :: Parsec String () SExp parseLambda :: Parser SExp
parseLambda = Lambda <$> between (char '(') (char ')') parseSExps parseLambda = Lambda <$> between (char '(') (char ')') parseSExps
parseList :: Parsec String () SExp parseList :: Parser SExp
parseList = List <$> between (char '[') (char ']') parseSExps parseList = List <$> between (char '[') (char ']') parseSExps

View file

@ -16,12 +16,18 @@ import GHC.IO.Handle (Handle)
import GHC.Show (Show (..)) import GHC.Show (Show (..))
import Protolude hiding (show) import Protolude hiding (show)
data SExp = Lambda [SExp] data SExp = Atom Text
| Atom Text | Num Integer
| List [SExp] | Bool Bool
| Str Text | Str Text
| List [SExp]
| Lambda [SExp]
| Void | Void
-- only exists during evaluation -- only exists during evaluation
| Fn { params :: [Text]
, body :: [SExp]
, closure :: Env
}
| Stream CmdStream | Stream CmdStream
| WaitingStream CmdStream | WaitingStream CmdStream
@ -29,11 +35,14 @@ instance Show SExp where
show = toS . repr show = toS . repr
repr :: SExp -> Text repr :: SExp -> Text
repr (Atom s) = s repr (Atom s) = s
repr (Str s) = "\"" <> toS s <> "\"" repr (Num n) = toS $ show n
repr (Lambda sexprs) = "(λ." <> (Text.intercalate " " (map repr sexprs)) <> ")" repr (Bool b) = if b then "true" else "false"
repr (List sexprs) = "[" <> (Text.intercalate " " (map repr sexprs)) <> "]" repr (Str s) = "\"" <> toS s <> "\""
repr Void = "ε" repr (List sexprs) = "[" <> (Text.intercalate " " (map repr sexprs)) <> "]"
repr (Lambda sexprs) = "(" <> (Text.intercalate " " (map repr sexprs)) <> ")"
repr Void = "ε"
repr (Fn p _ _) = "" <> (Text.intercalate "." p) <> ". ... )"
repr (Stream _) = "<stream>" repr (Stream _) = "<stream>"
repr (WaitingStream _) = "<w-stream>" repr (WaitingStream _) = "<w-stream>"