Skip to content

Commit 4f5a2fe

Browse files
author
Louis Jenkins
committed
Refactoring and documentation of ByteCode.hs is finished
1 parent aa53d2b commit 4f5a2fe

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

VirtualMachine/ByteCode.hs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)