This commit is contained in:
vanten-s 2024-08-11 04:25:14 +02:00
parent 60115d0612
commit e309d2208a
Signed by: vanten-s
GPG key ID: DE3060396884D3F2
4 changed files with 122 additions and 15 deletions

View file

@ -1,13 +1,111 @@
use crate::parser::Instruction;
use std::collections::HashMap;
use crate::{
parser::{Instruction, Value},
Result,
};
type Function = fn(&mut Assembler, usize);
pub struct Assembler {
instruction: Instruction,
functions: HashMap<String, Function>,
stack: Vec<String>,
assembled: Vec<u8>,
}
trait Assemble {
fn assemble(self, assembler: &mut Assembler) -> Result<()>;
}
impl Assemble for Value {
fn assemble(self, assembler: &mut Assembler) -> Result<()> {
match self {
Self::Instruction(instruction) => instruction.assemble(assembler),
Value::IntegerLiteral(v) => {
let bytes = v.to_le_bytes();
assembler.push(v.to_string());
assembler.add_instruction(&[0x68]);
assembler.add_instruction(&bytes);
Ok(())
}
_ => todo!()
}
}
}
impl Assemble for Instruction {
fn assemble(self, assembler: &mut Assembler) -> Result<()> {
let n_arguments = self.arguments.len();
for argument in self.arguments {
argument.assemble(assembler)?;
}
let function = match assembler.functions.get(&self.name) {
Some(v) => v,
None => return Err(crate::Error::UndefinedIdentifier(self.name))
};
function(assembler, n_arguments);
Ok(())
}
}
impl Assembler {
pub fn assemble(instruction: Instruction) -> Vec<u8> {
let assembler = Assembler { instruction };
pub fn assemble(instruction: Instruction) -> Result<Vec<u8>> {
let mut assembler = Self {
functions: Self::default_functions(),
stack: Vec::new(),
assembled: Vec::new(),
};
instruction.assemble(&mut assembler)?;
Ok(assembler.assembled)
}
todo!()
fn add_instruction(&mut self, instruction: &[u8]) {
self.assembled.extend_from_slice(instruction);
}
fn push(&mut self, identifier: String) {
self.stack.push(identifier);
}
fn pop(&mut self) {
self.stack.pop();
}
fn get_stack_location(&self, identifier: &str) -> Option<u32> {
self.stack
.iter()
.position(|x| x == identifier)
.map(|x| x as u32)
}
fn default_functions() -> HashMap<String, Function> {
let mut map: HashMap<String, Function> = HashMap::new();
map.insert(
"+".to_string(),
|assembler, n_arguments| {
if n_arguments != 2 { todo!() }
assembler.add_instruction(&[0x58]); // Pop EAX
assembler.pop();
assembler.add_instruction(&[0x03, 0x04, 0x24]); // add (%esp), %eax
assembler.add_instruction(&[0x5B]); // Pop EBX
assembler.pop();
assembler.add_instruction(&[0x50]); // Push EAX
assembler.push("".to_string());
},
);
map
}
}

View file

@ -1,6 +1,7 @@
#[derive(Clone, Debug, Hash)]
pub enum Error {
SyntaxError(SyntaxError),
UndefinedIdentifier(String),
}
#[derive(Clone, Debug, Hash)]
@ -16,6 +17,7 @@ impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::SyntaxError(e) => write!(f, "Error at: {}:{}. {}", e.row, e.column, e.message),
Error::UndefinedIdentifier(e) => write!(f, "Error: undefined identifier: {e}"),
}
}
}

View file

@ -6,7 +6,14 @@ mod error;
pub use error::*;
fn main() {
let code = "(+ 1 2)".to_string();
let code = "(+ 1 (+ 5 5))".to_string();
dbg!(parser::Parser::parse(code).unwrap());
let parsed = dbg!(parser::Parser::parse(code).unwrap());
let assembled = assembler::Assembler::assemble(parsed).unwrap();
for byte in assembled {
print!("{byte:#X}, ");
}
println!("");
}

View file

@ -7,17 +7,17 @@ pub struct Parser {
lines: Vec<Vec<char>>,
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub(crate) struct Instruction {
name: String,
arguments: Vec<Value>,
pub name: String,
pub arguments: Vec<Value>,
}
#[derive(Debug)]
enum Value {
#[derive(Debug, Clone)]
pub(crate) enum Value {
Instruction(Instruction),
StringLiteral(String),
IntegerLiteral(usize),
IntegerLiteral(u32),
Identifier(String),
}
@ -105,7 +105,7 @@ impl Parser {
Ok(accumulator)
}
fn integer_literal(&mut self) -> Result<usize> {
fn integer_literal(&mut self) -> Result<u32> {
let mut accumulator = String::new();
while self.lines[self.row][self.column].is_numeric() {
@ -115,7 +115,7 @@ impl Parser {
self.jump_whitespace();
match accumulator.parse::<usize>() {
match accumulator.parse() {
Ok(v) => Ok(v),
Err(_e) => Err(Error::SyntaxError(SyntaxError {
row: self.row,