module Math.REPL.Prim.Expr 
    ( Expr (..)
    , Operator (..)
    , constEq
    , isConst
    , joinMessage
    ) where

--------------------------------------------------------------------------------

-- | Represents an expression-tree
data Expr = Constant Double
          | Call String [Expr]
          | UnOp Operator Expr
          | BinOp (Expr, [(Operator, Expr)])
          | Variable String
          | Message [String]

-- | Represents an operator
data Operator = UnaryOp  (Double -> Double)
              | BinaryOp (Double -> Double -> Double)

--------------------------------------------------------------------------------

-- | Check whether two expressions are the same numeric value
-- assuming they have been evaluated fully
constEq :: Expr -> Expr -> Bool
constEq (Constant x) (Constant y) = x == y
constEq _ _                       = False

--------------------------------------------------------------------------------

-- | Checks whether an expression is a constant
isConst :: Expr -> Bool
isConst (Constant _) = True
isConst _            = False

--------------------------------------------------------------------------------

joinMessage :: Expr -> Expr -> Expr
joinMessage (Message e1) (Message e2) = Message (e1 ++ e2)
joinMessage m@(Message _) _           = m
joinMessage _ m@(Message _)           = m
joinMessage _ _ = error "joinMessage used on non-message Expr"

--------------------------------------------------------------------------------
