// 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 { // fn resolve_number(&self, data: &mut T) -> Result; // // fn resolve_bytes(&self, data: &mut T) -> Result, String>; // } // // #[derive(Debug)] // pub struct Macro { // pub args: Vec, // pub body: Vec, // } // // #[derive(Debug)] // pub enum State { // Default, // Macro { name: String, depth: usize }, // } // // #[derive(Debug)] // pub struct Data { // pub dir: String, // pub body: Vec, // pub program: [u8; 32 * 1024], // pub offset: u16, // pub contants: HashMap, // pub macros: HashMap, // pub state: State, // } // // impl Data { // pub fn new(dir: String, body: Vec) -> 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::(), // 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::, _>>() // { // 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 { fn resolve_number(&self, data: &mut T) -> Result; fn resolve_bytes(&self, data: &mut T) -> Result, String>; } #[derive(Debug)] pub enum ResolveResult { Resolved(Vec), 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, pub constants: HashMap, } 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 { while let Some(node) = self.body_stack.pop() { let res = self.resolve_node(node); dbg!(res); } Ok(self.program) } }