fork download
  1. module Main where
  2. import Data.Map as Map
  3.  
  4. data Runnable
  5. = Name String
  6. | Add Runnable Runnable
  7. | Block (Map String Runnable) Runnable
  8. | I Integer
  9. deriving (Eq, Ord, Show)
  10.  
  11. run :: Runnable -> Map String Runnable -> Either [String] Integer
  12. -- Instances
  13. -- Integers resolve to Right Integer
  14. run (I v) _ = Right v
  15. -- For Names
  16. -- look up their expression in the scope, then evaluate
  17. -- if name is out of scope, raise an error
  18. run (Name n) s = which (Map.lookup n s) where
  19. which Nothing = Left ["Variable not in scope: " ++ n]
  20. which (Just v) = run v s
  21. -- For Addition
  22. -- Run a, Run b, Add their results
  23. -- Raise appropriate errors where necessary
  24. run (Add a b) s = geta (run a s) where
  25. geta (Left es) = Left (es ++ ["In lhs of expression: " ++ show (Add a b)])
  26. geta (Right a') = getb a' (run b s)
  27. getb _ (Left es) = Left (es ++ ["In rhs of expression: " ++ show (Add a b)])
  28. getb a' (Right b') = Right (a' + b')
  29. -- For Blocks
  30. -- Run the block's expression under a new scope
  31. -- (merging the current with the block's scope definition)
  32. run (Block s' e) s = result $ run e (Map.union s' s) where
  33. result (Left es) = Left (es ++ ["In block: " ++ show (Block s' e)])
  34. result (Right v) = Right v
  35.  
  36. instance Num Runnable where
  37. (+) = undefined
  38. (-) = undefined
  39. (*) = undefined
  40. negate = undefined
  41. signum = undefined
  42. fromInteger = I
  43.  
  44. main = mapM_ print
  45. [ run 5 Map.empty
  46. , run (Name "a") Map.empty
  47. , run (Name "a") (fromList [("a", 6)])
  48. , run (Add 6 3) Map.empty
  49. , run (Add (Name "a") 7) (fromList [("a", 10)])
  50. , run (Block (fromList [("a", 10)]) (Name "a")) Map.empty
  51. ]
Success #stdin #stdout 0.01s 3584KB
stdin
Standard input is empty
stdout
Right 5
Left ["Variable not in scope: a"]
Right 6
Right 9
Right 17
Right 10