split files

This commit is contained in:
bQUARKz 2026-01-15 15:40:39 +00:00 committed by Nilton Constantino
parent 9ff9f0cb5b
commit 3e84a59ab6
No known key found for this signature in database
6 changed files with 203 additions and 194 deletions

View File

@ -1,8 +1,12 @@
use crate::vm::{Value, VirtualMachine};
use crate::Machine;
use crate::vm::{NativeInterface, Value, VirtualMachine};
pub trait NativeInterface {
fn syscall(&mut self, id: u32, vm: &mut crate::vm::VirtualMachine) -> Result<u64, String>;
}
impl NativeInterface for Machine {
fn call(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
match id {
// system.has_cart() -> bool
0x0001 => {
@ -69,7 +73,7 @@ impl NativeInterface for Machine {
}
Ok(300)
}
_ => Err(format!("Unknown native call: 0x{:08X}", id)),
_ => Err(format!("Unknown syscall: 0x{:08X}", id)),
}
}
}

View File

@ -0,0 +1,5 @@
pub struct CallFrame {
pub return_address: usize,
pub stack_base: usize,
pub locals_count: usize,
}

View File

@ -0,0 +1,7 @@
mod virtual_machine;
mod value;
mod opcode;
mod call_frame;
pub use value::Value;
pub use virtual_machine::VirtualMachine;

View File

@ -0,0 +1,133 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum OpCode {
// 6.1 Controle de Execução
Nop = 0x00,
Halt = 0x01,
Jmp = 0x02,
JmpIfFalse = 0x03,
// 6.2 Pilha
PushConst = 0x10,
Pop = 0x11,
Dup = 0x12,
Swap = 0x13,
// 6.3 Aritmética
Add = 0x20,
Sub = 0x21,
Mul = 0x22,
Div = 0x23,
// 6.4 Comparação e Lógica
Eq = 0x30,
Neq = 0x31,
Lt = 0x32,
Gt = 0x33,
And = 0x34,
Or = 0x35,
Not = 0x36,
// 6.5 Variáveis
GetGlobal = 0x40,
SetGlobal = 0x41,
GetLocal = 0x42,
SetLocal = 0x43,
// 6.6 Funções
Call = 0x50,
Ret = 0x51,
PushScope = 0x52,
PopScope = 0x53,
// 6.7 Heap
Alloc = 0x60,
LoadRef = 0x61,
StoreRef = 0x62,
// 6.8 Periféricos e Sistema
Syscall = 0x70,
FrameSync = 0x80,
}
impl TryFrom<u16> for OpCode {
type Error = String;
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(OpCode::Nop),
0x01 => Ok(OpCode::Halt),
0x02 => Ok(OpCode::Jmp),
0x03 => Ok(OpCode::JmpIfFalse),
0x10 => Ok(OpCode::PushConst),
0x11 => Ok(OpCode::Pop),
0x12 => Ok(OpCode::Dup),
0x13 => Ok(OpCode::Swap),
0x20 => Ok(OpCode::Add),
0x21 => Ok(OpCode::Sub),
0x22 => Ok(OpCode::Mul),
0x23 => Ok(OpCode::Div),
0x30 => Ok(OpCode::Eq),
0x31 => Ok(OpCode::Neq),
0x32 => Ok(OpCode::Lt),
0x33 => Ok(OpCode::Gt),
0x34 => Ok(OpCode::And),
0x35 => Ok(OpCode::Or),
0x36 => Ok(OpCode::Not),
0x40 => Ok(OpCode::GetGlobal),
0x41 => Ok(OpCode::SetGlobal),
0x42 => Ok(OpCode::GetLocal),
0x43 => Ok(OpCode::SetLocal),
0x50 => Ok(OpCode::Call),
0x51 => Ok(OpCode::Ret),
0x52 => Ok(OpCode::PushScope),
0x53 => Ok(OpCode::PopScope),
0x60 => Ok(OpCode::Alloc),
0x61 => Ok(OpCode::LoadRef),
0x62 => Ok(OpCode::StoreRef),
0x70 => Ok(OpCode::Syscall),
0x80 => Ok(OpCode::FrameSync),
_ => Err(format!("Invalid OpCode: 0x{:04X}", value)),
}
}
}
impl OpCode {
pub fn cycles(&self) -> u64 {
match self {
OpCode::Nop => 1,
OpCode::Halt => 1,
OpCode::Jmp => 2,
OpCode::JmpIfFalse => 3,
OpCode::PushConst => 2,
OpCode::Pop => 1,
OpCode::Dup => 1,
OpCode::Swap => 1,
OpCode::Add => 2,
OpCode::Sub => 2,
OpCode::Mul => 4,
OpCode::Div => 6,
OpCode::Eq => 2,
OpCode::Neq => 2,
OpCode::Lt => 2,
OpCode::Gt => 2,
OpCode::And => 2,
OpCode::Or => 2,
OpCode::Not => 1,
OpCode::GetGlobal => 3,
OpCode::SetGlobal => 3,
OpCode::GetLocal => 2,
OpCode::SetLocal => 2,
OpCode::Call => 5,
OpCode::Ret => 4,
OpCode::PushScope => 3,
OpCode::PopScope => 3,
OpCode::Alloc => 10,
OpCode::LoadRef => 3,
OpCode::StoreRef => 3,
OpCode::Syscall => 1, // Variável, mas vamos usar 1 como base ou definir via ID
OpCode::FrameSync => 1,
}
}
}

View File

@ -0,0 +1,43 @@
#[derive(Debug, Clone)]
pub enum Value {
Integer(i64),
Float(f64),
Boolean(bool),
String(String),
Ref(usize), // Referência ao heap
Null,
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Integer(a), Value::Integer(b)) => a == b,
(Value::Float(a), Value::Float(b)) => a == b,
(Value::Integer(a), Value::Float(b)) => *a as f64 == *b,
(Value::Float(a), Value::Integer(b)) => *a == *b as f64,
(Value::Boolean(a), Value::Boolean(b)) => a == b,
(Value::String(a), Value::String(b)) => a == b,
(Value::Ref(a), Value::Ref(b)) => a == b,
(Value::Null, Value::Null) => true,
_ => false,
}
}
}
impl Value {
pub fn as_float(&self) -> Option<f64> {
match self {
Value::Integer(i) => Some(*i as f64),
Value::Float(f) => Some(*f),
_ => None,
}
}
pub fn as_integer(&self) -> Option<i64> {
match self {
Value::Integer(i) => Some(*i),
Value::Float(f) => Some(*f as i64),
_ => None,
}
}
}

View File

@ -1,191 +1,8 @@
use std::convert::TryFrom;
use crate::native_interface::NativeInterface;
use crate::vm::call_frame::CallFrame;
use crate::vm::opcode::OpCode;
use crate::vm::value::Value;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum OpCode {
// 6.1 Controle de Execução
Nop = 0x00,
Halt = 0x01,
Jmp = 0x02,
JmpIfFalse = 0x03,
// 6.2 Pilha
PushConst = 0x10,
Pop = 0x11,
Dup = 0x12,
Swap = 0x13,
// 6.3 Aritmética
Add = 0x20,
Sub = 0x21,
Mul = 0x22,
Div = 0x23,
// 6.4 Comparação e Lógica
Eq = 0x30,
Neq = 0x31,
Lt = 0x32,
Gt = 0x33,
And = 0x34,
Or = 0x35,
Not = 0x36,
// 6.5 Variáveis
GetGlobal = 0x40,
SetGlobal = 0x41,
GetLocal = 0x42,
SetLocal = 0x43,
// 6.6 Funções
Call = 0x50,
Ret = 0x51,
PushScope = 0x52,
PopScope = 0x53,
// 6.7 Heap
Alloc = 0x60,
LoadRef = 0x61,
StoreRef = 0x62,
// 6.8 Periféricos e Sistema
Syscall = 0x70,
FrameSync = 0x80,
}
impl TryFrom<u16> for OpCode {
type Error = String;
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(OpCode::Nop),
0x01 => Ok(OpCode::Halt),
0x02 => Ok(OpCode::Jmp),
0x03 => Ok(OpCode::JmpIfFalse),
0x10 => Ok(OpCode::PushConst),
0x11 => Ok(OpCode::Pop),
0x12 => Ok(OpCode::Dup),
0x13 => Ok(OpCode::Swap),
0x20 => Ok(OpCode::Add),
0x21 => Ok(OpCode::Sub),
0x22 => Ok(OpCode::Mul),
0x23 => Ok(OpCode::Div),
0x30 => Ok(OpCode::Eq),
0x31 => Ok(OpCode::Neq),
0x32 => Ok(OpCode::Lt),
0x33 => Ok(OpCode::Gt),
0x34 => Ok(OpCode::And),
0x35 => Ok(OpCode::Or),
0x36 => Ok(OpCode::Not),
0x40 => Ok(OpCode::GetGlobal),
0x41 => Ok(OpCode::SetGlobal),
0x42 => Ok(OpCode::GetLocal),
0x43 => Ok(OpCode::SetLocal),
0x50 => Ok(OpCode::Call),
0x51 => Ok(OpCode::Ret),
0x52 => Ok(OpCode::PushScope),
0x53 => Ok(OpCode::PopScope),
0x60 => Ok(OpCode::Alloc),
0x61 => Ok(OpCode::LoadRef),
0x62 => Ok(OpCode::StoreRef),
0x70 => Ok(OpCode::Syscall),
0x80 => Ok(OpCode::FrameSync),
_ => Err(format!("Invalid OpCode: 0x{:04X}", value)),
}
}
}
impl OpCode {
pub fn cycles(&self) -> u64 {
match self {
OpCode::Nop => 1,
OpCode::Halt => 1,
OpCode::Jmp => 2,
OpCode::JmpIfFalse => 3,
OpCode::PushConst => 2,
OpCode::Pop => 1,
OpCode::Dup => 1,
OpCode::Swap => 1,
OpCode::Add => 2,
OpCode::Sub => 2,
OpCode::Mul => 4,
OpCode::Div => 6,
OpCode::Eq => 2,
OpCode::Neq => 2,
OpCode::Lt => 2,
OpCode::Gt => 2,
OpCode::And => 2,
OpCode::Or => 2,
OpCode::Not => 1,
OpCode::GetGlobal => 3,
OpCode::SetGlobal => 3,
OpCode::GetLocal => 2,
OpCode::SetLocal => 2,
OpCode::Call => 5,
OpCode::Ret => 4,
OpCode::PushScope => 3,
OpCode::PopScope => 3,
OpCode::Alloc => 10,
OpCode::LoadRef => 3,
OpCode::StoreRef => 3,
OpCode::Syscall => 1, // Variável, mas vamos usar 1 como base ou definir via ID
OpCode::FrameSync => 1,
}
}
}
#[derive(Debug, Clone)]
pub enum Value {
Integer(i64),
Float(f64),
Boolean(bool),
String(String),
Ref(usize), // Referência ao heap
Null,
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Integer(a), Value::Integer(b)) => a == b,
(Value::Float(a), Value::Float(b)) => a == b,
(Value::Integer(a), Value::Float(b)) => *a as f64 == *b,
(Value::Float(a), Value::Integer(b)) => *a == *b as f64,
(Value::Boolean(a), Value::Boolean(b)) => a == b,
(Value::String(a), Value::String(b)) => a == b,
(Value::Ref(a), Value::Ref(b)) => a == b,
(Value::Null, Value::Null) => true,
_ => false,
}
}
}
impl Value {
pub fn as_float(&self) -> Option<f64> {
match self {
Value::Integer(i) => Some(*i as f64),
Value::Float(f) => Some(*f),
_ => None,
}
}
pub fn as_integer(&self) -> Option<i64> {
match self {
Value::Integer(i) => Some(*i),
Value::Float(f) => Some(*f as i64),
_ => None,
}
}
}
pub struct CallFrame {
pub return_address: usize,
pub stack_base: usize,
pub locals_count: usize,
}
pub trait NativeInterface {
fn call(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String>;
}
pub struct VirtualMachine {
pub pc: usize,
@ -575,7 +392,7 @@ impl VirtualMachine {
}
OpCode::Syscall => {
let id = self.read_u32()?;
let native_cycles = native.call(id, self).map_err(|e| format!("Native call 0x{:08X} failed: {}", id, e))?;
let native_cycles = native.syscall(id, self).map_err(|e| format!("syscall 0x{:08X} failed: {}", id, e))?;
self.cycles += native_cycles;
}
OpCode::FrameSync => {
@ -655,7 +472,7 @@ mod tests {
fn test_add_instructions() {
struct NoopNative;
impl NativeInterface for NoopNative {
fn call(&mut self, _id: u32, _vm: &mut VirtualMachine) -> Result<u64, String> { Ok(0) }
fn syscall(&mut self, _id: u32, _vm: &mut VirtualMachine) -> Result<u64, String> { Ok(0) }
}
let mut native = NoopNative;
@ -681,7 +498,7 @@ mod tests {
fn test_jump_and_loop() {
struct NoopNative;
impl NativeInterface for NoopNative {
fn call(&mut self, _id: u32, _vm: &mut VirtualMachine) -> Result<u64, String> { Ok(0) }
fn syscall(&mut self, _id: u32, _vm: &mut VirtualMachine) -> Result<u64, String> { Ok(0) }
}
let mut native = NoopNative;
@ -741,7 +558,7 @@ mod tests {
cleared_color: Option<usize>,
}
impl NativeInterface for MockGfx {
fn call(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
fn syscall(&mut self, id: u32, vm: &mut VirtualMachine) -> Result<u64, String> {
if id == 0x1001 {
let color = vm.pop_integer()? as usize;
self.cleared_color = Some(color);