hence/src/lib/assembler.rs

355 lines
14 KiB
Rust

// use itertools::Itertools;
// use radix_fmt::radix;
// use std::collections::HashMap;
//
// use crate::arg;
// use crate::parser;
//
// pub trait ToCode {
// fn to_code(&self) -> String;
// }
//
// pub trait ByteResolvable<T> {
// fn resolve_number(&self, data: &mut T) -> Result<u16, String>;
//
// fn resolve_bytes(&self, data: &mut T) -> Result<Vec<u8>, String>;
// }
//
// #[derive(Debug)]
// pub struct Macro {
// pub args: Vec<String>,
// pub body: Vec<parser::ast::Node>,
// }
//
// #[derive(Debug)]
// pub enum State {
// Default,
// Macro { name: String, depth: usize },
// }
//
// #[derive(Debug)]
// pub struct Data {
// pub dir: String,
// pub body: Vec<parser::ast::Node>,
// pub program: [u8; 32 * 1024],
// pub offset: u16,
// pub contants: HashMap<String, arg::Arg>,
// pub macros: HashMap<String, Macro>,
// pub state: State,
// }
//
// impl Data {
// pub fn new(dir: String, body: Vec<parser::ast::Node>) -> Self {
// Self {
// dir,
// body,
// program: [0; 32 * 1024],
// offset: 0,
// contants: HashMap::new(),
// macros: HashMap::new(),
// state: State::Default,
// }
// }
// }
//
// pub fn assemble(data: &mut Data) -> Result<(), String> {
// for node in data.body.clone() {
// data.contants
// .insert("OFFSET".to_string(), arg::Arg::Number(data.offset));
//
// match &data.state {
// State::Default => {
// match node {
// parser::ast::Node::Comment(_) => {}
// parser::ast::Node::Label(x) => {
// if data.contants.contains_key(&x) {
// return Err(format!("Label already exists: '{x}'"));
// }
//
// data.contants
// .insert(x.to_string(), arg::Arg::Number(data.offset));
// }
// parser::ast::Node::Call { name, arg } => {
// let arg_num = match arg {
// Some(x) => x.resolve_number(data).unwrap(),
// _ => 0,
// };
//
// data.program[data.offset as usize] = match name.as_str() {
// "nop" => 0x00,
// "push" => 0x01,
// "pop" => 0x02,
// "ts" => 0x03,
// "tsr" => 0x04,
// "tss" => 0x05,
// "tlr" => 0x06,
// "tlrc" => 0x07,
// "tls" => 0x08,
// "ld" => 0x09,
// "dbg" => 0x0a,
// "alu" => 0x0b,
// "get" => 0x0c,
// "set" => 0x0d,
// _ => return Err(format!("Unknown opcode: '{name}'")),
// };
// if arg_num == 0 {
// data.program[data.offset as usize] |= 0b10000000;
// }
// data.offset += 1;
//
// if arg_num != 0 {
// data.program[data.offset as usize] = (arg_num >> 8) as u8;
// data.offset += 1;
//
// data.program[data.offset as usize] = arg_num as u8;
// data.offset += 1;
// }
// }
// parser::ast::Node::MacroCall { name, args } => {
// match name.as_str() {
// "debug" => {
// for arg in args {
// let bytes = arg.resolve_bytes(data).unwrap();
//
// println!("{}", arg.to_code().replace('\n', "\\n"));
// println!(" => {}", arg.resolve_number(data).unwrap());
// println!(
// " => [{}]",
// bytes
// .iter()
// .map(|n| {
// let num = radix(*n, 16).to_string();
// format!(
// "0x{}{}",
// "00".chars()
// .take(2 - num.len())
// .collect::<String>(),
// num
// )
// })
// .join(", ")
// );
// println!(
// " => \"{}\"",
// String::from_utf8(bytes).unwrap().replace('\n', "\\n")
// );
// }
// println!("==========");
// }
// "define" => {
// let name = match &args[0] {
// arg::Arg::Variable(x) | arg::Arg::String(x) => x,
// _ => return Err(
// "First argument of define macro needs to be a literal-like"
// .to_string(),
// ),
// };
//
// data.contants.insert(name.to_string(), (&args[1]).clone());
// }
// "macro" => {
// let name = match &args[0] {
// arg::Arg::Variable(x) | arg::Arg::String(x) => x,
// _ => return Err(
// "First argument of define macro needs to be a literal-like"
// .to_string(),
// ),
// };
// let args = match (&args[1..])
// .iter()
// // .map(|a| match a {
// // arg::Arg::Variable(x) => Ok(x.clone()),
// // __ => {
// // Err("Macro arguments need to be variables".to_string())
// // }
// // })
// .map(|a| {
// if let arg::Arg::Variable(x) = a {
// Ok(x.clone())
// } else {
// Err("Macro arguments need to be variables".to_string())
// }
// })
// .collect::<Result<Vec<_>, _>>()
// {
// Ok(x) => x,
// Err(x) => return Err(x),
// };
//
// data.macros.insert(
// name.clone(),
// Macro {
// args,
// body: Vec::new(),
// },
// );
// data.state = State::Macro {
// name: name.clone(),
// depth: 1,
// };
// }
// "macroend" => return Err("Unexpected macro end".to_string()),
// "org" => {
// data.offset = args[0].resolve_number(data).unwrap();
// }
// "org_add" => {
// data.offset += args[0].resolve_number(data).unwrap();
// }
// "org_sub" => {
// data.offset -= args[0].resolve_number(data).unwrap();
// }
// "bytes" => {
// for arg in args {
// for n in arg.resolve_bytes(data).unwrap() {
// data.program[data.offset as usize] = n;
// data.offset += 1;
// }
// }
// }
// "bw" => {
// let string_arg = args[0].resolve_bytes(data).unwrap();
// let string =
// String::from_utf8(string_arg).unwrap().replace("\\n", "\n");
//
// for n in string.bytes() {
// data.program[data.offset as usize] = n;
// data.offset += 1;
// }
// }
// _ => match data.macros.get(&name) {
// Some(m) => {
// dbg!(name, m);
// }
// None => return Err(format!("Unknown macro: '{name}'")),
// },
// };
// }
// }
// }
// State::Macro { name, depth } => match &node {
// parser::ast::Node::MacroCall {
// name: node_name,
// args: _,
// } => match node_name.as_str() {
// "macro" => {
// data.state = State::Macro {
// name: name.clone(),
// depth: depth + 1,
// };
// }
// "macroend" => {
// if *depth - 1 == 0 {
// data.state = State::Default;
// } else {
// data.state = State::Macro {
// name: name.clone(),
// depth: depth - 1,
// };
// }
// }
// _ => {
// data.macros.get_mut(name).unwrap().body.push(node.clone());
// }
// },
// _ => {
// data.macros.get_mut(name).unwrap().body.push(node.clone());
// }
// },
// }
//
// if data.offset > (32 * 1024) {
// return Err(format!(
// "Offset out of bounds: 0x{} > 0x8000",
// radix(data.offset, 16),
// ));
// }
// }
//
// Ok(())
// }
use anyhow::Result;
use std::collections::HashMap;
use crate::arg;
use crate::parser;
pub trait ToAssembly {
fn to_assembly(&self) -> String;
}
pub trait ByteResolvable<T> {
fn resolve_number(&self, data: &mut T) -> Result<u16, String>;
fn resolve_bytes(&self, data: &mut T) -> Result<Vec<u8>, String>;
}
#[derive(Debug)]
pub enum ResolveResult {
Resolved(Vec<u8>),
Partial(u16),
Unresolved,
}
impl ResolveResult {
pub fn empty() -> Self {
ResolveResult::Resolved(vec![])
}
}
pub const PROGRAM_SIZE: u16 = 32 * 1024;
pub type Program = [u8; PROGRAM_SIZE as usize];
pub struct Data {
pub dir: String,
pub ast: parser::ast::AST,
pub program: Program,
pub offset: u16,
pub body_stack: Vec<parser::ast::Node>,
pub constants: HashMap<String, arg::Arg>,
}
impl Data {
pub fn new(dir: String, ast: parser::ast::AST) -> Self {
Self {
dir,
body_stack: ast.body.iter().rev().cloned().collect(),
ast,
program: [0; PROGRAM_SIZE as usize],
offset: 0,
constants: HashMap::new(),
}
}
pub fn resolve_node(&mut self, node: parser::ast::Node) -> ResolveResult {
match node {
parser::ast::Node::Comment(_) => ResolveResult::empty(),
parser::ast::Node::Label(x) => {
self.constants.insert(x, arg::Arg::Number(self.offset));
ResolveResult::empty()
}
parser::ast::Node::Call { name, arg } => {
dbg!(name, arg);
ResolveResult::empty()
}
parser::ast::Node::MacroCall { name, args } => {
dbg!(name, args);
ResolveResult::empty()
}
}
}
pub fn assemble(&mut self) -> Result<Program> {
while let Some(node) = self.body_stack.pop() {
let res = self.resolve_node(node);
dbg!(res);
}
Ok(self.program)
}
}