updated print with new functions
This commit is contained in:
@@ -0,0 +1,279 @@
|
|||||||
|
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/source.rs
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct SourcePosition {
|
||||||
|
pub line: u32,
|
||||||
|
pub column: u32,
|
||||||
|
pub offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct SourceSpan {
|
||||||
|
pub start: SourcePosition,
|
||||||
|
pub end: SourcePosition,
|
||||||
|
pub file_id: u64, // Hash of the file path
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceSpan {
|
||||||
|
pub fn new(start: SourcePosition, end: SourcePosition, file_id: u64) -> Self {
|
||||||
|
Self { start, end, file_id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn single_char(pos: SourcePosition, file_id: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
start: pos,
|
||||||
|
end: pos,
|
||||||
|
file_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2. Enhanced Token with Source Information
|
||||||
|
Update the Token type to include source positions:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/model.rs
|
||||||
|
pub struct Token {
|
||||||
|
pub kind: TokenKind,
|
||||||
|
pub span: SourceSpan,
|
||||||
|
pub raw: String, // Original source text
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TokenKind {
|
||||||
|
// ... existing variants ...
|
||||||
|
}
|
||||||
|
3. Enhanced CodeModule Structure
|
||||||
|
Enhance the
|
||||||
|
CodeModule
|
||||||
|
struct to track source information:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/mod.rs
|
||||||
|
pub struct CodeModule {
|
||||||
|
pub path: PathBuf,
|
||||||
|
pub hash: u64,
|
||||||
|
pub source: String,
|
||||||
|
pub lines: Vec<usize>, // Line start offsets for quick lookup
|
||||||
|
pub tokens: Vec<Token>,
|
||||||
|
pub nodes: Vec<Node>,
|
||||||
|
pub dependencies: Vec<CodeModule>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CodeModule {
|
||||||
|
pub fn new(path: PathBuf, source: String) -> Self {
|
||||||
|
let hash = quick_hash(&path);
|
||||||
|
let lines = source.lines()
|
||||||
|
.scan(0, |offset, line| {
|
||||||
|
let start = *offset;
|
||||||
|
*offset += line.len() + 1; // +1 for newline
|
||||||
|
Some(start)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
path,
|
||||||
|
hash,
|
||||||
|
source,
|
||||||
|
lines,
|
||||||
|
tokens: Vec::new(),
|
||||||
|
nodes: Vec::new(),
|
||||||
|
dependencies: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position_from_offset(&self, offset: usize) -> (u32, u32) {
|
||||||
|
match self.lines.binary_search(&offset) {
|
||||||
|
Ok(line) => (line as u32 + 1, 1),
|
||||||
|
Err(0) => (1, offset as u32 + 1),
|
||||||
|
Err(line) => {
|
||||||
|
let line_start = self.lines[line - 1];
|
||||||
|
(line as u32, (offset - line_start + 1) as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4. Enhanced Lexer with Source Positions
|
||||||
|
Update the lexer to track source positions:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/lexer.rs
|
||||||
|
pub fn lex(module: &mut CodeModule) -> Result<(), AssembleError> {
|
||||||
|
let source = &module.source;
|
||||||
|
let mut tokens = Vec::new();
|
||||||
|
let mut pos = 0;
|
||||||
|
let mut line_start = 0;
|
||||||
|
let mut line = 1;
|
||||||
|
|
||||||
|
while pos < source.len() {
|
||||||
|
let c = source[pos..].chars().next().unwrap();
|
||||||
|
|
||||||
|
if c == '\n' {
|
||||||
|
line += 1;
|
||||||
|
line_start = pos + 1;
|
||||||
|
pos += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.is_whitespace() {
|
||||||
|
pos += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let token_start = pos;
|
||||||
|
// ... existing token parsing logic ...
|
||||||
|
|
||||||
|
// When creating a token:
|
||||||
|
let start_pos = SourcePosition {
|
||||||
|
line,
|
||||||
|
column: (token_start - line_start + 1) as u32,
|
||||||
|
offset: token_start,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update pos based on token length
|
||||||
|
let token_length = /* calculate token length */;
|
||||||
|
pos += token_length;
|
||||||
|
|
||||||
|
let end_pos = SourcePosition {
|
||||||
|
line,
|
||||||
|
column: (pos - line_start + 1) as u32,
|
||||||
|
offset: pos,
|
||||||
|
};
|
||||||
|
|
||||||
|
tokens.push(Token {
|
||||||
|
kind: token_kind,
|
||||||
|
span: SourceSpan::new(start_pos, end_pos, module.hash),
|
||||||
|
raw: source[token_start..pos].to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.tokens = tokens;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
5. Enhanced Error Reporting
|
||||||
|
Create a structured error type with source context:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/error.rs
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AssemblerError {
|
||||||
|
pub kind: ErrorKind,
|
||||||
|
pub span: SourceSpan,
|
||||||
|
pub message: String,
|
||||||
|
pub context: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AssemblerError {
|
||||||
|
pub fn new(kind: ErrorKind, span: SourceSpan, message: impl Into<String>) -> Self {
|
||||||
|
Self {
|
||||||
|
kind,
|
||||||
|
span,
|
||||||
|
message: message.into(),
|
||||||
|
context: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_context(mut self, context: impl Into<String>) -> Self {
|
||||||
|
self.context.push(context.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format(&self, module: &CodeModule) -> String {
|
||||||
|
let (line, col) = module.position_from_offset(self.span.start.offset);
|
||||||
|
let line_content = module.source.lines().nth(line as usize - 1).unwrap_or("");
|
||||||
|
|
||||||
|
let mut output = format!(
|
||||||
|
"{}:{}:{}: {}\n",
|
||||||
|
module.path.display(),
|
||||||
|
line,
|
||||||
|
col,
|
||||||
|
self.message
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add source line with caret
|
||||||
|
output.push_str(&format!("{}\n", line_content));
|
||||||
|
output.push_str(&" ".repeat(col as usize - 1));
|
||||||
|
output.push_str("^\n");
|
||||||
|
|
||||||
|
// Add context if any
|
||||||
|
for ctx in &self.context {
|
||||||
|
output.push_str(&format!(" = note: {}\n", ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
6. Integration with Compilation Pipeline
|
||||||
|
Update the compilation pipeline to use the enhanced types:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/assembler/mod.rs
|
||||||
|
pub fn assemble(src: &Path) -> Result<Vec<Instruction>, AssemblerError> {
|
||||||
|
let source = std::fs::read_to_string(src)
|
||||||
|
.map_err(|e| AssemblerError::io_error(src, e))?;
|
||||||
|
|
||||||
|
let mut module = CodeModule::new(src.to_path_buf(), source);
|
||||||
|
|
||||||
|
// Lexing
|
||||||
|
lexer::lex(&mut module)?;
|
||||||
|
|
||||||
|
// Parsing
|
||||||
|
parser::parse(&mut module)?;
|
||||||
|
|
||||||
|
// Resolution
|
||||||
|
resolver::resolve(&mut module)?;
|
||||||
|
|
||||||
|
// Code generation
|
||||||
|
codegen::generate(&module)
|
||||||
|
}
|
||||||
|
7. Logging Integration
|
||||||
|
Enhance the logging system to include source context:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/util/logging.rs
|
||||||
|
pub trait Loggable {
|
||||||
|
fn log(&self, level: LogLevel, message: impl std::fmt::Display);
|
||||||
|
fn log_with_span(&self, level: LogLevel, span: &SourceSpan, message: impl std::fmt::Display);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Loggable for CodeModule {
|
||||||
|
fn log_with_span(&self, level: LogLevel, span: &SourceSpan, message: impl std::fmt::Display) {
|
||||||
|
if span.file_id != self.hash {
|
||||||
|
if let Some(dep) = self.find_dependency(span.file_id) {
|
||||||
|
return dep.log_with_span(level, span, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (line, col) = self.position_from_offset(span.start.offset);
|
||||||
|
let line_content = self.source.lines().nth(line as usize - 1).unwrap_or("");
|
||||||
|
|
||||||
|
log::log!(
|
||||||
|
level,
|
||||||
|
"{}:{}:{}: {}\n {}\n {}{}",
|
||||||
|
self.path.display(),
|
||||||
|
line,
|
||||||
|
col,
|
||||||
|
message,
|
||||||
|
line_content,
|
||||||
|
" ".repeat(col as usize - 1),
|
||||||
|
"^"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
8. Usage Example
|
||||||
|
Here's how you'd use this in practice:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// In your parser or code that needs to report errors
|
||||||
|
fn parse_token(&mut self, module: &CodeModule) -> Result<Token, AssemblerError> {
|
||||||
|
// ...
|
||||||
|
if !is_valid_token(&token) {
|
||||||
|
return Err(AssemblerError::new(
|
||||||
|
ErrorKind::SyntaxError,
|
||||||
|
token.span,
|
||||||
|
"Invalid token"
|
||||||
|
).with_context("Expected a valid instruction or directive"));
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
+63
-15
@@ -13,11 +13,27 @@
|
|||||||
// usage for reset:
|
// usage for reset:
|
||||||
// push pcx
|
// push pcx
|
||||||
// jmp print::reset
|
// jmp print::reset
|
||||||
|
//
|
||||||
|
// usage for clear:
|
||||||
|
// push pcx
|
||||||
|
// jmp print::clear
|
||||||
|
//
|
||||||
|
// usage for print_byte:
|
||||||
|
// push (register containing byte)
|
||||||
|
// push pcx
|
||||||
|
// jmp print::print_byte
|
||||||
|
//
|
||||||
|
// usage for print_word:
|
||||||
|
// push (register containing word)
|
||||||
|
// push pcx
|
||||||
|
// jmp print::print_word
|
||||||
|
//
|
||||||
|
|
||||||
dw display: 0x20000
|
dw display: 0x20000
|
||||||
dw current: 0x20000
|
dw current: 0x20000
|
||||||
|
|
||||||
// prints the given text to the screen.
|
// ------------------------------------------
|
||||||
|
// prints the string at addr(arg[0]) to the screen.
|
||||||
print:
|
print:
|
||||||
push bpr
|
push bpr
|
||||||
mov spr, bpr
|
mov spr, bpr
|
||||||
@@ -25,7 +41,7 @@ print:
|
|||||||
ldw bpr, rg0, 8
|
ldw bpr, rg0, 8
|
||||||
ldw current, rg1
|
ldw current, rg1
|
||||||
|
|
||||||
print_loop:
|
_print_loop:
|
||||||
ldb rg0, acc
|
ldb rg0, acc
|
||||||
stb acc, rg1
|
stb acc, rg1
|
||||||
|
|
||||||
@@ -33,24 +49,47 @@ print_loop:
|
|||||||
addi rg1, 1
|
addi rg1, 1
|
||||||
|
|
||||||
cmp acc, zero
|
cmp acc, zero
|
||||||
jne print_loop
|
jne _print_loop
|
||||||
jmp end
|
jmp _end
|
||||||
|
|
||||||
// return
|
// ------------------------------------------
|
||||||
end:
|
// prints the value of arg[0] to the screen.
|
||||||
stw rg1, current
|
print_word:
|
||||||
|
// initialise
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
mov bpr, spr
|
// load byte into acc
|
||||||
pop bpr
|
ldw bpr, rg0, 8
|
||||||
return
|
ldw current, rg1
|
||||||
|
|
||||||
// resets the cursor position on the screen
|
stw rg0, rg1
|
||||||
|
addi rg1, 4
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the last byte of arg[0] to the screen.
|
||||||
|
print_byte:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
ldw current, rg1
|
||||||
|
|
||||||
|
stb rg0, rg1
|
||||||
|
addi rg1, 1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// resets the cursor position on the screen to 0x20000. (0,0)
|
||||||
reset:
|
reset:
|
||||||
push bpr
|
push bpr
|
||||||
mov spr, bpr
|
mov spr, bpr
|
||||||
ldw display, rg1
|
ldw display, rg1
|
||||||
jmp end
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// clears the screen
|
||||||
clear:
|
clear:
|
||||||
push bpr
|
push bpr
|
||||||
mov spr, bpr
|
mov spr, bpr
|
||||||
@@ -58,10 +97,19 @@ clear:
|
|||||||
lli 500 rg0
|
lli 500 rg0
|
||||||
ldw display, rg1
|
ldw display, rg1
|
||||||
|
|
||||||
clear_loop:
|
_clear_loop:
|
||||||
dec rg0
|
dec rg0
|
||||||
stw zero, rg1
|
stw zero, rg1
|
||||||
addi rg1, 4
|
addi rg1, 4
|
||||||
cmp rg0, zero
|
cmp rg0, zero
|
||||||
jgt clear_loop
|
jgt _clear_loop
|
||||||
jmp end
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// return
|
||||||
|
_end:
|
||||||
|
stw rg1, current
|
||||||
|
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
return
|
||||||
@@ -9,10 +9,12 @@ init:
|
|||||||
mov bpr, spr
|
mov bpr, spr
|
||||||
|
|
||||||
start:
|
start:
|
||||||
lwi string, rg1
|
// string, rg1
|
||||||
|
lli 87, rg1
|
||||||
|
|
||||||
push rg1
|
push rg1
|
||||||
call print::print
|
|
||||||
|
call print::print_byte
|
||||||
pop rg1
|
pop rg1
|
||||||
|
|
||||||
hlt
|
hlt
|
||||||
Binary file not shown.
Reference in New Issue
Block a user