wrote new "ContextTree" system, emulator filetree is kind of broken for now. next commit will fix this.

This commit is contained in:
2026-08-03 01:45:30 +01:00
parent e6ae60a798
commit 8d28bf39f8
10 changed files with 376 additions and 204 deletions
+23 -67
View File
@@ -4,17 +4,11 @@ use crate::{assembler::AssembleError, expect_token};
use common::prelude::*;
use dsa_tasks::ProcessAgent;
pub fn codegen(nodes: Vec<Node>, ctx: &ProcessAgent) -> Result<Vec<Instruction>, AssembleError> {
let mut instructions = vec![];
for node in nodes {
ctx.log(format!("{}", node));
instructions.push(build_instruction(&node)?);
}
ctx.log("Assembly Successful ✅");
Ok(instructions)
pub fn codegen(nodes: &[Node], ctx: &ProcessAgent) -> Result<Vec<Instruction>, AssembleError> {
nodes
.iter()
.map(build_instruction)
.collect::<Result<Vec<_>, _>>()
}
fn build_instruction(node: &Node) -> Result<Instruction, AssembleError> {
@@ -41,6 +35,7 @@ fn build_instruction(node: &Node) -> Result<Instruction, AssembleError> {
Opcode::Jmp | Opcode::Call | Opcode::Jic | Opcode::Jnc => {
ins_jump_unconditional(opcode, &args)
}
Opcode::Jez | Opcode::Jnz => ins_jump_conditional(opcode, &args),
Opcode::Shl | Opcode::Shr => ins_bitshift(opcode, &args),
Opcode::Add
@@ -72,10 +67,7 @@ fn build_instruction(node: &Node) -> Result<Instruction, AssembleError> {
}
}
fn ins_mov(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_mov(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -92,10 +84,7 @@ fn ins_mov(
}
}
fn ins_cmov(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_cmov(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -116,10 +105,7 @@ fn ins_cmov(
}
}
fn ins_ldx_stx(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_ldx_stx(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -147,10 +133,7 @@ fn ins_ldx_stx(
}
}
fn ins_stack(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_stack(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(reg_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -163,10 +146,7 @@ fn ins_stack(
}
}
fn ins_load_imm(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_load_imm(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(value_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -184,10 +164,7 @@ fn ins_load_imm(
}
}
fn ins_jump_unconditional(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_jump_unconditional(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(addr_imm_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -206,21 +183,16 @@ fn ins_jump_unconditional(
}
}
fn ins_jump_conditional(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_jump_conditional(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(condition_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
let Some(addr_imm_token) = args.get(1) else {
return Err(AssembleError::MissingArgument(1));
};
let addr_reg_token = if let Some(token) = args.get(2) {
token
} else {
&Token::Register(Register::Zero)
};
let addr_reg_token = args
.get(2)
.map_or(&Token::Register(Register::Zero), |token| token);
let condition = expect_token!(condition_token, Register)?;
let addr_imm = expect_token!(addr_imm_token, Immediate)?;
@@ -233,10 +205,7 @@ fn ins_jump_conditional(
})
}
fn ins_comparison(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_comparison(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(left_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -261,10 +230,7 @@ fn ins_comparison(
})
}
fn ins_bitshift(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_bitshift(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(src_reg) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -290,10 +256,7 @@ fn ins_bitshift(
})
}
fn ins_arithmetic(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_arithmetic(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(left_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -321,10 +284,7 @@ fn ins_arithmetic(
})
}
fn ins_imm_arithmetic(
opcode: Opcode,
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn ins_imm_arithmetic(opcode: Opcode, args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(reg_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -368,9 +328,7 @@ fn ins_interrupt(args: &[Token]) -> Result<Instruction, AssembleError> {
Ok(Instruction::int(code))
}
fn build_data_instruction(
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn build_data_instruction(args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(immediate_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -379,9 +337,7 @@ fn build_data_instruction(
Ok(Instruction::data(immediate))
}
fn build_segment_instruction(
args: &[Token],
) -> Result<Instruction, AssembleError> {
fn build_segment_instruction(args: &[Token]) -> Result<Instruction, AssembleError> {
let Some(immediate_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -390,6 +346,6 @@ fn build_segment_instruction(
Ok(Instruction::data(
// mask the first 6 bits for the opcode
// this is really deprecated tbh. may remove in future.
Opcode::Segment as u32 | (immediate & 0x05FFFFFF),
Opcode::Segment as u32 | (immediate & 0x05FF_FFFF),
))
}
+38 -34
View File
@@ -1,15 +1,16 @@
#![allow(dead_code, unused)]
use dsa_tasks::{ProcessAgent, TraceableProcess};
use crate::assembler::resolver2::{SectionId, resolve_address, resolve_dependencies, resolve_symbols, split_sections};
use crate::assembler::resolver2::{
SectionId, resolve_address, resolve_dependencies, resolve_symbols, split_sections,
};
use dsa_formats::binary_dse::{DseExecutable, SymbolEntry};
use dsa_tasks::{ProcessAgent, TraceableProcess};
use std::{
collections::HashSet,
fmt, fs,
hash::{DefaultHasher, Hash, Hasher},
path::{Path, PathBuf},
sync::
mpsc::{self},
sync::mpsc::{self},
};
// Module declarations
@@ -64,6 +65,16 @@ impl TraceableProcess for Assembler {
fn run(mut self: Box<Self>, ctx: ProcessAgent) -> Result<Self::Output, Self::Error> {
assemble(&self.src_path, &ctx)
}
fn label(&self) -> String {
format!(
"Assembling {}",
self.src_path
.file_name()
.expect("a valid path must have a file name")
.to_string_lossy()
)
}
}
fn assemble(src: &Path, ctx: &ProcessAgent) -> Result<DseExecutable, AssembleError> {
@@ -74,21 +85,14 @@ fn assemble(src: &Path, ctx: &ProcessAgent) -> Result<DseExecutable, AssembleErr
let nodes = program.nodes.clone();
// for node in &nodes {
// ctx.log(format!("{:?}", node));
// }
let (data_nodes, mut text_nodes) = split_sections(nodes);
let symbol_table = resolve_symbols(&data_nodes, &mut text_nodes)?;
let text_len = text_nodes.len() as u32;
ctx.log("Generating assembly output...");
ctx.log("Generating Instructions...");
// println!("Generating assembly output...");
let instructions = codegen(text_nodes, ctx)?;
let text: Vec<u32> = instructions
.iter()
.map(|i| i.0).collect();
let instructions = codegen(&text_nodes, ctx)?;
let text: Vec<u32> = instructions.iter().map(|i| i.0).collect();
let data = build_data_bytes(&data_nodes)?;
@@ -117,20 +121,16 @@ fn assemble(src: &Path, ctx: &ProcessAgent) -> Result<DseExecutable, AssembleErr
.iter()
.find(|(sym, _)| sym.name == "_init")
.map(|(_, entry)| resolve_address(*entry, text_len))
.ok_or(AssembleError::UndefinedSymbol(Symbol {
name: "_init".to_string(),
module: Module::Resolved(0),
}))?;
.ok_or_else(|| {
AssembleError::UndefinedSymbol(Symbol {
name: "_init".to_string(),
module: Module::Resolved(0),
})
})?;
ctx.log("Compilation Successful");
Ok(DseExecutable::new(
symbols.as_slice(),
&string_table,
&data,
&text,
entry_point,
).unwrap())
Ok(DseExecutable::new(symbols.as_slice(), &string_table, &data, &text, entry_point).unwrap())
}
fn build_data_bytes(data_nodes: &[Node]) -> Result<Vec<u8>, AssembleError> {
@@ -144,7 +144,6 @@ fn build_data_bytes(data_nodes: &[Node]) -> Result<Vec<u8>, AssembleError> {
Ok(bytes)
}
fn prepare_dependency(
path: &Path,
modules: &mut HashSet<u64>,
@@ -157,21 +156,26 @@ fn prepare_dependency(
.expect("Failed to get file name from path");
if let Ok(path) = path.canonicalize() {
ctx.log(format!("{:20} {:20} [{}]", "Building", filename, path.display()));
ctx.log(format!(
"{:30} {:20} [{}]",
"Building",
filename,
path.display()
));
}
let src =
fs::read_to_string(path).map_err(|_| AssembleError::InvalidFile(path.to_path_buf()))?;
let file_hash = quick_hash(path);
ctx.log(format!("{:20} {:20}", "Tokenising", filename));
ctx.log(format!("{:30} {:20}", "Lexing", filename));
let tokens = lexer::lexer(src, file_hash)?;
// let tokens = Lexer::new(src, file_hash).run()?;
ctx.log(format!("{:20} {:20}", "Parsing", filename));
ctx.log(format!("{:30} {:20}", "Parsing", filename));
let parsed = Parser::parse_nodes(tokens)?;
ctx.log(format!("{:20} {:20}", "Resolving Deps", filename));
ctx.log(format!("{:30} {:20}", "Resolving Dependencies", filename));
// Get the parent directory of the source file to use as the base directory
let base_dir = path
.parent()
@@ -181,20 +185,20 @@ fn prepare_dependency(
let deps = Parser::get_dependencies(&nodes, path)?;
ctx.log(format!("{:20} {:20}", "Expanding Pseudo-ops", filename));
ctx.log(format!("{:30} {:20}", "Expanding Macros", filename));
// add a section instruction
nodes.insert(
0,
node!(None, Opcode::Segment, Token::Immediate(file_hash as u32)),
);
program.add_module(nodes);
for dep in deps {
ctx.log(format!(
"{:20} {:20}",
"Including",
"Including Dependency",
dep.file_name()
.and_then(|f| f.to_str())
.expect("Dependency path has no file name or is not valid UTF-8")
@@ -202,7 +206,7 @@ fn prepare_dependency(
let dep_hash = quick_hash(&dep);
if modules.insert(dep_hash) {
prepare_dependency(dep.as_path(), modules, program, &ctx)?;
prepare_dependency(dep.as_path(), modules, program, ctx)?;
}
}