packages feed

lhae-0.0.2: src/Model/CellExpression/Evaluator.hs

module Model.CellExpression.Evaluator (evaluate,Lookup)
    where

import Prelude hiding (lookup)
import Control.Applicative ((<$>))
import Control.Monad (forM)
import Model.CellContent (CellExpr (..),CellValue(..),RuntimeReason(..)
                         ,Reference(..),Symbol)
import Model.CellExpression.Evaluator.Common 
    (withNum,withList,withNumList,getNumList,fLength)
import Model.CellExpression.Evaluator.Math (mean,median)

type Lookup = Reference -> IO CellValue

evaluate :: Lookup -> CellExpr -> IO CellValue
evaluate lookup e =
    let binary f = return . mathBinary f
        eval = evaluate lookup
    in
      case e of
        EmptyExpr -> return $ EmptyValue
        NumberExpr a -> return $ NumberValue a
        StringExpr a -> return $ StringValue a
        ListExpr a -> ListValue <$> forM a eval
        Reference a -> lookup a
        UnaryOp "-" a -> forM [NumberExpr 0,a] eval >>= binary (-)
        BinaryOp "+" a b -> forM [a,b] eval >>= binary (+)
        BinaryOp "-" a b -> forM [a,b] eval >>= binary (-)
        BinaryOp "*" a b -> forM [a,b] eval >>= binary (*)
        BinaryOp "/" a b -> forM [a,b] eval >>= binary (/)
        BinaryOp "^" a b -> forM [a,b] eval >>= binary (**)
        Call f arg -> evaluateFun f <$> eval arg
        Sub a -> eval a
        NamedReference _ -> error "Model.CellExpression.Evaluator.evaluate: NamedReference"
        CompileErrorExpr a -> return $ Error $ CompileError a

evaluateFun :: Symbol -> CellValue -> CellValue
evaluateFun f arg = 
    case f of
      "sum" -> withNumList arg $ NumberValue . sum
      "count" -> withList arg $ NumberValue . fLength
      "abs" -> withNum arg $ NumberValue . abs
      "mean" -> withNumList arg $ NumberValue . mean
      "median" -> withNumList arg $ NumberValue . median
      unknown -> Error $ UnknownIdentifier unknown

mathBinary :: (Double -> Double -> Double) -> [CellValue] -> CellValue
mathBinary f = 
    either Error (\[a,b] -> NumberValue $ f a b) . getNumList