/Leibniz.hs

https://github.com/jvranish/Leibniz · Haskell · 89 lines · 70 code · 17 blank · 2 comment · 2 complexity · 087e185dfa3bd329e2bc14dbf05ef709 MD5 · raw file

  1. module Main where
  2. import System( getArgs )
  3. import Prelude hiding (lookup)
  4. import Data.Maybe
  5. import Data.Map hiding (update, map, null)
  6. import Text.Parsec.String
  7. import Control.Monad.Error
  8. -- http://en.wikipedia.org/wiki/Gottfried_Leibniz#Information_technology
  9. -- http://notvincenz.blogspot.com/2008/01/simple-type-inference-in-haskell.html
  10. import LeibnizExpr
  11. import LeibnizParser
  12. import LeibnizBuiltIns
  13. errorMsg :: ParsedExpr -> String -> String
  14. errorMsg parsedExpr msg = "Error: " ++ msg ++ ", at " ++ (show $ getPos parsedExpr) ++ "\n"
  15. evaluateExpr :: Closure -> [ParsedExpr] -> ParsedExpr -> ParsedExpr
  16. evaluateExpr closure stack parsedExpr = evaluateExpr' $ getExpr parsedExpr
  17. where
  18. evaluateExpr' (Apply a b) = evaluateExpr closure (evaluateExpr closure [] b : stack) a
  19. evaluateExpr' (Constructor stuff name) = newExpr (Constructor (stuff ++ stack) name)
  20. evaluateExpr' (Id name) = maybe (evalError ("Id '" ++ name ++ "' not found in context: " ++ show closure ++ "\n")) (evaluateExpr closure stack) $ lookup name closure
  21. evaluateExpr' (Undefined _) = parsedExpr -- to avoid problems if stack is not null
  22. evaluateExpr' (Literal (BuiltIn _ f))
  23. | not $ null stack = applyBuiltin f $ getExpr topOfStack
  24. evaluateExpr' _ | null stack = parsedExpr
  25. evaluateExpr' (FunctionDef x@(Equation patterns _) xs newClosure)
  26. | length stack >= length patterns = fromMaybe (evalError "pattern match failure") $ firstJust $ map (matchEquation (union newClosure closure) stack) (x:xs)
  27. evaluateExpr' (FunctionDef _ _ _) = evalError "Not enough parameters to evaluate function"
  28. evaluateExpr' x = evalError $ "Attempt to apply: " ++ (show . getExpr . head $ stack) ++ ", to nonfunction: " ++ show x ++ "\n"
  29. evalError = newExpr . Undefined . errorMsg parsedExpr
  30. topOfStack = evaluateExpr closure [] (head stack)
  31. applyBuiltin _ (Undefined _) = topOfStack
  32. applyBuiltin f _ = evaluateExpr closure (tail stack) (f topOfStack)
  33. newExpr = subsExpr parsedExpr
  34. matchEquation :: Closure -> [ParsedExpr] -> Equation ParsedExpr -> Maybe ParsedExpr
  35. matchEquation closure stack (Equation patterns expr) = let evalRightSide newClosure = evaluateExpr (union newClosure closure) (drop (length patterns) stack) expr in
  36. either Just (Just . evalRightSide . fromList =<<) (collectMatches $ zipWith (match []) patterns stack)
  37. collectMatches :: (Error a) => [Either a (Maybe [b])] -> Either a (Maybe [b])
  38. collectMatches = foldr (liftM2 $ liftM2 mplus) (Right $ Just [])
  39. match :: [ParsedExpr] -> ParsedExpr -> ParsedExpr -> Either ParsedExpr (Maybe [(String, ParsedExpr)])
  40. match stuff parsedPattern parsedExpr = match' (getExpr parsedPattern) (getExpr parsedExpr)
  41. where
  42. match' (Id name) _ = Right $ Just [(name, parsedExpr)]
  43. match' (Apply a b) _ = match (b:stuff) a parsedExpr
  44. match' (Constructor _ a) (Constructor otherStuff b) | a == b = collectMatches $ zipWith (match []) stuff otherStuff
  45. match' _ (Undefined _) = Left parsedExpr
  46. match' pattern expr | pattern == expr = Right $ Just []
  47. match' _ _ = Right Nothing --pattern match fail
  48. firstJust :: [Maybe a] -> Maybe a
  49. firstJust (Nothing:xs) = firstJust xs
  50. firstJust (x:_) = x
  51. firstJust [] = Nothing
  52. moduleToClosure :: ParsedModule -> Closure
  53. moduleToClosure parsedModule = fromList [(name, value) | Definition name value <- map nodeExpr $ moduleDefs $ nodeExpr parsedModule]
  54. evaluateMain :: ParsedModule -> Either String ParsedExpr
  55. evaluateMain parsedModule = let topLevel = union (moduleToClosure parsedModule) builtIns in
  56. (maybeToError "main function is not defined in module.\n" $ lookup "main" topLevel) >>= (Right . evaluateExpr topLevel [])
  57. maybeToError :: e -> Maybe a -> Either e a
  58. maybeToError _ (Just a) = Right a
  59. maybeToError e Nothing = Left e
  60. parseArg :: (Monad m) => [a] -> m a
  61. parseArg [] = fail "Please pass in a file"
  62. parseArg (x:_) = return x
  63. main :: IO ()
  64. main = do
  65. args <- getArgs
  66. fileName <- parseArg args
  67. parsedModuleOrError <- parseFromFile parseSource fileName
  68. either putStrLn print $ either (Left . show) Right parsedModuleOrError >>= evaluateMain
  69. testParse :: IO ()
  70. testParse = parseFromFile parseSource "test.v" >>= either print print
  71. testEval :: IO ()
  72. testEval = parseFromFile parseSource "test.v" >>= either print (print . evaluateMain)