aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Eval.hs39
-rw-r--r--src/Helper.hs2
-rw-r--r--src/Parser.hs20
-rw-r--r--src/Reducer.hs4
4 files changed, 58 insertions, 7 deletions
diff --git a/src/Eval.hs b/src/Eval.hs
index 47ca4ca..c65bf0e 100644
--- a/src/Eval.hs
+++ b/src/Eval.hs
@@ -47,6 +47,14 @@ evalDefine name exp =
Right f -> modify ((name, f) :) >> pure (Right f)
)
+evalTest :: Expression -> Expression -> Program (Failable Instruction)
+evalTest exp1 exp2 =
+ evalExp exp1
+ >>= (\case
+ Left exp1 -> pure $ Left exp1
+ Right exp1 -> fmap (Test exp1) <$> evalExp exp2
+ )
+
eval :: [String] -> Environment -> IO Environment
eval [] env = pure env
eval (line : ls) env = case parse parseLine "FILE" line of
@@ -56,7 +64,21 @@ eval (line : ls) env = case parse parseLine "FILE" line of
let (res, env') = evalDefine name exp `runState` env
in case res of
Left err -> print err >> eval ls env'
- Right _ -> (putStrLn $ name <> " = " <> show exp) >> eval ls env'
+ Right _ -> eval ls env'
+ Test exp1 exp2 ->
+ let (res, _) = evalTest exp1 exp2 `runState` env
+ in case res of
+ Left err -> putStrLn (show err) >> pure env
+ Right (Test exp1' exp2') ->
+ when
+ (reduce exp1' /= reduce exp2')
+ ( putStrLn
+ $ "ERROR: test failed: "
+ <> (show exp1)
+ <> " != "
+ <> (show exp2)
+ )
+ >> eval ls env
_ -> eval ls env
evalFunc :: String -> Environment -> IO Environment
@@ -65,6 +87,7 @@ evalFunc func env = case lookup func env of
Just exp -> (print $ reduce exp) >> pure env
-- TODO: Less duplicate code (liftIO?)
+-- TODO: Generally improve eval code
evalRepl :: String -> Environment -> InputT IO Environment
evalRepl line env = case parse parseReplLine "REPL" line of
Left err -> outputStrLn (show err) >> pure env
@@ -97,6 +120,20 @@ evalRepl line env = case parse parseReplLine "REPL" line of
Left exception -> print (exception :: IOError) >> pure env
Right file -> eval (filter (not . null) $ lines file) [] >>= pure
)
+ Test exp1 exp2 ->
+ let (res, _) = evalTest exp1 exp2 `runState` env
+ in case res of
+ Left err -> outputStrLn (show err) >> pure env
+ Right (Test exp1' exp2') ->
+ when
+ (reduce exp1' /= reduce exp2')
+ ( outputStrLn
+ $ "ERROR: test failed: "
+ <> (show exp1)
+ <> " != "
+ <> (show exp2)
+ )
+ >> pure env
_ -> pure env
evalFile :: String -> IO ()
diff --git a/src/Helper.hs b/src/Helper.hs
index 5e02a94..57fb9f4 100644
--- a/src/Helper.hs
+++ b/src/Helper.hs
@@ -14,7 +14,7 @@ type Failable = Either Error
data Expression = Bruijn Int | Variable String | Abstraction Expression | Application Expression Expression
deriving (Ord, Eq)
-data Instruction = Define String Expression | Evaluate Expression | Comment String | Load String
+data Instruction = Define String Expression | Evaluate Expression | Comment String | Load String | Test Expression Expression
deriving (Show)
instance Show Expression where
show (Bruijn x ) = show x
diff --git a/src/Parser.hs b/src/Parser.hs
index 6fbeca4..33b3c44 100644
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -6,7 +6,7 @@ module Parser
import Control.Monad ( ap )
import Data.Functor.Identity
import Helper
-import Text.Parsec
+import Text.Parsec hiding ( parseTest )
import Text.Parsec.Language
import qualified Text.Parsec.Token as Token
@@ -107,9 +107,23 @@ parseComment = string "#" >> Comment <$> almostAnything
parseLoad :: Parser Instruction
parseLoad = string ":load " >> Load <$> almostAnything
+parseTest :: Parser Instruction
+parseTest = do
+ string ":test "
+ exp1 <- parseExpression
+ spaces
+ reservedOp "="
+ spaces
+ exp2 <- parseExpression
+ pure $ Test exp1 exp2
+
parseLine :: Parser Instruction
-parseLine = try parseDefine <|> parseComment
+parseLine = try parseDefine <|> try parseComment <|> try parseTest
parseReplLine :: Parser Instruction
parseReplLine =
- try parseReplDefine <|> parseComment <|> parseEvaluate <|> parseLoad
+ try parseReplDefine
+ <|> try parseComment
+ <|> try parseEvaluate
+ <|> try parseLoad
+ <|> try parseTest
diff --git a/src/Reducer.hs b/src/Reducer.hs
index 809687b..a7c544a 100644
--- a/src/Reducer.hs
+++ b/src/Reducer.hs
@@ -20,11 +20,11 @@ bind :: Expression -> Expression -> Int -> Expression
bind exp (Bruijn x) n = if x == n then exp else Bruijn x
bind exp (Application exp1 exp2) n =
Application (bind exp exp1 n) (bind exp exp2 n)
-bind exp (Abstraction exp') n = Abstraction (bind (exp <-> 0) exp' (succ n))
+bind exp (Abstraction exp') n = Abstraction (bind (exp <-> (-1)) exp' (succ n))
step :: Expression -> Expression
step (Bruijn exp ) = Bruijn exp
-step (Application (Abstraction exp) app ) = (bind (app <-> 0) exp 0) <+> 0
+step (Application (Abstraction exp) app ) = (bind (app <-> (-1)) exp 0) <+> 0
step (Application exp1 exp2) = Application (step exp1) (step exp2)
step (Abstraction exp ) = Abstraction (step exp)