Skip to content

Commit

Permalink
Use result when looking up addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
jeroenbakker-atmind committed Jan 29, 2025
1 parent 14f867e commit 9972020
Show file tree
Hide file tree
Showing 21 changed files with 216 additions and 142 deletions.
8 changes: 5 additions & 3 deletions c64-assembler/examples/black_border_d64.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use c64_assembler::generator::Generator;
use c64_assembler::generator::ProgramGenerator;
use c64_assembler::validator::AssemblerResult;
use c64_assembler_macro::application;
use cbm::disk::directory::FileType;
use cbm::disk::file::{FileOps, Scheme};
use cbm::disk::{Disk, Id, D64};
use cbm::Petscii;

fn main() {
fn main() -> AssemblerResult<()> {
let application = application!(
name="Set black border"
include_vic20_defines
Expand All @@ -21,10 +22,10 @@ fn main() {
rts
)
)
);
)?;

// Compile to program.
let program = ProgramGenerator::default().generate(application);
let program = ProgramGenerator::default().generate(application)?;

// Create a disk in memory.
let geometry = D64::geometry(false);
Expand All @@ -42,4 +43,5 @@ fn main() {
disk.iter().flatten().for_each(|entry| {
println!("{:<4} {:<16}", entry.file_size, entry.filename);
});
Ok(())
}
8 changes: 5 additions & 3 deletions c64-assembler/examples/black_border_dasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use c64_assembler::builder::InstructionBuilder;
use c64_assembler::builder::ModuleBuilder;
use c64_assembler::generator::DasmGenerator;
use c64_assembler::generator::Generator;
use c64_assembler::validator::AssemblerResult;

fn main() {
fn main() -> AssemblerResult<()> {
let application = ApplicationBuilder::default()
.name("Set black border")
.include_vic20_defines()
Expand All @@ -23,8 +24,9 @@ fn main() {
)
.build(),
)
.build();
.build()?;

let source = DasmGenerator::default().generate(application);
let source = DasmGenerator::default().generate(application)?;
println!("{source}");
Ok(())
}
8 changes: 5 additions & 3 deletions c64-assembler/examples/black_border_macro.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use c64_assembler::generator::Generator;
use c64_assembler::generator::{print_hexdump, ProgramGenerator};
use c64_assembler::validator::AssemblerResult;
use c64_assembler_macro::application;

fn main() {
fn main() -> AssemblerResult<()> {
let application = application!(
name="Set black border"
include_vic20_defines
Expand All @@ -17,8 +18,9 @@ fn main() {
rts
)
)
);
)?;

let bytes = ProgramGenerator::default().generate(application);
let bytes = ProgramGenerator::default().generate(application)?;
print_hexdump(&bytes);
Ok(())
}
8 changes: 5 additions & 3 deletions c64-assembler/examples/black_border_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use c64_assembler::builder::InstructionBuilder;
use c64_assembler::builder::ModuleBuilder;
use c64_assembler::generator::Generator;
use c64_assembler::generator::{print_hexdump, ProgramGenerator};
use c64_assembler::validator::AssemblerResult;

fn main() {
fn main() -> AssemblerResult<()> {
let application = ApplicationBuilder::default()
.name("Set black border")
.include_vic20_defines()
Expand All @@ -23,8 +24,9 @@ fn main() {
)
.build(),
)
.build();
.build()?;

let bytes = ProgramGenerator::default().generate(application);
let bytes = ProgramGenerator::default().generate(application)?;
print_hexdump(&bytes);
Ok(())
}
8 changes: 5 additions & 3 deletions c64-assembler/examples/zeropage_addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use c64_assembler::builder::InstructionBuilder;
use c64_assembler::builder::ModuleBuilder;
use c64_assembler::generator::Generator;
use c64_assembler::generator::{print_hexdump, ProgramGenerator};
use c64_assembler::validator::AssemblerResult;

fn main() {
fn main() -> AssemblerResult<()> {
let zeropage_fe = "ADDRESS_ZEROPAGE_FE";
let address_c000 = "ADDRESS_C000";

Expand All @@ -28,8 +29,9 @@ fn main() {
)
.build(),
)
.build();
.build()?;

let bytes = ProgramGenerator::default().generate(application);
let bytes = ProgramGenerator::default().generate(application)?;
print_hexdump(&bytes);
Ok(())
}
7 changes: 4 additions & 3 deletions c64-assembler/src/builder/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
label::AddressReference,
Address, ZeroPage,
},
validator::AssemblerResult,
Application, Module,
};

Expand Down Expand Up @@ -284,9 +285,9 @@ impl ApplicationBuilder {
}

/// Build the application
pub fn build(&mut self) -> Application {
finalize(&mut self.application);
self.application.clone()
pub fn build(&mut self) -> AssemblerResult<Application> {
finalize(&mut self.application)?;
Ok(self.application.clone())
}
}

Expand Down
30 changes: 17 additions & 13 deletions c64-assembler/src/builder/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use crate::{
user_count::UserCount,
Address,
},
validator::AssemblerResult,
Application, Instructions,
};

pub fn finalize(application: &mut Application) {
pub fn finalize(application: &mut Application) -> AssemblerResult<()> {
defines_update_user_count(application);
functions_update_user_count(application);
update_label_addresses(application);
update_label_addresses(application)
}

fn defines_update_user_count(application: &mut Application) {
Expand Down Expand Up @@ -92,29 +93,32 @@ fn count_users_instructions(instructions: &Instructions, name: &String) -> usize
result
}

fn update_label_addresses(application: &mut Application) {
fn update_label_addresses(application: &mut Application) -> AssemblerResult<()> {
let mut label_addresses = HashMap::<String, Address>::default();
let mut function_addresses = HashMap::<String, Address>::default();
let mut current_address = application.entry_point;

let mut update_label_addresses_instructions = |current_address: &mut Address, instructions: &Instructions| {
for instruction in &instructions.instructions {
if let Operation::Label(label) = &instruction.operation {
label_addresses.insert(label.clone(), *current_address);
let mut update_label_addresses_instructions =
|current_address: &mut Address, instructions: &Instructions| -> AssemblerResult<()> {
for instruction in &instructions.instructions {
if let Operation::Label(label) = &instruction.operation {
label_addresses.insert(label.clone(), *current_address);
}
let byte_size = instruction.byte_size(application)?;
*current_address += byte_size;
}
let byte_size = instruction.byte_size(application);
*current_address += byte_size;
}
};
Ok(())
};

for module in &application.modules {
update_label_addresses_instructions(&mut current_address, &module.instructions);
update_label_addresses_instructions(&mut current_address, &module.instructions)?;
for function in &module.functions {
function_addresses.insert(function.name.clone(), current_address);
update_label_addresses_instructions(&mut current_address, &function.instructions);
update_label_addresses_instructions(&mut current_address, &function.instructions)?;
}
}

application.address_lookup.extend(label_addresses);
application.address_lookup.extend(function_addresses);
Ok(())
}
5 changes: 3 additions & 2 deletions c64-assembler/src/generator/dasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
user_count::UserCount,
ZeroPage,
},
validator::AssemblerResult,
Application, Function, Instructions, Module,
};

Expand All @@ -29,7 +30,7 @@ impl Default for DasmGenerator {
impl Generator for DasmGenerator {
type Output = String;

fn generate(mut self, application: Application) -> Self::Output {
fn generate(mut self, application: Application) -> AssemblerResult<Self::Output> {
self.line(format!("; --- Application: {} ---", application.name.to_uppercase()));
self.line("; NOTE: This file is generated, do not modify".to_string());
self.line_new();
Expand All @@ -48,7 +49,7 @@ impl Generator for DasmGenerator {
self.module(&application, module);
}

self.output.join("\n")
Ok(self.output.join("\n"))
}
}

Expand Down
4 changes: 2 additions & 2 deletions c64-assembler/src/generator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Generators to export to a .PRG or source code.
use crate::Application;
use crate::{validator::AssemblerResult, Application};

mod dasm;
mod program;
Expand All @@ -9,7 +9,7 @@ pub trait Generator {
type Output;

/// Generate an output for the given application.
fn generate(self, application: Application) -> Self::Output;
fn generate(self, application: Application) -> AssemblerResult<Self::Output>;
}

pub use dasm::*;
Expand Down
40 changes: 24 additions & 16 deletions c64-assembler/src/generator/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
address_mode::{AddressMode, Immediate},
Address, ZeroPage,
},
validator::{AssemblerResult, Error},
Application, Instructions, Module,
};

Expand All @@ -25,46 +26,53 @@ pub struct ProgramGenerator {
impl Generator for ProgramGenerator {
type Output = Vec<u8>;

fn generate(mut self, application: Application) -> Self::Output {
fn generate(mut self, application: Application) -> AssemblerResult<Self::Output> {
self.add_u16(application.entry_point);
for module in &application.modules {
self.generate_module(&application, module);
self.generate_module(&application, module)?;
}
self.output
Ok(self.output)
}
}

impl ProgramGenerator {
fn generate_module(&mut self, application: &Application, module: &Module) {
self.generate_instructions(application, &module.instructions);
fn generate_module(&mut self, application: &Application, module: &Module) -> AssemblerResult<()> {
self.generate_instructions(application, &module.instructions)?;
for function in &module.functions {
self.generate_instructions(application, &function.instructions);
self.generate_instructions(application, &function.instructions)?;
}
Ok(())
}

fn generate_instructions(&mut self, application: &Application, instructions: &Instructions) {
fn generate_instructions(&mut self, application: &Application, instructions: &Instructions) -> AssemblerResult<()> {
for instruction in &instructions.instructions {
self.generate_instruction(application, instruction);
self.generate_instruction(application, instruction)?;
}
Ok(())
}

fn generate_instruction(&mut self, application: &Application, instruction: &Instruction) {
fn generate_instruction(&mut self, application: &Application, instruction: &Instruction) -> AssemblerResult<()> {
match (&instruction.operation.definition(), &instruction.operation) {
(Some(definition), _) => {
self.add_byte_code(application, &instruction.address_mode, definition);
}
(Some(definition), _) => self.add_byte_code(application, &instruction.address_mode, definition),
(None, Operation::Label(_)) => {
// Labels don't have bytes in the byte stream, they are only markers
Ok(())
}
(None, Operation::Raw(bytes)) => {
self.add_bytes(bytes);
Ok(())
}

(_, _) => panic!(),
(_, _) => Err(Error::InternalCompilerError),
}
}

fn add_byte_code(&mut self, application: &Application, address_mode: &AddressMode, instruction: &InstructionDef) {
fn add_byte_code(
&mut self,
application: &Application,
address_mode: &AddressMode,
instruction: &InstructionDef,
) -> AssemblerResult<()> {
match address_mode {
AddressMode::Implied => {
self.add_u8(instruction.implied);
Expand Down Expand Up @@ -117,11 +125,10 @@ impl ProgramGenerator {
self.add_u16(address);
}
AddressMode::Relative(address_reference) => {
const RELATIVE_INSTRUCTION_BYTE_SIZE: Address = 2;
let current_instruction =
application.entry_point + self.output.len() as Address - PROGRAM_HEADER_BYTE_SIZE;
let address = application.address(address_reference);
let next_instruction = current_instruction + RELATIVE_INSTRUCTION_BYTE_SIZE;
let next_instruction = current_instruction + address_mode.byte_size(application)?;
let relative_address = (address as i32 - next_instruction as i32) as i8;

self.add_u8(instruction.relative);
Expand All @@ -144,6 +151,7 @@ impl ProgramGenerator {
self.add_u8(address.low());
}
};
Ok(())
}
}

Expand Down
Loading

0 comments on commit 9972020

Please sign in to comment.