diff --git a/Cargo.lock b/Cargo.lock index 3ef61c2..14bb9f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,127 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "riscv_interpreter" version = "0.1.0" +dependencies = [ + "codespan-reporting", + "itertools", + "rayon", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 883d84e..db2436e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,8 @@ name = "riscv_interpreter" version = "0.1.0" edition = "2021" + +[dependencies] +codespan-reporting = { version = "0.11.1", features = ["ascii-only"] } +itertools = "0.12.0" +rayon = "1.8.1" diff --git a/src/env.rs b/src/env.rs index 8c9dc18..87adf33 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,3 +1,79 @@ +use std::collections::HashMap; +#[derive(Debug)] +pub struct Env { + register_alias: HashMap, + labels: HashMap, + registers: [i64; 32], + stack: Vec, // TODO: Find the size of the stack +} -pub enum Env {} +impl Env { + pub fn new() -> Self { + // alias -> xN + let register_alias = [ + ("zero", 0), + ("ra", 1), + ("sp", 2), + ("gp", 3), + ("tp", 4), + ("t0", 5), + ("t1", 6), + ("t2", 7), + ("s0", 8), + ("s1", 9), + ("a0", 10), + ("a1", 11), + ("a2", 12), + ("a3", 13), + ("a4", 14), + ("a5", 15), + ("a6", 16), + ("a7", 17), + ("s2", 18), + ("s3", 19), + ("s4", 20), + ("s5", 21), + ("s6", 22), + ("s7", 23), + ("s8", 24), + ("s9", 25), + ("s10", 26), + ("s11", 27), + ("t3", 28), + ("t4", 29), + ("t5", 30), + ("t6", 31), + ] + .iter() + .map(|(k, v)| (k.to_string(), v.to_owned())) + .collect::>(); + + Self { + register_alias, + labels: HashMap::new(), + registers: [0; 32], + stack: Vec::new(), + } + } + + pub fn set_register(&mut self, reg: usize, value: i64) { + self.registers[reg] = value; + } + + pub fn get_register(&self, reg: usize) -> i64 { + self.registers[reg] + } + + pub fn alias_to_register(&self, reg: &str) -> Option { + self.register_alias.get(reg).copied() + } + + pub fn add_label(&mut self, label: &str, value: usize) { + self.labels.insert(label.to_string(), value); + } + + pub fn get_label(&self, label: &str) -> Option { + self.labels.get(label).copied() + } +} diff --git a/src/err.rs b/src/err.rs index 83ede89..efe1608 100644 --- a/src/err.rs +++ b/src/err.rs @@ -1,19 +1,26 @@ use std::fmt::{self, Display, Formatter}; +#[derive(Debug, Clone)] pub enum SyntaxErr { TraillingComma, - UnmatchedParen, + /// false for '(' true for ')' + UnmatchedParen(bool), + UnexpectedChar, + OutsideOp(String), } impl Display for SyntaxErr { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { SyntaxErr::TraillingComma => write!(f, "trailling comma"), - SyntaxErr::UnmatchedParen => write!(f, "unmatched parenthesis"), + SyntaxErr::UnmatchedParen(_) => write!(f, "unmatched parenthesis"), + SyntaxErr::UnexpectedChar => write!(f, "unexpected character"), + SyntaxErr::OutsideOp(kind) => write!(f, "{kind} before opcode"), } } } +#[derive(Debug, Clone)] pub enum RuntimeErr { InvalidRegister(String), UnexpectedImmediate, diff --git a/src/main.rs b/src/main.rs index e7a11a9..9c14777 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,9 @@ +use rayon::prelude::*; +use riscv_interpreter::parser::{parse, Token}; + fn main() { - println!("Hello, world!"); + let input = std::fs::read_to_string("test.s").unwrap(); + let tokens = parse(&input); + // println!("{:#?} -> {:#?}", input, tokens.into_par_iter().filter(|(token, _)| !matches!(token, Token::Spacing)).collect::>()); + println!("{:#?} -> {:#?}", input, tokens); } diff --git a/src/parser.rs b/src/parser.rs index ab0197d..6cfda23 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,23 +1,245 @@ -pub enum Expr { +/// TODO: Strings, Symbols +use crate::err::SyntaxErr; +use itertools::Itertools; +use rayon::prelude::*; + +#[derive(Debug, Clone)] +pub enum Token { + /// ' ', '\t', '\r' + Spacing, + /// \# blablabla, + Comment, /// 1, 2, -1 Immediate(i64), /// zero, r1, pc + /// + /// Technically also label references and symbols, but we'll handle those later Register(String), /// add, xor, j - Op(Vec), + Op(String, Vec<(Token, Loc)>), ///