module PrimitiveValue where

import Data.Text (Text)
import qualified Parser.Ast as Ast

-- | Primitive value.
data PrimitiveValue num
  = -- | Number primitive.
    PrimNum num
  | -- | Boolean primitive.
    PrimBool Bool
  | -- | String primitive.
    PrimString Text
  deriving (Int -> PrimitiveValue num -> ShowS
forall num. Show num => Int -> PrimitiveValue num -> ShowS
forall num. Show num => [PrimitiveValue num] -> ShowS
forall num. Show num => PrimitiveValue num -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PrimitiveValue num] -> ShowS
$cshowList :: forall num. Show num => [PrimitiveValue num] -> ShowS
show :: PrimitiveValue num -> String
$cshow :: forall num. Show num => PrimitiveValue num -> String
showsPrec :: Int -> PrimitiveValue num -> ShowS
$cshowsPrec :: forall num. Show num => Int -> PrimitiveValue num -> ShowS
Show, PrimitiveValue num -> PrimitiveValue num -> Bool
forall num.
Eq num =>
PrimitiveValue num -> PrimitiveValue num -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PrimitiveValue num -> PrimitiveValue num -> Bool
$c/= :: forall num.
Eq num =>
PrimitiveValue num -> PrimitiveValue num -> Bool
== :: PrimitiveValue num -> PrimitiveValue num -> Bool
$c== :: forall num.
Eq num =>
PrimitiveValue num -> PrimitiveValue num -> Bool
Eq)

-- | Represents an unsuccessful operation application on primitive values.
data Err
  = -- | Mismatched types error.
    MismatchedTypes
  | -- | Division by 0 error.
    DivisionByZero

primitiveUnOpApplication :: Integral num => Ast.UnaryOp -> PrimitiveValue num -> Either Err (PrimitiveValue num)
primitiveUnOpApplication :: forall num.
Integral num =>
UnaryOp -> PrimitiveValue num -> Either Err (PrimitiveValue num)
primitiveUnOpApplication UnaryOp
unOp PrimitiveValue num
constant = case (UnaryOp
unOp, PrimitiveValue num
constant) of
  (UnaryOp
Ast.UnaryPlusOp, PrimNum num
c) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum num
c
  (UnaryOp
Ast.UnaryMinusOp, PrimNum num
c) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ -num
c
  (UnaryOp
Ast.NotOp, PrimBool Bool
c) -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not Bool
c
  (UnaryOp, PrimitiveValue num)
_ -> forall a b. a -> Either a b
Left Err
MismatchedTypes

primitiveBinOpApplication :: Integral num => Ast.BinaryOp -> PrimitiveValue num -> PrimitiveValue num -> Either Err (PrimitiveValue num)
primitiveBinOpApplication :: forall num.
Integral num =>
BinaryOp
-> PrimitiveValue num
-> PrimitiveValue num
-> Either Err (PrimitiveValue num)
primitiveBinOpApplication BinaryOp
binOp PrimitiveValue num
lhs PrimitiveValue num
rhs = case (BinaryOp
binOp, PrimitiveValue num
lhs, PrimitiveValue num
rhs) of
  -- Number
  (BinaryOp
Ast.EqOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Eq a => a -> a -> Bool
== num
rhs'
  (BinaryOp
Ast.NeOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Eq a => a -> a -> Bool
/= num
rhs'
  (BinaryOp
Ast.LeOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Ord a => a -> a -> Bool
<= num
rhs'
  (BinaryOp
Ast.LtOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Ord a => a -> a -> Bool
< num
rhs'
  (BinaryOp
Ast.MeOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Ord a => a -> a -> Bool
>= num
rhs'
  (BinaryOp
Ast.MtOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Ord a => a -> a -> Bool
> num
rhs'
  (BinaryOp
Ast.PlusOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Num a => a -> a -> a
+ num
rhs'
  (BinaryOp
Ast.MinusOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Num a => a -> a -> a
- num
rhs'
  (BinaryOp
Ast.MultOp, PrimNum num
lhs', PrimNum num
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Num a => a -> a -> a
* num
rhs'
  (BinaryOp
Ast.DivOp, PrimNum num
lhs', PrimNum num
rhs') -> if num
rhs' forall a. Eq a => a -> a -> Bool
== num
0 then forall a b. a -> Either a b
Left Err
DivisionByZero else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Integral a => a -> a -> a
`div` num
rhs'
  (BinaryOp
Ast.ModOp, PrimNum num
lhs', PrimNum num
rhs') -> if num
rhs' forall a. Eq a => a -> a -> Bool
== num
0 then forall a b. a -> Either a b
Left Err
DivisionByZero else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. num -> PrimitiveValue num
PrimNum forall a b. (a -> b) -> a -> b
$ num
lhs' forall a. Integral a => a -> a -> a
`mod` num
rhs'
  -- Boolean
  (BinaryOp
Ast.OrOp, PrimBool Bool
lhs', PrimBool Bool
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Bool
lhs' Bool -> Bool -> Bool
|| Bool
rhs'
  (BinaryOp
Ast.AndOp, PrimBool Bool
lhs', PrimBool Bool
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Bool
lhs' Bool -> Bool -> Bool
&& Bool
rhs'
  (BinaryOp
Ast.EqOp, PrimBool Bool
lhs', PrimBool Bool
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Bool
lhs' forall a. Eq a => a -> a -> Bool
== Bool
rhs'
  (BinaryOp
Ast.NeOp, PrimBool Bool
lhs', PrimBool Bool
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Bool
lhs' forall a. Eq a => a -> a -> Bool
/= Bool
rhs'
  -- String
  (BinaryOp
Ast.EqOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Eq a => a -> a -> Bool
== Text
rhs'
  (BinaryOp
Ast.NeOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Eq a => a -> a -> Bool
/= Text
rhs'
  (BinaryOp
Ast.LeOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Ord a => a -> a -> Bool
<= Text
rhs'
  (BinaryOp
Ast.LtOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Ord a => a -> a -> Bool
< Text
rhs'
  (BinaryOp
Ast.MeOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Ord a => a -> a -> Bool
>= Text
rhs'
  (BinaryOp
Ast.MtOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Bool -> PrimitiveValue num
PrimBool forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Ord a => a -> a -> Bool
> Text
rhs'
  (BinaryOp
Ast.PlusOp, PrimString Text
lhs', PrimString Text
rhs') -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall num. Text -> PrimitiveValue num
PrimString forall a b. (a -> b) -> a -> b
$ Text
lhs' forall a. Semigroup a => a -> a -> a
<> Text
rhs'
  (BinaryOp, PrimitiveValue num, PrimitiveValue num)
_ -> forall a b. a -> Either a b
Left Err
MismatchedTypes