module Math.Haskellator (calculate) where
import Control.Monad
import Math.Haskellator.Internal.AstProcessingSteps.Evaluate
import Math.Haskellator.Internal.AstProcessingSteps.Normalize
import Math.Haskellator.Internal.Expr
import Math.Haskellator.Internal.Lexer
import Math.Haskellator.Internal.Parser
import Math.Haskellator.Internal.Utils.Error
getAst :: String -> Either Error Expr
getAst :: String -> Either Error Expr
getAst = String -> Either Error Tokens
scan (String -> Either Error Tokens)
-> (Tokens -> Either Error Expr) -> String -> Either Error Expr
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Tokens -> Either Error Expr
parse (Tokens -> Either Error Expr)
-> (Expr -> Either Error Expr) -> Tokens -> Either Error Expr
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Expr -> Either Error Expr
normalize
calculate :: String
-> Either Error EvalValue
calculate :: String -> Either Error EvalValue
calculate String
input = do
Expr
ast <- String -> Either Error Expr
getAst String
input
Expr -> Either Error EvalValue
evaluateWithConv Expr
ast
evaluateWithConv :: Expr -> Either Error EvalValue
evaluateWithConv :: Expr -> Either Error EvalValue
evaluateWithConv = Expr -> Either Error EvalValue
ev where
ev :: Expr -> Either Error EvalValue
ev (Conversion Expr
expr Dimension
target) = do
EvalValue
r <- Expr -> Either Error EvalValue
execute Expr
expr
let baseV :: EvalValue
baseV = EvalValue -> EvalValue
convertDimensionToBase EvalValue
r
case EvalValue -> Dimension -> Maybe EvalValue
tryConvertDimensionTo EvalValue
baseV Dimension
target of
Just EvalValue
v -> EvalValue -> Either Error EvalValue
forall a. a -> Either Error a
forall (m :: * -> *) a. Monad m => a -> m a
return EvalValue
v
Maybe EvalValue
Nothing -> Error -> Either Error EvalValue
forall a b. a -> Either a b
Left (Error -> Either Error EvalValue)
-> Error -> Either Error EvalValue
forall a b. (a -> b) -> a -> b
$ Kind -> String -> Error
Error Kind
RuntimeError (String -> Error) -> String -> Error
forall a b. (a -> b) -> a -> b
$ String
"Cannot convert " String -> String -> String
forall a. [a] -> [a] -> [a]
++ EvalValue -> String
forall a. Show a => a -> String
show EvalValue
baseV String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" to " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Dimension -> String
forall a. Show a => a -> String
show Dimension
target
ev Expr
expr = Expr -> Either Error EvalValue
execute Expr
expr