module ObjectFile where

import qualified Data.Map as M
import Data.Map (Map)
import qualified Data.Set as S
import Data.Set (Set)
import Data.Word

data SectionFlag =
	Readable | Writable | Present
	deriving (Show, Eq, Ord)
data RelocationType = A4 | R4 | AS4 | RS4 | U2 | L2 deriving (Show,Read,Ord,Eq)


type SectionFlags = Set SectionFlag

data Section = Section {
	secName :: String,
	secBase :: Word64,
	secSize :: Word64,
	secFlags :: SectionFlags,
	secSymbols :: Map String Symbol,
	secData :: [Word8],
	secRelocs :: [Relocation]
	} deriving Show

data Symbol = Symbol {
	symName :: String,
	symValue :: Word64,
	symSection :: Int,
	symType :: String
	} deriving Show

data Relocation = Relocation {
	relLocation :: Word64,
	relSection :: Int,
	relRef :: Int, -- Section or symbol index to insert address to
	relType :: RelocationType
	} deriving Show

data ObjectFile = ObjectFile {
	sections :: Map Int Section
	} deriving Show

mergeSymbol x y = error "Merge unimplemented"

modifySymbols f sec = sec { secSymbols = f (secSymbols sec) }
modifyRelocs f sec = sec { secRelocs = f (secRelocs sec) }

addSymbol :: Symbol -> Section -> Section
addSymbol sym = modifySymbols (M.insertWith mergeSymbol (symName sym) sym)

addReloc :: Relocation -> Section -> Section
addReloc rel = modifyRelocs (rel:)

hasFlag f = S.member f

readSectionFlag x =
	case x of
		'R' -> Readable
		'W' -> Writable
		'P' -> Present
showSectionFlag f =
	case f of
		Readable -> 'R'
		Writable -> 'W'
		Present -> 'P'

readSectionFlags :: String -> SectionFlags
readSectionFlags = foldr (S.insert . readSectionFlag) S.empty

showSectionFlags = map showSectionFlag . S.toList

numberSection n = modifySymbols (M.map f)
	where
		f sym = sym { symSection = n }

