module Language.Lua.Bytecode where
import Data.Vector(Vector)
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
newtype Reg = Reg Int
deriving (Read,Show,Eq,Ord)
instance Enum Reg where
toEnum = Reg
fromEnum (Reg r) = r
newtype UpIx = UpIx Int
deriving (Read,Show,Eq,Ord)
newtype ProtoIx = ProtoIx Int
deriving (Read,Show,Eq,Ord)
newtype Kst = Kst Int
deriving (Read,Show,Eq,Ord)
data RK = RK_Reg !Reg | RK_Kst !Kst
deriving (Read,Show,Eq,Ord)
data Chunk = Chunk !Int Function
deriving (Read,Show,Eq)
data OpCode
= OP_MOVE !Reg !Reg
| OP_LOADK !Reg !Kst
| OP_LOADKX !Reg
| OP_LOADBOOL !Reg !Bool !Bool
| OP_LOADNIL !Reg !Int
| OP_GETUPVAL !Reg !UpIx
| OP_GETTABUP !Reg !UpIx !RK
| OP_GETTABLE !Reg !Reg !RK
| OP_SETTABUP !UpIx !RK !RK
| OP_SETUPVAL !Reg !UpIx
| OP_SETTABLE !Reg !RK !RK
| OP_NEWTABLE !Reg !Int !Int
| OP_SELF !Reg !Reg !RK
| OP_ADD !Reg !RK !RK
| OP_SUB !Reg !RK !RK
| OP_MUL !Reg !RK !RK
| OP_MOD !Reg !RK !RK
| OP_POW !Reg !RK !RK
| OP_DIV !Reg !RK !RK
| OP_IDIV !Reg !RK !RK
| OP_BAND !Reg !RK !RK
| OP_BOR !Reg !RK !RK
| OP_BXOR !Reg !RK !RK
| OP_SHL !Reg !RK !RK
| OP_SHR !Reg !RK !RK
| OP_UNM !Reg !Reg
| OP_BNOT !Reg !Reg
| OP_NOT !Reg !Reg
| OP_LEN !Reg !Reg
| OP_CONCAT !Reg !Reg !Reg
| OP_JMP !(Maybe Reg) !Int
| OP_EQ !Bool !RK !RK
| OP_LT !Bool !RK !RK
| OP_LE !Bool !RK !RK
| OP_TEST !Reg !Bool
| OP_TESTSET !Reg !Reg !Bool
| OP_CALL !Reg !Count !Count
| OP_TAILCALL !Reg !Count !Count
| OP_RETURN !Reg !Count
| OP_FORLOOP !Reg !Int
| OP_FORPREP !Reg !Int
| OP_TFORCALL !Reg !Int
| OP_TFORLOOP !Reg !Int
| OP_SETLIST !Reg !Int !Int
| OP_CLOSURE !Reg !ProtoIx
| OP_VARARG !Reg !Count
| OP_EXTRAARG !Int
deriving (Read, Show, Eq, Ord)
data Count = CountInt !Int | CountTop
deriving (Read, Show, Eq, Ord)
data Function = Function
{ funcSource :: !(Maybe ByteString)
, funcLineDefined :: !Int
, funcLastLineDefined :: !Int
, funcNumParams :: !Int
, funcIsVararg :: !Bool
, funcMaxStackSize :: !Int
, funcCode :: !(Vector OpCode)
, funcConstants :: !(Vector Constant)
, funcUpvalues :: !(Vector Upvalue)
, funcProtos :: !(Vector Function)
, funcDebug :: !DebugInfo
}
deriving (Read, Show, Eq)
data Constant = KNil | KBool Bool | KNum Double | KInt Int | KString ByteString | KLongString ByteString
deriving (Read, Show, Eq, Ord)
data Upvalue = UpReg Reg | UpUp UpIx
deriving (Read, Show, Eq, Ord)
type LineNumber = Int
data DebugInfo = DebugInfo
{ debugInfoLines :: !(Vector LineNumber)
, debugInfoVars :: !(Vector VarInfo)
, debugInfoUpvalues :: !(Vector ByteString)
}
deriving (Read, Show, Eq)
data VarInfo = VarInfo
{ varInfoName :: !ByteString
, varInfoStart, varInfoEnd :: !Int
}
deriving (Read, Show, Eq)
propagateSources :: Function -> Function
propagateSources = go B.empty
where
go name func =
case funcSource func of
Nothing ->
func { funcSource = (Just name)
, funcProtos = fmap (go name) (funcProtos func) }
Just src ->
func { funcProtos = fmap (go src) (funcProtos func) }
plusReg :: Reg -> Int -> Reg
plusReg (Reg i) j = Reg (i+j)
diffReg :: Reg -> Reg -> Int
diffReg (Reg i) (Reg j) = i j
regRange :: Reg -> Int -> [Reg]
regRange start n = take n [start ..]