Works :)
This commit is contained in:
parent
60115d0612
commit
e309d2208a
108
src/assembler.rs
108
src/assembler.rs
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -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!("");
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue