Merge remote-tracking branch 'refs/remotes/origin/main'

This commit is contained in:
2025-06-16 23:40:29 +01:00
6 changed files with 116 additions and 90 deletions
+12 -10
View File
@@ -1,3 +1,5 @@
use std::str::FromStr;
use crate::{AssembleError, parser::Opcode};
use common::prelude::Register;
@@ -26,9 +28,9 @@ pub fn lexer(mut program: String) -> Result<Vec<Token>, AssembleError> {
break;
}
if token.starts_with('"') {
literal.push_str(&token[1..]);
println!("literal: {}", literal);
if let Some(stripped) = token.strip_prefix('"') {
literal.push_str(stripped);
println!("literal: {literal}");
}
if !literal.is_empty() {
@@ -72,7 +74,7 @@ pub fn lexer(mut program: String) -> Result<Vec<Token>, AssembleError> {
Ok(tokens)
}
pub fn parse_register(token: &str) -> Result<Option<Token>, AssembleError> {
Ok(Register::try_from(token).map(|r| Token::Register(r)).ok())
Ok(Register::try_from(token).map(Token::Register).ok())
}
pub fn parse_opcode(token: &str) -> Result<Option<Token>, AssembleError> {
@@ -117,23 +119,23 @@ pub fn parse_binary(token: &str) -> Result<Option<Token>, AssembleError> {
}
pub fn parse_decimal(token: &str) -> Result<Option<Token>, AssembleError> {
if !token.parse::<u32>().is_ok() {
return Ok(None);
if token.parse::<u32>().is_err() {
Ok(None)
} else {
return Ok(Some(Token::Immediate(token.parse().unwrap())));
Ok(Some(Token::Immediate(token.parse().unwrap())))
}
}
pub fn parse_label(token: &str) -> Result<Option<Token>, AssembleError> {
if !token.ends_with(":") {
return Ok(None);
Ok(None)
} else {
return Ok(Some(Token::Symbol(token[0..token.len() - 1].to_string())));
Ok(Some(Token::Symbol(token[0..token.len() - 1].to_string())))
}
}
pub fn parse_symbol(token: &str) -> Result<Option<Token>, AssembleError> {
if token.chars().nth(0).unwrap().is_numeric() {
if token.chars().next().unwrap().is_numeric() {
return Ok(None);
}
+2 -2
View File
@@ -7,7 +7,7 @@ use crate::{lexer::Token, parser::TokenType};
pub mod lexer;
pub mod parser;
pub fn assemble(src: &str) -> Vec<Instruction> {
pub fn assemble(_src: &str) -> Vec<Instruction> {
todo!()
}
@@ -31,7 +31,7 @@ impl fmt::Display for AssembleError {
match self {
AssembleError::Generic => write!(f, "Generic error"),
AssembleError::UnexpectedToken(tok, expected) => {
write!(f, "Unexpected token {:?}, expected {:?}", tok, expected)
write!(f, "Unexpected token {tok:?}, expected {expected:?}")
}
}
}
+2 -2
View File
@@ -7,11 +7,11 @@ fn main() {
let program = fs::read_to_string("../resources/dsa/print.dsa").unwrap();
let tokens = lexer::lexer(program).unwrap();
println!("{:?}", tokens);
println!("{tokens:?}");
let parser = Parser::new(tokens);
for node in parser {
println!("{:?}", node);
println!("{node:?}");
}
}
+89 -66
View File
@@ -1,6 +1,4 @@
use std::path::Iter;
use common::prelude::Register;
use std::str::FromStr;
use crate::AssembleError;
use crate::lexer::{Symbol, Token};
@@ -58,6 +56,7 @@ impl TokenType {
// TODO: MAKE SURE I DO THE BIT SHIFT FOR LUI CODEGEN
#[derive(Debug)]
#[expect(dead_code)]
pub struct Node(Option<Symbol>, Opcode, Vec<Token>);
impl Iterator for Parser {
@@ -116,7 +115,8 @@ impl Parser {
Opcode::Ldb | Opcode::Ldbs | Opcode::Ldh | Opcode::Ldhs | Opcode::Ldw => {
let base = self.expect_any(&[TokenType::Register, TokenType::Symbol])?;
let dest = self.expect_any(&[TokenType::Register, TokenType::Symbol])?;
let offset = self.maybe_expect(&[TokenType::Register, TokenType::Immediate]);
let offset =
self.maybe_expect(&[TokenType::Register, TokenType::Immediate]);
if offset.is_some() {
self.tokens.pop();
args = vec![base, offset.unwrap(), dest];
@@ -129,7 +129,8 @@ impl Parser {
let base = self.expect_any(&[TokenType::Register, TokenType::Symbol])?;
let dest = self.expect_any(&[TokenType::Register, TokenType::Symbol])?;
let offset = self.maybe_expect(&[TokenType::Register, TokenType::Immediate]);
let offset =
self.maybe_expect(&[TokenType::Register, TokenType::Immediate]);
if offset.is_some() {
self.tokens.pop();
args = vec![base, offset.unwrap(), dest];
@@ -224,10 +225,13 @@ impl Parser {
Ok(Node(label, opcode, args))
}
fn parse_data_definition(&mut self, opcode: Opcode) -> Result<Vec<Token>, AssembleError> {
fn parse_data_definition(
&mut self,
opcode: Opcode,
) -> Result<Vec<Token>, AssembleError> {
let mut values = Vec::new();
let name = self.expect(TokenType::Symbol)?;
let _name = self.expect(TokenType::Symbol)?;
values.push(self.tokens.pop().unwrap());
match opcode {
@@ -301,7 +305,7 @@ impl Parser {
fn maybe_expect(&mut self, types: &[TokenType]) -> Option<Token> {
let tok = self.tokens.last().unwrap();
if types.contains(&TokenType::from_token(&tok)) {
if types.contains(&TokenType::from_token(tok)) {
Some(tok.clone())
} else {
None
@@ -363,70 +367,89 @@ pub enum Opcode {
Lwi,
}
#[derive(Debug)]
pub enum OpcodeFromStrError {
InvalidRegister(&'static str),
}
impl std::fmt::Display for OpcodeFromStrError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidRegister(reg) => write!(f, "register does not exist: {reg}"),
}
}
}
impl std::error::Error for OpcodeFromStrError {}
impl FromStr for Opcode {
type Err = OpcodeFromStrError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"nop" => Ok(Self::Nop),
"mov" => Ok(Self::Mov),
"movs" => Ok(Self::Movs),
"ldb" => Ok(Self::Ldb),
"ldbs" => Ok(Self::Ldbs),
"ldh" => Ok(Self::Ldh),
"ldhs" => Ok(Self::Ldhs),
"ldw" => Ok(Self::Ldw),
"stb" => Ok(Self::Stb),
"sth" => Ok(Self::Sth),
"stw" => Ok(Self::Stw),
"lli" => Ok(Self::Lli),
"lui" => Ok(Self::Lui),
"jmp" => Ok(Self::Jmp),
"jeq" => Ok(Self::Jeq),
"jne" => Ok(Self::Jne),
"jgt" => Ok(Self::Jgt),
"jge" => Ok(Self::Jge),
"jlt" => Ok(Self::Jlt),
"jle" => Ok(Self::Jle),
"cmp" => Ok(Self::Cmp),
"inc" => Ok(Self::Inc),
"dec" => Ok(Self::Dec),
"shl" => Ok(Self::Shl),
"shr" => Ok(Self::Shr),
"add" => Ok(Self::Add),
"sub" => Ok(Self::Sub),
"and" => Ok(Self::And),
"or" => Ok(Self::Or),
"not" => Ok(Self::Not),
"xor" => Ok(Self::Xor),
"nand" => Ok(Self::Nand),
"nor" => Ok(Self::Nor),
"xnor" => Ok(Self::Xnor),
"int" => Ok(Self::Int),
"irt" => Ok(Self::Irt),
"hlt" => Ok(Self::Hlt),
"iadd" => Ok(Self::Iadd),
"isub" => Ok(Self::Isub),
"db" => Ok(Self::Db),
"dh" => Ok(Self::Dh),
"dw" => Ok(Self::Dw),
"resb" => Ok(Self::Resb),
"resh" => Ok(Self::Resh),
"resw" => Ok(Self::Resw),
"push" => Ok(Self::Push),
"pop" => Ok(Self::Pop),
"lwi" => Ok(Self::Lwi),
_ => Err(OpcodeFromStrError::InvalidRegister("unknown opcode")),
}
}
}
impl Opcode {
pub const OPCODES: &[&str] = &[
// Real instructions (0x00-0x26)
"nop", "mov", "movs", "ldb", "ldbs", "ldh", "ldhs", "ldw", "stb", "sth", "stw", "lli",
"lui", "jmp", "jeq", "jne", "jgt", "jge", "jlt", "jle", "cmp", "inc", "dec", "shl", "shr",
"add", "sub", "and", "or", "not", "xor", "nand", "nor", "xnor", "int", "irt", "hlt",
"iadd", "isub", // Pseudo-instructions
"nop", "mov", "movs", "ldb", "ldbs", "ldh", "ldhs", "ldw", "stb", "sth", "stw",
"lli", "lui", "jmp", "jeq", "jne", "jgt", "jge", "jlt", "jle", "cmp", "inc",
"dec", "shl", "shr", "add", "sub", "and", "or", "not", "xor", "nand", "nor",
"xnor", "int", "irt", "hlt", "iadd", "isub", // Pseudo-instructions
"db", "dh", "dw", "resb", "resh", "resw", "push", "pop", "lwi",
];
pub fn from_str(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"nop" => Some(Self::Nop),
"mov" => Some(Self::Mov),
"movs" => Some(Self::Movs),
"ldb" => Some(Self::Ldb),
"ldbs" => Some(Self::Ldbs),
"ldh" => Some(Self::Ldh),
"ldhs" => Some(Self::Ldhs),
"ldw" => Some(Self::Ldw),
"stb" => Some(Self::Stb),
"sth" => Some(Self::Sth),
"stw" => Some(Self::Stw),
"lli" => Some(Self::Lli),
"lui" => Some(Self::Lui),
"jmp" => Some(Self::Jmp),
"jeq" => Some(Self::Jeq),
"jne" => Some(Self::Jne),
"jgt" => Some(Self::Jgt),
"jge" => Some(Self::Jge),
"jlt" => Some(Self::Jlt),
"jle" => Some(Self::Jle),
"cmp" => Some(Self::Cmp),
"inc" => Some(Self::Inc),
"dec" => Some(Self::Dec),
"shl" => Some(Self::Shl),
"shr" => Some(Self::Shr),
"add" => Some(Self::Add),
"sub" => Some(Self::Sub),
"and" => Some(Self::And),
"or" => Some(Self::Or),
"not" => Some(Self::Not),
"xor" => Some(Self::Xor),
"nand" => Some(Self::Nand),
"nor" => Some(Self::Nor),
"xnor" => Some(Self::Xnor),
"int" => Some(Self::Int),
"irt" => Some(Self::Irt),
"hlt" => Some(Self::Hlt),
"iadd" => Some(Self::Iadd),
"isub" => Some(Self::Isub),
"db" => Some(Self::Db),
"dh" => Some(Self::Dh),
"dw" => Some(Self::Dw),
"resb" => Some(Self::Resb),
"resh" => Some(Self::Resh),
"resw" => Some(Self::Resw),
"push" => Some(Self::Push),
"pop" => Some(Self::Pop),
"lwi" => Some(Self::Lwi),
_ => None,
}
}
pub fn to_opcode_value(&self) -> Option<u8> {
match self {
Self::Nop => Some(0x00),
+9 -8
View File
@@ -59,9 +59,9 @@ impl Component for ControlPanel {
// Step
if ui.button("Step").clicked() {
self.sender
.send(Command::Step)
.unwrap_or_else(|_| state.error = Some("Failed to send command".to_string()));
self.sender.send(Command::Step).unwrap_or_else(|_| {
state.error = Some("Failed to send command".to_string());
});
}
ui.separator();
@@ -78,12 +78,13 @@ impl Component for ControlPanel {
ui.label(format!("Instructions: {}", state.instructions));
ui.label(format!("PC: 0x{:08X}", state.reg_file.get(Register::Pcx)));
let instruction = match Instruction::decode(state.reg_file.get(Register::Cir)) {
Ok(instruction) => instruction.to_string(),
Err(_) => "Invalid Instruction".to_string(),
};
let instruction = Instruction::decode(state.reg_file.get(Register::Cir))
.map_or_else(
|_| "Invalid Instruction".to_string(),
|instruction| instruction.to_string(),
);
ui.label(format!("Instruction: {}", instruction));
ui.label(format!("Instruction: {instruction}"));
});
render_register_table(state, ui, ctx);
+2 -2
View File
@@ -306,7 +306,7 @@ impl Editor {
self.sender
.send(Command::Write(self.load_offset, self.output.clone()))
.unwrap_or_else(|_| {
self.error = Some("Failed to send command".to_string())
self.error = Some("Failed to send command".to_string());
});
}
@@ -323,7 +323,7 @@ impl Editor {
// Resets the emulator and all attached devices
if ui.button("Reset Emulator").clicked() {
self.sender.send(Command::Reset).unwrap_or_else(|_| {
self.error = Some("Failed to send command".to_string())
self.error = Some("Failed to send command".to_string());
});
}
});