msp430-repl/src/lib.rs
John Breaux fc8f8b9622 v0.3.0: Total overhaul
- Everything has been rewritten
- Modularity is improved somewhat
  - No dependency injection in preprocessor/parser, though
- There are now early and late constant evaluation engines
  - This engine allows for by-value access to already-assembled code
  - Performs basic math operations, remainder, bitwise logic, bit shifts, negation, and bit inversion
  - Also allows for indexing into already-generated code using pointer-arithmetic syntax: `*(&main + 10)`. This is subject to change? It's clunky, and only allows word-aligned access. However, this rewrite is taking far too long, so I'll call the bikeshedding here.
  - Pretty sure this constant evaluation is computationally equivalent to Deadfish?
2024-01-30 05:27:12 -06:00

109 lines
3.9 KiB
Rust

// © 2023 John Breaux
//! A bare-bones toy assembler for the TI MSP430, for use in MicroCorruption
//!
//! This project aims to assemble any valid msp430 instructions, while being lenient about the
//! syntax. After all, a real-world parser is going to face all kinds of malformed input, and it
//! would be nice to support that kind of input (or, if it's completely unsalvageable, provide a
//! useful message to the author.)
//!
//! The [`Parser`](preamble::Parser) will ignore whitespace, excluding newlines,
//! unless syntactically relevant. It will also discard comma-separators between operands of a
//! two-operand instruction.
//!
//! It returns an AST structured as follows
//! ```text
//! Root
//! ├─ Line
//! │ └─ Empty
//! ├─ Line
//! │ └─ Comment
//! ├─ Line
//! │ └─ Directive // Pre- or Post-processor directive
//! ├─ Linel
//! │ └─ Label // Label definition
//! ├─ Line
//! │ └─ Instruction
//! │ ├─ Opcode
//! │ └─ Encoding::Single
//! │ ├─ Width
//! │ └─ PrimaryOperand
//! │ ├─ Identifier // Label, for relative-addressed data/code
//! │ ├─ Register // Direct, indexed, indirect or indirect-post-increment register.
//! │ └─ Number // Index, absolute address or immediate value.
//! ├─ Line
//! │ └─ Instruction
//! │ ├─ Opcode
//! │ └─ Encoding::Double
//! │ ├─ Width
//! │ ├─ PrimaryOperand
//! │ ├─ Identifier // Label, for relative-addressed data/code
//! │ │ ├─ Register // Direct, indexed, indirect or indirect-post-increment register.
//! │ │ └─ Number // Index, absolute address or immediate value.
//! │ └─ SecondaryOperand
//! │ ├─ Identifier // Label, for relative-addressed data/code
//! │ ├─ Register // Direct or indexed register
//! │ └─ Number // Index or absolute address
//! ├─ Line
//! │ └─ Instruction
//! │ ├─ Opcode
//! │ └─ Encoding::Jump
//! │ └─ JumpTarget
//! │ ├─ Identifier // Label
//! │ └─ Number // Even, PC-relative offset in range (-1024..=1022)
//! └─ Line
//! └─ EndOfFile
//! ```
pub mod util {
use std::{
fmt::{Debug, Display},
ops::{Index, Range},
};
/// A <code> [Clone] + [Copy] + [!Iterator](Iterator) <\code> version of a [Range]
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Span<Idx> {
pub start: Idx,
pub end: Idx,
}
impl<Idx> From<Span<Idx>> for Range<Idx> {
fn from(value: Span<Idx>) -> Self {
value.start..value.end
}
}
impl<Idx> From<Range<Idx>> for Span<Idx> {
fn from(value: Range<Idx>) -> Self {
Self { start: value.start, end: value.end }
}
}
impl<T> Index<Span<usize>> for [T] {
type Output = [T];
fn index(&self, index: Span<usize>) -> &Self::Output {
self.index(Range::from(index))
}
}
impl Index<Span<usize>> for str {
type Output = str;
fn index(&self, index: Span<usize>) -> &Self::Output {
self.index(Range::from(index))
}
}
impl<Idx: Debug> Debug for Span<Idx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}..{:?}", self.start, self.end)
}
}
impl<Idx: Display> Display for Span<Idx> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}..{}", self.start, self.end)
}
}
}
pub mod lexer;
pub mod preprocessor;
pub mod parser;
pub mod assembler;