From f4027cae775e3c9c237675f9df35a744d54f3f2e Mon Sep 17 00:00:00 2001
From: Ben Bridle <bridle.benjamin@gmail.com>
Date: Mon, 28 Oct 2024 19:52:29 +1300
Subject: Rewrite assembler

This is an almost complete rewrite of the entire assembler from the
ground up, with a different parsing strategy and a whole new symbol
resolution mechanism for automatically including library files.

The assembly syntax has also been slightly modified, with padding
tokens now being prefixed with '#' instead of '$', and a block-style
anonymous-label syntax which uses the '{' and '}' characters.
---
 src/locators/bytecode.rs | 39 +++++++++++++++++++++++++++
 src/locators/source.rs   | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
 create mode 100644 src/locators/bytecode.rs
 create mode 100644 src/locators/source.rs

(limited to 'src/locators')

diff --git a/src/locators/bytecode.rs b/src/locators/bytecode.rs
new file mode 100644
index 0000000..500e9f0
--- /dev/null
+++ b/src/locators/bytecode.rs
@@ -0,0 +1,39 @@
+pub struct BytecodeSpan {
+    /// The location of this span in the assembled bytecode.
+    pub location: BytecodeLocation,
+    /// The bytes which this span represents.
+    pub bytes: Vec<u8>,
+}
+
+
+impl Default for BytecodeSpan {
+    fn default() -> Self {
+        Self {
+            location: BytecodeLocation {
+                address: 0,
+                length: 0,
+            },
+            bytes: Vec::new(),
+        }
+    }
+}
+
+
+#[derive(Clone, Copy)]
+pub struct BytecodeLocation {
+    // Address of the first byte.
+    pub address: usize,
+    // Length as a number of bytes.
+    pub length: usize,
+}
+
+
+impl std::fmt::Display for BytecodeLocation {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        write!(f, "0x{:>04x}", self.address)?;
+        if self.length > 0 {
+            write!(f, "-0x{:>04x}", self.address + self.length)?;
+        }
+        Ok(())
+    }
+}
diff --git a/src/locators/source.rs b/src/locators/source.rs
new file mode 100644
index 0000000..2f10bd9
--- /dev/null
+++ b/src/locators/source.rs
@@ -0,0 +1,69 @@
+use std::path::PathBuf;
+
+
+#[derive(Clone)]
+pub struct SourceSpan {
+    /// The source characters which this span represents.
+    pub string: String,
+    /// The location of this span in the merged source file.
+    pub in_merged: SourceLocation,
+    /// The location of this span in the original source file.
+    pub in_source: Option<SourceLocation>,
+}
+
+
+#[derive(Clone)]
+pub struct SourceLocation {
+    /// File path the source was loaded from.
+    pub path: Option<PathBuf>,
+    /// Position of the first character of the string.
+    pub start: Position,
+    /// Position of the final character of the string.
+    pub end: Position,
+}
+
+impl std::fmt::Display for SourceLocation {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        let y = self.start.line + 1;
+        let x = self.start.column + 1;
+        match &self.path {
+            Some(path) => write!(f, "{}:{y}:{x}", path.as_os_str().to_string_lossy()),
+            None => write!(f, "<unknown>:{y}:{x}"),
+        }
+    }
+}
+
+
+#[derive(Clone, Copy)]
+pub struct Position {
+    /// The number of lines that precede this line in the file.
+    pub line: usize,
+    /// The number of characters that precede this character in the line.
+    pub column: usize,
+}
+
+impl Position {
+    pub fn to_next_char(&mut self) {
+        self.column += 1;
+    }
+
+    pub fn to_next_line(&mut self) {
+        self.line += 1;
+        self.column = 0;
+    }
+
+    pub fn advance(&mut self, c: char) {
+        match c {
+            '\n' => self.to_next_line(),
+            _ => self.to_next_char(),
+        }
+    }
+}
+
+impl std::fmt::Display for Position {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        let y = self.line + 1;
+        let x = self.column + 1;
+        write!(f, "{y}:{x}")
+    }
+}
-- 
cgit v1.2.3-70-g09d2