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 -- | Zero-based index into upvalues 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 -- ^ number of upvalues and function body deriving (Read,Show,Eq) data OpCode = OP_MOVE !Reg !Reg {- ^ A B R(A) := R(B) -} | OP_LOADK !Reg !Kst {- ^ A Bx R(A) := Kst(Bx) -} | OP_LOADKX !Reg {- ^ A R(A) := Kst(extra arg) -} | OP_LOADBOOL !Reg !Bool !Bool{- ^ A B C R(A) := (Bool)B; if (C) pc++ -} | OP_LOADNIL !Reg !Int {- ^ A B R(A), R(A+1), ..., R(A+B) := nil -} | OP_GETUPVAL !Reg !UpIx {- ^ A B R(A) := UpValue[B] -} | OP_GETTABUP !Reg !UpIx !RK {- ^ A B C R(A) := UpValue[B][RK(C)] -} | OP_GETTABLE !Reg !Reg !RK {- ^ A B C R(A) := R(B)[RK(C)] -} | OP_SETTABUP !UpIx !RK !RK {- ^ A B C UpValue[A][RK(B)] := RK(C) -} | OP_SETUPVAL !Reg !UpIx {- ^ A B UpValue[B] := R(A) -} | OP_SETTABLE !Reg !RK !RK {- ^ A B C R(A)[RK(B)] := RK(C) -} | OP_NEWTABLE !Reg !Int !Int {- ^ A B C R(A) := {} (size = B,C) -} | OP_SELF !Reg !Reg !RK {- ^ A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] -} | OP_ADD !Reg !RK !RK {- ^ A B C R(A) := RK(B) + RK(C) -} | OP_SUB !Reg !RK !RK {- ^ A B C R(A) := RK(B) - RK(C) -} | OP_MUL !Reg !RK !RK {- ^ A B C R(A) := RK(B) * RK(C) -} | OP_MOD !Reg !RK !RK {- ^ A B C R(A) := RK(B) % RK(C) -} | OP_POW !Reg !RK !RK {- ^ A B C R(A) := RK(B) ^ RK(C) -} | OP_DIV !Reg !RK !RK {- ^ A B C R(A) := RK(B) / RK(C) -} | OP_IDIV !Reg !RK !RK {- ^ A B C R(A) := RK(B) // RK(C) -} | OP_BAND !Reg !RK !RK {- ^ A B C R(A) := RK(B) & RK(C) -} | OP_BOR !Reg !RK !RK {- ^ A B C R(A) := RK(B) | RK(C) -} | OP_BXOR !Reg !RK !RK {- ^ A B C R(A) := RK(B) ~ RK(C) -} | OP_SHL !Reg !RK !RK {- ^ A B C R(A) := RK(B) << RK(C) -} | OP_SHR !Reg !RK !RK {- ^ A B C R(A) := RK(B) >> RK(C) -} | OP_UNM !Reg !Reg {- ^ A B R(A) := -R(B) -} | OP_BNOT !Reg !Reg {- ^ A B R(A) := ~R(B) -} | OP_NOT !Reg !Reg {- ^ A B R(A) := not R(B) -} | OP_LEN !Reg !Reg {- ^ A B R(A) := length of R(B) -} | OP_CONCAT !Reg !Reg !Reg {- ^ A B C R(A) := R(B).. ... ..R(C) -} | OP_JMP !(Maybe Reg) !Int {- ^ A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) -} | OP_EQ !Bool !RK !RK {- ^ A B C if ((RK(B) == RK(C)) ~= A) then pc++ -} | OP_LT !Bool !RK !RK {- ^ A B C if ((RK(B) < RK(C)) ~= A) then pc++ -} | OP_LE !Bool !RK !RK {- ^ A B C if ((RK(B) <= RK(C)) ~= A) then pc++ -} | OP_TEST !Reg !Bool {- ^ A C if not (R(A) <=> C) then pc++ -} | OP_TESTSET !Reg !Reg !Bool {- ^ A B C if (R(B) <=> C) then R(A) := R(B) else pc++ -} | OP_CALL !Reg !Count !Count {- ^ A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) -} | OP_TAILCALL !Reg !Count !Count {- ^ A B C return R(A)(R(A+1), ... ,R(A+B-1)) -} | OP_RETURN !Reg !Count {- ^ A B return R(A), ... ,R(A+B-2) (see note) -} | OP_FORLOOP !Reg !Int {- ^ A sBx R(A)+=R(A+2); if R(A) 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) } -- | Compute a register relative to another. plusReg :: Reg -> Int {- ^ offset -} -> Reg plusReg (Reg i) j = Reg (i+j) -- | Compute the distance between two registers. diffReg :: Reg -> Reg -> Int diffReg (Reg i) (Reg j) = i - j -- | Compute a list of registers given a startin register and length. regRange :: Reg {- ^ start -} -> Int {- ^ length -} -> [Reg] regRange start n = take n [start ..]