-- CSPSC 312 - 2024 - Reading in FValues
-- Copyright D. Poole 2024, released under the GPL.
module Features where

data FValue =  BooleanF Bool
             | NumberF Integer
             | StringF [Char]
             | MissingF
             | ErrorF
        deriving (Eq)
        
instance Show FValue where
    show (BooleanF b) = show b
    show (NumberF n)  = show n
    show (StringF s)  = '\"':s++"\""
    show MissingF     = "Missing"
    show ErrorF       = "Error"


flist = [BooleanF True, MissingF, NumberF 34, NumberF 22, StringF "wow"]

-- use readf (or readf.trim) instead of read for FValues
readf:: String -> FValue
readf "" = MissingF
readf "true" = BooleanF True
readf "True" = BooleanF True
readf "false" = BooleanF False
readf "False" = BooleanF False
readf st
   | all digit st = NumberF (read st)
   | head st == '-' && all digit (tail st)  = NumberF (read st)
   | otherwise = StringF st

digit :: Char -> Bool
digit ch = ch >= '0' && ch <= '9'

-- try:
-- readf "435"
-- readf "cs312"
-- readf ""

-- trim st   - removes blanks from beginning and end of st, and collapses mutliple spaces into one
trim :: String -> String
trim [] = []
trim (' ':t) = trim t
trim [x] = [x]
trim (x:" ") = [x]
trim (a:' ':' ':r) = trim (a:' ':r)
trim (a:' ':r) = a:' ':trim r
trim (h:t) = h :trim t


-- try
-- trim "   ab    cd   "
-- trim "   ab    cd   gh"

-- readtr means read from trimmed string
readtr = readf . trim


-- An example use of Fvalue for heterogenous use of addition
(&)  :: FValue -> FValue -> FValue
BooleanF x & BooleanF y = BooleanF (x && y)
NumberF x & NumberF y = NumberF (x+y)
StringF x & StringF y = StringF (x ++ y)
_ & _ = ErrorF

-- try
-- readf "17" & readf "23"
-- readf "cs" & readf "fun"
-- readf "True" & readf "False"
-- readf "cs" & readf "312"