@@ -160,11 +160,15 @@ module VirtualMachine.ByteCode where
160160 increment = -- 'iinc' has local variable index as first, with value as second indice
161161 join $ modifyLocal frame <$> getNextBC frame <*> ((+) . fromIntegral <$> getNextBC frame)
162162
163+ {- Conditional jump instructions ('if', 'for', and 'while') -}
163164 cmpOp :: StackFrame -> ByteCode -> IO ()
164165 cmpOp frame bc
165166 | bc >= 148 && bc <= 152 = pushCmp
166- | bc >= 153 && bc <= 166 = (program_counter . code_segment <$> readIORef frame) >>= readIORef
167- >>= \ pc -> getNextShort frame >>= \ jmp -> when (bc >= 159 ) pushCmp >> cmpJmp (fromIntegral pc + jmp - 1 )
167+ | bc >= 153 && bc <= 166 = getPC' frame >>= \ pc -> getNextShort frame >>= \ jmp ->
168+ -- Special Case: We combine instructions which directly compare two different
169+ -- values for a jump by first pushing the result of the comparison on the operand
170+ -- stack, and THEN comparing them to save time and code.
171+ when (bc >= 159 ) pushCmp >> cmpJmp (pc + jmp - 1 )
168172 | otherwise = error $ " Bad ByteCode Instruction: " ++ show bc
169173 where
170174 pushCmp :: IO ()
@@ -179,27 +183,31 @@ module VirtualMachine.ByteCode where
179183 | bc == 156 || bc == 162 = flip condJmp [GT , EQ ]
180184 | bc == 157 || bc == 163 = flip condJmp [GT ]
181185 | bc == 158 || bc == 164 = flip condJmp [LT , EQ ]
186+ | otherwise = error $ " Bad ByteCode Instruction: " ++ show bc
182187 condJmp :: Word16 -> [Ordering ] -> IO ()
183- condJmp jmp ord = popOp frame >>= \ op -> when (intToOrd op `elem` ord )
188+ condJmp jmp ords = popOp frame >>= \ cmp -> when (enumToOrd cmp `elem` ords )
184189 (readIORef frame >>= flip (writeIORef . program_counter . code_segment) (fromIntegral jmp))
190+ ordToInt :: Ordering -> Int
185191 ordToInt ord = case ord of
186192 GT -> 1
187193 EQ -> 0
188194 LT -> - 1
189- intToOrd int = case int of
195+ enumToOrd :: Integral a => a -> Ordering
196+ enumToOrd x = case x of
190197 1 -> GT
191198 0 -> EQ
192199 - 1 -> LT
200+ _ -> error " Bad Enumerable Value! "
193201
194-
195-
196-
202+ {- Obtains the next ByteCode instruction and increments the PC -}
197203 getNextBC :: StackFrame -> IO ByteCode
198204 getNextBC frame = readIORef frame >>= \ f -> -- Read StackFrame from passed reference
199205 let segment = code_segment f in -- Retrieve current set of instructions
200206 readIORef (program_counter segment) >>= \ n -> -- Read current ByteCode instruction
201207 modifyIORef (program_counter segment) (+ 1 ) >> -- Increment PC
202208 return (byte_code segment !! fromIntegral n) -- Return ByteCode instruction
203209
210+ {- Obtains the next two ByteCode instructions as a short, and increments the PC by 2 -}
204211 getNextShort :: StackFrame -> IO Word16
205- getNextShort frame = replicateM 2 (getNextBC frame) >>= \ (i1: i2: _) -> return $ fromIntegral i1 `shift` 8 .|. fromIntegral i2
212+ getNextShort frame = replicateM 2 (getNextBC frame) >>= \ (i1: i2: _) ->
213+ return $ fromIntegral i1 `shift` 8 .|. fromIntegral i2
0 commit comments