aboutsummaryrefslogtreecommitdiffstats
path: root/src/Lib.hs
diff options
context:
space:
mode:
authorJan Tuomi <jan.tuomi@valuemotive.com>2022-09-24 14:36:37 +0300
committerJan Tuomi <jans.tuomi@gmail.com>2022-12-05 14:21:53 +0200
commit95fa4b4de7027749a6512def696d07ed64217b50 (patch)
tree699738c9aecf7a2830656e137bdcc1175bff31e1 /src/Lib.hs
parent5995f723058c5152980fb74034ad8f4d8bbd7a99 (diff)
Implement match
Diffstat (limited to 'src/Lib.hs')
-rw-r--r--src/Lib.hs27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/Lib.hs b/src/Lib.hs
index 569d5f5..e5ea214 100644
--- a/src/Lib.hs
+++ b/src/Lib.hs
@@ -242,7 +242,7 @@ evaluate :: Env -> AST -> LContext AST
evaluate env (ASTFunctionCall (first:args))
| first == ASTSymbol "\\" = do
(arg1, arg2) <- case args of
- [a, b] -> return (a, b)
+ [arg1', arg2'] -> return (arg1', arg2')
_ -> throwError $ LException $ "\\ called with " ++ show (length args) ++ " arguments"
(ASTVector params') <- assertVectorAST arg1
params <- mapM assertSymbolAST params'
@@ -250,8 +250,29 @@ evaluate env (ASTFunctionCall (first:args))
body <- assertFunctionCallAST arg2
let fn = curriedMakeUserDefFn env params body
return $ ASTFunction fn
- | first == ASTSymbol "match" =
- throwError $ LException "match not implemented"
+ | first == ASTSymbol "match" = do
+ (cond, rest) <- case args of
+ [] -> throwError $ LException $ "match called with no arguments"
+ (_:[]) -> throwError $ LException $ "Empty match cases"
+ (cond':rest') -> return (cond', rest')
+ if length rest `mod` 2 == 0
+ then do
+ caseMatchers <- oddElems rest $> mapM (evaluate env)
+ let caseBranches = evenElems rest
+ let caseMap = M.fromList $ L.zip caseMatchers caseBranches
+ evaledCond <- evaluate env cond
+ case M.lookup evaledCond caseMap of
+ Just branch -> evaluate env branch
+ Nothing -> throwError $ LException $ "matching case not found, condition " ++ show cond
+ else do
+ let (defaultBranch:revCases) = reverse rest
+ caseMatchers <- oddElems (reverse revCases) $> mapM (evaluate env)
+ let caseBranches = evenElems (reverse revCases)
+ let caseMap = M.fromList $ L.zip caseMatchers caseBranches
+ evaledCond <- evaluate env cond
+ case M.lookup evaledCond caseMap of
+ Just branch -> evaluate env branch
+ Nothing -> evaluate env defaultBranch
| otherwise = do
fnEvaled <- evaluate env first
(ASTFunction fn) <- assertFunctionAST fnEvaled