Skip to content

Commit

Permalink
Polishing
Browse files Browse the repository at this point in the history
Signed-off-by: Miquel Sabaté Solà <[email protected]>
  • Loading branch information
mssola committed Oct 9, 2024
1 parent 47ea0f3 commit e7591c8
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 105 deletions.
4 changes: 2 additions & 2 deletions lib/xixanta/src/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ impl Assembler {
fn evaluate_instruction(&mut self, node: &Box<PNode>) -> Result<Bundle, EvalError> {
let (mode, mut bundle) = match &node.left {
Some(_) => self.get_addressing_mode_and_bytes(node)?,
None => (AddressingMode::Implied, Bundle::new()),
None => (AddressingMode::Implied, Bundle::default()),
};

let mnemonic = node.value.value.to_lowercase();
Expand Down Expand Up @@ -529,7 +529,7 @@ impl Assembler {
left_arm: &Box<PNode>,
) -> Result<(AddressingMode, Bundle), EvalError> {
if left_arm.value.value.to_lowercase().trim() == "a" {
return Ok((AddressingMode::Implied, Bundle::new()));
return Ok((AddressingMode::Implied, Bundle::default()));
}

let val = self.evaluate_node(&left_arm)?.unwrap();
Expand Down
119 changes: 32 additions & 87 deletions lib/xixanta/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::errors::ParseError;
use std::fmt;
use std::ops::Range;

/// A Positioned String. That is, a String which also has information on the
/// line number and the column range.
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct PString {
/// The actual value.
pub value: String,
Expand All @@ -16,39 +15,17 @@ pub struct PString {
pub range: Range<usize>,
}

// TODO: documentation
impl PString {
pub fn new() -> Self {
PString {
value: String::from(""),
line: 0,
range: Range { start: 0, end: 0 },
}
}

pub fn from(value: &str) -> Self {
PString {
value: String::from(value),
line: 0,
range: Range { start: 0, end: 0 },
}
}

pub fn parser_error(&self, message: &str) -> ParseError {
// TODO: we can go further :)
ParseError {
line: self.line,
message: String::from(message),
}
}

pub fn is_valid(&self) -> bool {
!(self.value.is_empty() || self.range.is_empty())
/// Returns true if the string has either an empty value or an empty range.
pub fn is_empty(&self) -> bool {
self.value.is_empty() || self.range.is_empty()
}

/// Returns an empty tuple if the string contains a valid identifier, or a
/// String containing the error otherwise.
pub fn is_valid_identifier(&self) -> Result<(), String> {
if self.value.trim().is_empty() {
return Err(format!("empty identifier"));
return Err(String::from("empty identifier"));
}

// You cannot assign into a name which is reserved.
Expand All @@ -75,12 +52,10 @@ impl PString {
for c in self.value.to_lowercase().chars() {
if c == '_' {
valid_hex = false;
} else {
if c.is_alphabetic() {
alpha_seen = true;
if c > 'f' && c <= 'z' {
valid_hex = false;
}
} else if c.is_alphabetic() {
alpha_seen = true;
if c > 'f' && c <= 'z' {
valid_hex = false;
}
}
}
Expand All @@ -107,30 +82,32 @@ impl PString {
}
}

#[derive(Debug, Clone, PartialEq)]
/// A Bundle represents a set of bytes that can be encoded as binary data.
#[derive(Debug, Default, Clone)]
pub struct Bundle {
/// The bytes which make up any encodable element for the application. The
/// capacity is of three bytes maximum, but the actual size is encoded in
/// the `size` property.
pub bytes: [u8; 3],

/// The amount of bytes which have actually been set on this bundle.
pub size: u8,

/// The address where the given bytes are to be placed on the resulting
/// binary file.
pub address: usize,

/// If this bundle encodes an instruction, the amount of cycles it takes for
/// the CPU to actually execute it.
pub cycles: u8,
pub affected_on_page: bool,
}

impl Bundle {
pub fn new() -> Self {
Self {
bytes: [0, 0, 0],
size: 0,
address: 0,
cycles: 0,
affected_on_page: false,
}
}
/// Whether the cost in cycles is affected when crossing a page boundary.
pub affected_on_page: bool,
}

#[derive(Eq, Hash, PartialEq, Debug, Clone)]
/// Represents the addressing mode being used by an instruction.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum AddressingMode {
Unknown, // TODO: is this really used?
Implied,
Immediate,
Absolute,
Expand Down Expand Up @@ -158,11 +135,13 @@ impl fmt::Display for AddressingMode {
AddressingMode::Indirect => write!(f, "indirect"),
AddressingMode::IndirectX => write!(f, "indirect indexed by x"),
AddressingMode::IndirectY => write!(f, "indirect indexed by y"),
_ => write!(f, "unknown"),
}
}
}

/* TODO: it most probably can be removed
* TODO: if so, most of this stuff can probably be moved away into other files.
/// Encodable is a trait to be implemented by those structs that might need to
/// be encoded into the outside world. That is, structures that make sense to
/// output into files or other output streams.
Expand Down Expand Up @@ -206,40 +185,6 @@ pub struct Instruction {
pub resolved: bool,
}
impl Instruction {
pub fn unknown() -> Instruction {
Instruction {
mnemonic: PString::new(),
opcode: 0,
bytes: [0, 0],
size: 0,
left: None,
right: None,
mode: AddressingMode::Unknown,
cycles: 0,
affected_on_page: false,
address: 0,
resolved: true,
}
}

pub fn from(mnemonic: &str) -> Instruction {
Instruction {
mnemonic: PString::from(mnemonic),
opcode: 0,
bytes: [0, 0],
size: 0,
left: None,
right: None,
mode: AddressingMode::Unknown,
cycles: 0,
affected_on_page: false,
address: 0,
resolved: true,
}
}
}

impl Encodable for Instruction {
fn size(&self) -> u8 {
self.size
Expand Down Expand Up @@ -298,7 +243,6 @@ impl Encodable for Instruction {
AddressingMode::IndirectY => {
format!("{} (${:02X}), y", self.mnemonic.value, self.bytes[0])
}
AddressingMode::Unknown => String::from("unknown instruction"),
}
}
Expand Down Expand Up @@ -455,3 +399,4 @@ mod tests {
);
}
}
*/
25 changes: 11 additions & 14 deletions lib/xixanta/src/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
use crate::instruction::{Fill, Node, PString};
use std::collections::HashMap;

use crate::errors::ParseError;
type Result<T> = std::result::Result<T, ParseError>;

lazy_static! {
pub static ref EMPTY: Vec<Segment> = vec![Segment {
name: String::from("CODE"),
Expand All @@ -16,25 +10,25 @@ lazy_static! {
name: String::from("HEADER"),
start: 0x0000,
size: 0x0010,
fill: Some(Fill { value: 0x00 }),
fill: Some(0x00),
},
Segment {
name: String::from("VECTORS"),
start: 0xFFFA,
size: 0x0006,
fill: Some(Fill { value: 0x00 }),
fill: Some(0x00),
},
Segment {
name: String::from("CODE"),
start: 0x8000,
size: 0x7FFA,
fill: Some(Fill { value: 0x00 }),
fill: Some(0x00),
},
Segment {
name: String::from("CHARS"),
start: 0x0000,
size: 0x2000,
fill: Some(Fill { value: 0x00 }),
fill: Some(0x00),
}
];
}
Expand All @@ -44,9 +38,10 @@ pub struct Segment {
pub name: String,
pub start: u16,
pub size: usize,
pub fill: Option<Fill>,
pub fill: Option<usize>,
}

/* TODO
#[derive(Debug)]
pub struct Mapping {
pub segments: Vec<Segment>,
Expand Down Expand Up @@ -90,9 +85,10 @@ impl Mapping {
pub fn switch(&mut self, id: &PString) -> Result<()> {
if !self.nodes.contains_key(&id.value) {
return Err(
id.parser_error(format!("segment '{}' has not been defined", id.value).as_str())
);
// TODO
// return Err(
// id.parser_error(format!("segment '{}' has not been defined", id.value).as_str())
// );
}
id.value.clone_into(&mut self.current);
Expand All @@ -114,3 +110,4 @@ impl Mapping {
}
}
}
*/
4 changes: 2 additions & 2 deletions lib/xixanta/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ impl Parser {
// indirection itself.
left = Some(Box::new(PNode {
node_type: NodeType::Indirection,
value: PString::new(),
value: PString::default(),
left,
right: right.clone(),
args: None,
Expand Down Expand Up @@ -651,7 +651,7 @@ impl Parser {
// Reaching this condition is usually a bad sign, but there is so many
// ways in which it could go wrong, that an `assert!` wouldn't be fair
// either. Hence, just error out.
if !id.is_valid() {
if id.is_empty() {
return Err(self.parser_error("invalid identifier"));
}

Expand Down

0 comments on commit e7591c8

Please sign in to comment.