From 66e51b39cf9d4fb6a7bd00027f7d7496f64f633e Mon Sep 17 00:00:00 2001 From: Leo dev Date: Wed, 29 Oct 2025 18:18:07 +0100 Subject: [PATCH] Labels --- input.fg | 17 ++++++--------- src/emulator/instruction.rs | 41 +++++++++++++++++++++++++++++++++++++ src/emulator/mod.rs | 15 +++++++++++++- src/main.rs | 39 ++++++++++++++++++++--------------- src/text.rs | 34 ------------------------------ 5 files changed, 84 insertions(+), 62 deletions(-) delete mode 100644 src/text.rs diff --git a/input.fg b/input.fg index 7074090..1977c74 100644 --- a/input.fg +++ b/input.fg @@ -1,11 +1,6 @@ -reg rx, 1 -reg ry, 2 -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx -mul rx, ry, rx +reg ra, 1 +reg rb, 2 + +label double +mul ra, rb, ra +jmp double diff --git a/src/emulator/instruction.rs b/src/emulator/instruction.rs index 1620cd2..d77a35a 100644 --- a/src/emulator/instruction.rs +++ b/src/emulator/instruction.rs @@ -8,6 +8,8 @@ pub enum Instruction { Sub(u8, u8, u8), Mul(u8, u8, u8), Div(u8, u8, u8), + Label(String), + Jmp(String), } impl Display for Instruction { @@ -22,7 +24,46 @@ impl Display for Instruction { Instruction::Sub(a, b, c) => format!("SUB {a}, {b}, {c}"), Instruction::Mul(a, b, c) => format!("MUL {a}, {b}, {c}"), Instruction::Div(a, b, c) => format!("DIV {a}, {b}, {c}"), + Instruction::Label(a) => format!("LABEL {a}"), + Instruction::Jmp(a) => format!("JMP {a}"), } ) } } + +impl Instruction { + pub fn from_text(s: &str) -> Vec { + s.lines() + .filter_map(|v| { + let (name, args) = v.split_once(' ')?; + let args: Vec<&str> = args.split(',').map(str::trim).collect(); + + match name.to_lowercase().as_str() { + "hlt" => Some(Instruction::Hlt), + "reg" => Some(Instruction::Reg(reg(args[0]), num(args[1]))), + "add" => Some(Instruction::Add(reg(args[0]), reg(args[1]), reg(args[2]))), + "sub" => Some(Instruction::Sub(reg(args[0]), reg(args[1]), reg(args[2]))), + "mul" => Some(Instruction::Mul(reg(args[0]), reg(args[1]), reg(args[2]))), + "div" => Some(Instruction::Div(reg(args[0]), reg(args[1]), reg(args[2]))), + "label" => Some(Instruction::Label(args[0].to_string())), + "jmp" => Some(Instruction::Jmp(args[0].to_string())), + _ => None, + } + }) + .collect() + } +} + +fn reg(r: &str) -> u8 { + match r.to_lowercase().as_str() { + "ra" => 0, + "rb" => 1, + "rc" => 2, + "rd" => 3, + _ => 0, + } +} + +fn num(r: &str) -> usize { + r.parse().unwrap() +} diff --git a/src/emulator/mod.rs b/src/emulator/mod.rs index d8e07b7..b70a549 100644 --- a/src/emulator/mod.rs +++ b/src/emulator/mod.rs @@ -1,7 +1,7 @@ pub mod instruction; pub mod registry; -use std::fmt::Display; +use std::{collections::HashMap, fmt::Display}; use osui::state::{DependencyHandler, State}; @@ -12,6 +12,7 @@ pub struct Emulator { pub instructions: Vec, pub registers: Registry, pub inst: State, + pub labels: State>, } impl Emulator { @@ -56,6 +57,18 @@ impl Emulator { let y = self.registers.get(*ry); self.registers.set(*r, x / y); } + + // 6 | Label + Instruction::Label(l) => { + self.labels.get().insert(l.clone(), **pc); + } + + // 7 | Jump + Instruction::Jmp(l) => { + if let Some(v) = self.labels.get().get(l) { + **pc = *v; + } + } } } else { break; diff --git a/src/main.rs b/src/main.rs index fbc8b4c..618b618 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,17 @@ mod binary; mod emulator; -mod text; -use std::{fs, sync::Arc}; +use std::{collections::HashMap, fs, sync::Arc}; use osui::prelude::*; -use crate::{ - emulator::{instruction::Instruction, registry::Registry}, - text::from_text, -}; +use crate::emulator::{instruction::Instruction, registry::Registry}; fn main() { let screen = Screen::new(); let s = fs::read_to_string("input.fg").unwrap(); - app(&screen, from_text(&s)).draw(&screen); + app(&screen, Instruction::from_text(&s)).draw(&screen); screen.run().unwrap(); } @@ -24,11 +20,13 @@ fn app(_screen: &Arc, instructions: Vec) -> Rsx { let pc = use_state::(0); let inst = use_state::(Instruction::Hlt); let registers = Registry(use_state([0; 8])); + let labels = use_state(HashMap::new()); let emulator = emulator::Emulator { pc: pc.clone(), registers: registers.clone(), inst: inst.clone(), + labels: labels.clone(), instructions, }; @@ -38,18 +36,27 @@ fn app(_screen: &Arc, instructions: Vec) -> Rsx { FlexRow, gap: 1, { @Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; @Transform::new().padding(1, 1); - %pc - "Program Counter: {pc}" + FlexCol, gap: 1, { + %pc + "Program Counter: {pc}" + + "|" + + %labels + "Labels: {labels:?}" + } @Style { foreground: None, background: Background::RoundedOutline(0xff0000) }; @Transform::new().padding(1, 1); - %registers - "{registers}" - } + FlexCol, gap: 1, { + %registers + "{registers}" - @Style { foreground: None, background: Background::RoundedOutline(0x0000ff) }; - @Transform::center().padding(2, 2); - %inst - "Current instruction: {inst}" + "|" + + %inst + "Current instruction: {inst}" + } + } } } diff --git a/src/text.rs b/src/text.rs deleted file mode 100644 index 39c4167..0000000 --- a/src/text.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::emulator::instruction::Instruction; - -pub fn reg(r: &str) -> u8 { - match r.to_lowercase().as_str() { - "rx" => 0, - "ry" => 1, - "rz" => 2, - "ra" => 3, - _ => 0, - } -} - -pub fn num(r: &str) -> usize { - r.parse().unwrap() -} - -pub fn from_text(s: &str) -> Vec { - s.lines() - .filter_map(|v| { - let (name, args) = v.split_once(' ')?; - let args: Vec<&str> = args.split(',').map(str::trim).collect(); - - match name.to_lowercase().as_str() { - "hlt" => Some(Instruction::Hlt), - "reg" => Some(Instruction::Reg(reg(args[0]), num(args[1]))), - "add" => Some(Instruction::Add(reg(args[0]), reg(args[1]), reg(args[2]))), - "sub" => Some(Instruction::Sub(reg(args[0]), reg(args[1]), reg(args[2]))), - "mul" => Some(Instruction::Mul(reg(args[0]), reg(args[1]), reg(args[2]))), - "div" => Some(Instruction::Div(reg(args[0]), reg(args[1]), reg(args[2]))), - _ => None, - } - }) - .collect() -}