@@ -25,9 +25,9 @@ module VirtualMachine.ByteCode where
2525 execute :: Runtime_Environment -> IO ()
2626 execute env = head <$> readIORef (stack env) -- Take the head of the stack (current stack frame)
2727 >>= \ frame -> when (debug_mode env) (debugFrame frame >>= putStrLn ) -- Optional Debug
28- >> readIORef frame >>= \ f -> readIORef (program_counter . code_segment $ f) >>= \ pc ->
29- unless ( fromIntegral pc >= length (byte_code . code_segment $ f)) -- While valid program_counter
30- ( getNextBC frame >>= execute' frame >> execute env) -- Execute instruction
28+ >> getPC' frame >>= \ pc -> maxPC frame >>= \ max_pc ->
29+ -- While valid program_counter, execute instruction
30+ unless (pc >= max_pc) ( getNextBC frame >>= execute' frame >> execute env)
3131 where
3232 -- The main dispatcher logic
3333 execute' :: StackFrame -> ByteCode -> IO ()
@@ -38,12 +38,12 @@ module VirtualMachine.ByteCode where
3838 | bc >= 1 && bc <= 15 = constOp frame bc
3939 -- Push raw byte(s)
4040 | bc == 16 || bc == 17 =
41- -- 0x10 pushes a single byte, but 0x11 pushes a short
41+ -- Special Case: 0x10 pushes a single byte, but 0x11 pushes a short
4242 (if bc == 16 then fromIntegral <$> getNextBC frame else getNextShort frame)
4343 >>= pushOp frame . fromIntegral
44- -- Load constant pool constant
44+ -- Load from runtime constant pool
4545 | bc >= 18 && bc <= 20 =
46- -- Only 0x12 uses only one byte, so we add a special case
46+ -- Special Case: 0x12 uses only one byte for index, while 0x13 and 0x14 use two
4747 (if bc == 18 then fromIntegral <$> getNextBC frame else getNextShort frame)
4848 >>= loadConstantPool env . fromIntegral >>= pushOp frame
4949 -- Loads
@@ -56,9 +56,10 @@ module VirtualMachine.ByteCode where
5656 | bc >= 96 && bc <= 132 = mathOp frame bc
5757 -- Conditionals
5858 | bc >= 148 && bc <= 166 = cmpOp frame bc
59- -- Goto
60- | bc == 167 = (program_counter . code_segment <$> readIORef frame) >>= readIORef
61- >>= \ pc -> getNextShort frame >>= \ n -> readIORef frame >>= flip (writeIORef . program_counter . code_segment) (fromIntegral (fromIntegral pc + n - 1 ))
59+ -- Goto: The address is the offset from the current, with the offset being
60+ -- the next two instructions. Since we advance the PC 2 (+1 from reading this
61+ -- instruction), we must decrement the count by 3 to correctly obtain the target.
62+ | bc == 167 = getNextShort frame >>= \ jmp -> modifyPC frame (+ (jmp - 3 ))
6263 -- Return
6364 | bc == 177 = return ()
6465 -- Runtime Stubs
0 commit comments