content: {-# LANGUAGE DeriveGeneric #-}
  
  module Kit.Ast.Definitions.VarDefinition where
  
  import Control.Monad
  import Data.Hashable
  import GHC.Generics
  import Kit.Ast.Definitions.Base
  import Kit.Ast.Metadata
  import Kit.Ast.Modifier
  import Kit.Ast.TypePath
  import Kit.Ast.Span
  import Kit.Str
  
  data VarDefinition a b = VarDefinition {
    varName :: TypePath,
    varBundle :: Maybe TypePath,
    varPos :: Span,
    varMeta :: [Metadata],
    varModifiers :: [Modifier],
    varType :: b,
    varDefault :: Maybe a,
    varIsLocal :: Bool,
    varIsConst :: Bool
  } deriving (Eq, Generic, Show)
  
  instance Positioned (VarDefinition a b) where
    position = varPos
  
  instance (Hashable a, Hashable b) => Hashable (VarDefinition a b)
  
  varRealName f =
    if hasNoMangle (varMeta f) then ([], tpName $ varName f) else varName f
  
  newVarDefinition :: VarDefinition a b
  newVarDefinition = VarDefinition
    { varName      = undefined
    , varBundle    = Nothing
    , varMeta      = []
    , varModifiers = [Public]
    , varType      = undefined
    , varDefault   = Nothing
    , varPos       = NoPos
    , varIsLocal   = False
    , varIsConst   = False
    }
  
  convertVarDefinition
    :: (Monad m)
    => Converter m a b c d
    -> VarDefinition a b
    -> m (VarDefinition c d)
  convertVarDefinition (Converter { exprConverter = exprConverter, typeConverter = typeConverter }) v
    = do
      newType    <- typeConverter (varPos v) (varType v)
      newDefault <- maybeConvert exprConverter (varDefault v)
      return $ (newVarDefinition) { varName      = varName v
                                  , varBundle    = varBundle v
                                  , varMeta      = varMeta v
                                  , varModifiers = varModifiers v
                                  , varType      = newType
                                  , varDefault   = newDefault
                                  , varPos       = varPos v
                                  , varIsLocal   = varIsLocal v
                                  , varIsConst   = varIsConst v
                                  }
  