2020-10-21 22:34:04 +02:00
|
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
|
|
# or more contributor license agreements. See the NOTICE file
|
|
|
|
# distributed with this work for additional information
|
|
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
|
|
# to you under the Apache License, Version 2.0 (the
|
|
|
|
# "License"); you may not use this file except in compliance
|
|
|
|
# with the License. You may obtain a copy of the License at
|
|
|
|
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
# Unless required by applicable law or agreed to in writing,
|
|
|
|
# software distributed under the License is distributed on an
|
|
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
# KIND, either express or implied. See the License for the
|
|
|
|
# specific language governing permissions and limitations
|
|
|
|
# under the License.
|
|
|
|
|
2020-10-17 11:47:42 +02:00
|
|
|
## This module takes chunks of bytecode, and prints their contents to the
|
|
|
|
## screen.
|
|
|
|
|
2020-08-07 17:11:06 +02:00
|
|
|
import ../meta/chunk
|
2020-09-01 18:09:36 +02:00
|
|
|
import ../common
|
2020-08-07 17:11:06 +02:00
|
|
|
import strformat
|
|
|
|
|
|
|
|
|
2020-08-13 23:39:26 +02:00
|
|
|
|
2020-08-07 17:11:06 +02:00
|
|
|
proc simpleInstruction(name: string, index: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
echo &"\tInstruction at IP: {name}\n"
|
|
|
|
return index + 1
|
2020-08-07 17:11:06 +02:00
|
|
|
|
|
|
|
|
2020-08-17 08:55:33 +02:00
|
|
|
proc byteInstruction(name: string, chunk: Chunk, offset: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
var slot = chunk.code[offset + 1]
|
|
|
|
echo &"\tInstruction at IP: {name}, points to slot {slot}\n"
|
|
|
|
return offset + 1
|
2020-08-17 08:55:33 +02:00
|
|
|
|
|
|
|
|
2020-08-07 19:38:52 +02:00
|
|
|
proc constantLongInstruction(name: string, chunk: Chunk, offset: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
# Rebuild the index
|
|
|
|
var constantArray: array[3, uint8] = [chunk.code[offset + 1], chunk.code[offset + 2], chunk.code[offset + 3]]
|
|
|
|
var constant: int
|
|
|
|
copyMem(constant.addr, unsafeAddr(constantArray), sizeof(constantArray))
|
|
|
|
echo &"\tInstruction at IP: {name}, points to slot {constant}"
|
|
|
|
let obj = chunk.consts.values[constant]
|
|
|
|
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
|
|
|
|
return offset + 4
|
2020-08-07 19:38:52 +02:00
|
|
|
|
|
|
|
|
2020-08-07 17:11:06 +02:00
|
|
|
proc constantInstruction(name: string, chunk: Chunk, offset: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
var constant = chunk.code[offset + 1]
|
|
|
|
echo &"\tInstruction at IP: {name}, points to index {constant}"
|
|
|
|
let obj = chunk.consts.values[constant]
|
|
|
|
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
|
|
|
|
return offset + 2
|
2020-08-07 17:11:06 +02:00
|
|
|
|
|
|
|
|
2020-08-19 14:19:01 +02:00
|
|
|
proc jumpInstruction(name: string, chunk: Chunk, offset: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
var jump = uint16 (chunk.code[offset + 1] shr 8)
|
|
|
|
jump = jump or chunk.code[offset + 2]
|
|
|
|
echo &"\tInstruction at IP: {name}\n\tJump offset: {jump}\n"
|
|
|
|
return offset + 3
|
2020-08-19 13:10:34 +02:00
|
|
|
|
2020-08-28 00:05:56 +02:00
|
|
|
|
2020-08-07 17:11:06 +02:00
|
|
|
proc disassembleInstruction*(chunk: Chunk, offset: int): int =
|
2020-10-17 15:36:14 +02:00
|
|
|
## Takes one bytecode instruction and prints it
|
|
|
|
echo &"Current IP position: {offset}\nCurrent line: {chunk.lines[offset]}"
|
|
|
|
var opcode = OpCode(chunk.code[offset])
|
|
|
|
case opcode:
|
|
|
|
of simpleInstructions:
|
|
|
|
result = simpleInstruction($opcode, offset)
|
|
|
|
of constantInstructions:
|
|
|
|
result = constantInstruction($opcode, chunk, offset)
|
|
|
|
of constantLongInstructions:
|
|
|
|
result = constantLongInstruction($opcode, chunk, offset)
|
|
|
|
of byteInstructions:
|
|
|
|
result = byteInstruction($opcode, chunk, offset)
|
|
|
|
of jumpInstructions:
|
|
|
|
result = jumpInstruction($opcode, chunk, offset)
|
|
|
|
else:
|
|
|
|
echo &"Unknown opcode {opcode} at index {offset}"
|
|
|
|
result = offset + 1
|
2020-08-07 17:11:06 +02:00
|
|
|
|
2020-08-08 16:19:44 +02:00
|
|
|
|
2020-08-07 17:11:06 +02:00
|
|
|
proc disassembleChunk*(chunk: Chunk, name: string) =
|
2020-10-17 15:36:14 +02:00
|
|
|
## Takes a chunk of bytecode, and prints it
|
|
|
|
echo &"==== JAPL VM Debugger - Chunk '{name}' ====\n"
|
|
|
|
var index = 0
|
|
|
|
while index < chunk.code.len:
|
|
|
|
index = disassembleInstruction(chunk, index)
|
|
|
|
echo &"==== Debug session ended - Chunk '{name}' ===="
|
2020-08-13 17:53:23 +02:00
|
|
|
|