{- | Module: Util Description: Utility functions used throughout Ion Copyright: (c) 2015 Chris Hodapp -} module Ivory.Language.Ion.Util where import Data.Char ( isAlpha, isDigit ) import Ivory.Language import Ivory.Language.Proc ( Def(..), IvoryCall_ ) import qualified Ivory.Language.Syntax.AST as AST import qualified Ivory.Language.Syntax.Type as Ty -- | Return the symbol name of an Ivory procedure procName :: Def proc -> String procName def = case def of DefProc p -> AST.procSym p DefImport i -> AST.importSym i -- | Return the Ivory unsigned int type (in its AST) that the given 'Integer' -- would require (i.e. any value from 0 to 255 returns a 'Ty.Word8'; values -- beyond that but less than 65535 require a 'Ty.Word16'; and so on.) -- The given integer must be non-negative. fitWordType :: Integer -> Ty.Type fitWordType i = if (i < 0) then error ("fitWordType: Integer " ++ show i ++ " is negative.") else if (i < 2^8) then Ty.TyWord Ty.Word8 else if (i < 2^16) then Ty.TyWord Ty.Word16 else if (i < 2^32) then Ty.TyWord Ty.Word32 else if (i < 2^64) then Ty.TyWord Ty.Word64 else error ("fitWordType: Integer " ++ show i ++ " is too large.") -- | Checks the given string for being a valid C identifier. If it is, then -- it returns 'Nothing', and otherwise 'Just' and the string index of the -- character which renders it invalid. checkCName :: String -> Maybe Int checkCName [] = Just 0 -- empty identifier is not allowed checkCName str = check str 0 where check :: String -> Int -> Maybe Int check [] _ = Nothing check (c:cs) i = if (isAlpha c || '_' == c || (i > 0 && isDigit c)) then check cs (i + 1) else Just i