-----------------------------------------------------------------------------
-- |
-- Module      : Blip.Compiler.Types
  Copyright    : ( c ) 2012 , 2013 , 2014  
-- License     : BSD-style
-- Maintainer  : 
-- Stability   : experimental
  Portability : ghc
--
-- Type definitions which are used in multiple modules.
--
-----------------------------------------------------------------------------
module Blip.Compiler.Types 
   ( Identifier, CompileConfig (..), VarIndex, IndexedVarSet
   , ConstantID, ConstantCache, CompileState (..), BlockState (..)
   , AnnotatedCode (..), LabelMap, Dumpable (..), VarSet
   , LocalScope (..), NestedScope (..), VarInfo (..)
   , ScopeIdentifier, FrameBlockInfo (..), Context (..), ParameterTypes (..)
   ) where

import Data.Set (Set)
import Blip.Bytecode (Bytecode (..))
import Blip.Marshal (PyObject (..))
import Data.Word (Word32, Word16)
import qualified Data.Map as Map

-- The context in which a variable is used affects the bytecode
-- related to that use.
data Context
   = ModuleContext
   | ClassContext
   | FunctionContext
   deriving (Eq, Ord, Show)

-- information about how a variable is bound plus its offset into
-- the appropriate structure
data VarInfo
   = LocalVar
   | CellVar !VarIndex 
   | FreeVar !VarIndex 
   | ExplicitGlobal
   | ImplicitGlobal

type VarSet = Set Identifier

-- XXX need to handle keyword only paramters
data ParameterTypes
   = ParameterTypes
     { parameterTypes_pos :: ![Identifier]
     , parameterTypes_varPos :: !(Maybe Identifier)
     , parameterTypes_varKeyword :: !(Maybe Identifier)
     }
   deriving (Eq, Show)

data LocalScope
   = LocalScope
     { localScope_params :: !ParameterTypes
     , localScope_locals :: !VarSet
     , localScope_freeVars :: !VarSet
     , localScope_cellVars :: !VarSet
     , localScope_explicitGlobals :: !VarSet
     }
     deriving Show

-- start and end coordinates of span (row, col, row, col)
type ScopeIdentifier = (Int, Int, Int, Int)

-- mapping from source location to pair of (scope name, local scope)
newtype NestedScope =
   NestedScope (Map.Map ScopeIdentifier (String, LocalScope))
   deriving Show

data Dumpable = DumpScope | DumpAST
   deriving (Eq, Ord, Show)

data AnnotatedCode
   = AnnotatedCode 
     { annotatedCode_bytecode :: !Bytecode
  instruction can be labelled zero or more times
     , annotatedCode_index :: !Word16 }    -- byte offset of the instruction within this sequence of bytecode
   deriving Show

type Identifier = String -- a variable name

data CompileConfig =
   CompileConfig
   { compileConfig_magic :: !Word32
   , compileConfig_dumps :: !(Set Dumpable)
   }
   deriving (Eq, Show)

type ConstantID = Word16
type ConstantCache = Map.Map PyObject ConstantID 

data CompileState = CompileState
   { state_config :: !CompileConfig
   , state_blockState :: !BlockState
   , state_filename :: !FilePath
   , state_nestedScope :: !NestedScope
   }

-- Map from Label to Instruction offset.
-- The same instruction can be labelled multiple times,
  but each label is attached to exactly one instruction .
type LabelMap = Map.Map Word16 Word16

type VarIndex = Word16
type IndexedVarSet = Map.Map Identifier VarIndex

data BlockState = BlockState 
   { state_label :: !Word16
   , state_instructions :: ![AnnotatedCode]
  zero or more labels for the next instruction
   , state_constants :: ![PyObject] 
   , state_constantCache :: !ConstantCache
   , state_nextConstantID :: !ConstantID
   , state_names :: ![Identifier]
   , state_nameCache :: !IndexedVarSet
   , state_nextNameID :: !VarIndex
   , state_objectName :: !String
   , state_instruction_index :: !Word16
   , state_labelMap :: !LabelMap
   , state_locals :: !VarSet
   , state_fastLocals :: !IndexedVarSet
   , state_freeVars :: !IndexedVarSet
   , state_cellVars :: !IndexedVarSet
   , state_explicitGlobals :: !VarSet
   , state_argcount :: !Word32
   , state_flags :: !Word32
   , state_frameBlockStack :: ![FrameBlockInfo]
   , state_context :: !Context
   , state_lineNumber :: !Word32
   , state_lineNumberTable :: ![(Word16, Word32)] -- mapping from bytecode offset to source line number
   , state_firstLineNumber :: !Word32
   }
   deriving (Show)

data FrameBlockInfo
   = FrameBlockLoop !Word16
   | FrameBlockExcept 
   | FrameBlockFinallyTry 
   | FrameBlockFinallyEnd
   deriving (Eq, Show)

---------------------------------------------------------------------------
 |
 Module      : Blip.Compiler.Types
 License     : BSD-style
 Maintainer  : 
 Stability   : experimental

 Type definitions which are used in multiple modules.

---------------------------------------------------------------------------
 The context in which a variable is used affects the bytecode
 related to that use.
 information about how a variable is bound plus its offset into
 the appropriate structure
 XXX need to handle keyword only paramters
 start and end coordinates of span (row, col, row, col)
 mapping from source location to pair of (scope name, local scope)
 byte offset of the instruction within this sequence of bytecode
 a variable name
 Map from Label to Instruction offset.
 The same instruction can be labelled multiple times,
 mapping from bytecode offset to source line number
  Copyright    : ( c ) 2012 , 2013 , 2014  
  Portability : ghc
module Blip.Compiler.Types 
   ( Identifier, CompileConfig (..), VarIndex, IndexedVarSet
   , ConstantID, ConstantCache, CompileState (..), BlockState (..)
   , AnnotatedCode (..), LabelMap, Dumpable (..), VarSet
   , LocalScope (..), NestedScope (..), VarInfo (..)
   , ScopeIdentifier, FrameBlockInfo (..), Context (..), ParameterTypes (..)
   ) where

import Data.Set (Set)
import Blip.Bytecode (Bytecode (..))
import Blip.Marshal (PyObject (..))
import Data.Word (Word32, Word16)
import qualified Data.Map as Map

data Context
   = ModuleContext
   | ClassContext
   | FunctionContext
   deriving (Eq, Ord, Show)

data VarInfo
   = LocalVar
   | CellVar !VarIndex 
   | FreeVar !VarIndex 
   | ExplicitGlobal
   | ImplicitGlobal

type VarSet = Set Identifier

data ParameterTypes
   = ParameterTypes
     { parameterTypes_pos :: ![Identifier]
     , parameterTypes_varPos :: !(Maybe Identifier)
     , parameterTypes_varKeyword :: !(Maybe Identifier)
     }
   deriving (Eq, Show)

data LocalScope
   = LocalScope
     { localScope_params :: !ParameterTypes
     , localScope_locals :: !VarSet
     , localScope_freeVars :: !VarSet
     , localScope_cellVars :: !VarSet
     , localScope_explicitGlobals :: !VarSet
     }
     deriving Show

type ScopeIdentifier = (Int, Int, Int, Int)

newtype NestedScope =
   NestedScope (Map.Map ScopeIdentifier (String, LocalScope))
   deriving Show

data Dumpable = DumpScope | DumpAST
   deriving (Eq, Ord, Show)

data AnnotatedCode
   = AnnotatedCode 
     { annotatedCode_bytecode :: !Bytecode
  instruction can be labelled zero or more times
   deriving Show


data CompileConfig =
   CompileConfig
   { compileConfig_magic :: !Word32
   , compileConfig_dumps :: !(Set Dumpable)
   }
   deriving (Eq, Show)

type ConstantID = Word16
type ConstantCache = Map.Map PyObject ConstantID 

data CompileState = CompileState
   { state_config :: !CompileConfig
   , state_blockState :: !BlockState
   , state_filename :: !FilePath
   , state_nestedScope :: !NestedScope
   }

  but each label is attached to exactly one instruction .
type LabelMap = Map.Map Word16 Word16

type VarIndex = Word16
type IndexedVarSet = Map.Map Identifier VarIndex

data BlockState = BlockState 
   { state_label :: !Word16
   , state_instructions :: ![AnnotatedCode]
  zero or more labels for the next instruction
   , state_constants :: ![PyObject] 
   , state_constantCache :: !ConstantCache
   , state_nextConstantID :: !ConstantID
   , state_names :: ![Identifier]
   , state_nameCache :: !IndexedVarSet
   , state_nextNameID :: !VarIndex
   , state_objectName :: !String
   , state_instruction_index :: !Word16
   , state_labelMap :: !LabelMap
   , state_locals :: !VarSet
   , state_fastLocals :: !IndexedVarSet
   , state_freeVars :: !IndexedVarSet
   , state_cellVars :: !IndexedVarSet
   , state_explicitGlobals :: !VarSet
   , state_argcount :: !Word32
   , state_flags :: !Word32
   , state_frameBlockStack :: ![FrameBlockInfo]
   , state_context :: !Context
   , state_lineNumber :: !Word32
   , state_firstLineNumber :: !Word32
   }
   deriving (Show)

data FrameBlockInfo
   = FrameBlockLoop !Word16
   | FrameBlockExcept 
   | FrameBlockFinallyTry 
   | FrameBlockFinallyEnd
   deriving (Eq, Show)
