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 {
|
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 {
|
impl Assembler {
|
||||||
pub fn assemble(instruction: Instruction) -> Vec<u8> {
|
pub fn assemble(instruction: Instruction) -> Result<Vec<u8>> {
|
||||||
let assembler = Assembler { instruction };
|
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)]
|
#[derive(Clone, Debug, Hash)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
SyntaxError(SyntaxError),
|
SyntaxError(SyntaxError),
|
||||||
|
UndefinedIdentifier(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash)]
|
#[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 {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::SyntaxError(e) => write!(f, "Error at: {}:{}. {}", e.row, e.column, e.message),
|
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::*;
|
pub use error::*;
|
||||||
|
|
||||||
fn main() {
|
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>>,
|
lines: Vec<Vec<char>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Instruction {
|
pub(crate) struct Instruction {
|
||||||
name: String,
|
pub name: String,
|
||||||
arguments: Vec<Value>,
|
pub arguments: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
enum Value {
|
pub(crate) enum Value {
|
||||||
Instruction(Instruction),
|
Instruction(Instruction),
|
||||||
StringLiteral(String),
|
StringLiteral(String),
|
||||||
IntegerLiteral(usize),
|
IntegerLiteral(u32),
|
||||||
Identifier(String),
|
Identifier(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ impl Parser {
|
||||||
Ok(accumulator)
|
Ok(accumulator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn integer_literal(&mut self) -> Result<usize> {
|
fn integer_literal(&mut self) -> Result<u32> {
|
||||||
let mut accumulator = String::new();
|
let mut accumulator = String::new();
|
||||||
|
|
||||||
while self.lines[self.row][self.column].is_numeric() {
|
while self.lines[self.row][self.column].is_numeric() {
|
||||||
|
@ -115,7 +115,7 @@ impl Parser {
|
||||||
|
|
||||||
self.jump_whitespace();
|
self.jump_whitespace();
|
||||||
|
|
||||||
match accumulator.parse::<usize>() {
|
match accumulator.parse() {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
Err(_e) => Err(Error::SyntaxError(SyntaxError {
|
Err(_e) => Err(Error::SyntaxError(SyntaxError {
|
||||||
row: self.row,
|
row: self.row,
|
||||||
|
|
Loading…
Reference in a new issue