worked on print.dsa and maths/core.dsa
This commit is contained in:
@@ -1,279 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
```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"));
|
|
||||||
}
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// a simple brainf##k interpreter,
|
// a simple brainf##k interpreter,
|
||||||
// because I already wrote a compiler lol.
|
// because I already wrote a compiler lol.
|
||||||
|
|
||||||
include print "./lib/print.dsa"
|
include print "./lib/io/print.dsa"
|
||||||
|
|
||||||
// "print hello world"
|
// "print hello world"
|
||||||
db program: "++++++++++++++++++++++++++++++++++++++++++++
|
db program: "++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
include print "../io/print.dsa"
|
||||||
|
|
||||||
|
dw idt: 0xFFFF0000
|
||||||
|
|
||||||
|
setup_idt:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
// load the IDT into the IDR
|
||||||
|
ldw idt, idr
|
||||||
|
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
irt
|
||||||
|
|
||||||
|
setup_hard_fault_handler:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
lwi handle_hard_fault, rg0
|
||||||
|
stw rg0, idr, 4
|
||||||
|
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
irt
|
||||||
|
|
||||||
|
dw hard_fault_err: "FATAL: Illegal Instruction or Memory Access!"
|
||||||
|
handle_hard_fault:
|
||||||
|
call print::reset
|
||||||
|
lwi hard_fault_err, rg0
|
||||||
|
push rg0
|
||||||
|
call print::print
|
||||||
|
pop zero
|
||||||
|
hlt
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
// usage:
|
// usage:
|
||||||
//
|
//
|
||||||
// include print "<relative path>""
|
// include print "<relative path>""
|
||||||
//
|
//
|
||||||
// usage for print:
|
// usage for print:
|
||||||
// push (register containing address of string)
|
// push (register containing address of string)
|
||||||
// push pcx
|
// push pcx
|
||||||
@@ -68,7 +68,7 @@ print_word:
|
|||||||
jmp _end
|
jmp _end
|
||||||
|
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
// prints the last byte of arg[0] to the screen.
|
// prints the last byte of arg[0] to the screen.
|
||||||
print_byte:
|
print_byte:
|
||||||
push bpr
|
push bpr
|
||||||
mov spr, bpr
|
mov spr, bpr
|
||||||
@@ -80,6 +80,58 @@ print_byte:
|
|||||||
addi rg1, 1
|
addi rg1, 1
|
||||||
jmp _end
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the value of arg[0] to the screen in hex.
|
||||||
|
print_hex_byte:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
// put arg byte in rg0
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
ldw current, rg1
|
||||||
|
|
||||||
|
// mask to get lower nibble
|
||||||
|
lli 0xF, rg2
|
||||||
|
// save rg0 state
|
||||||
|
push rg0
|
||||||
|
|
||||||
|
shr rg0, 4
|
||||||
|
and rg0, rg2, rg0
|
||||||
|
call _print_hex_nibble
|
||||||
|
pop rg0
|
||||||
|
|
||||||
|
and rg0, rg2, rg0
|
||||||
|
call _print_hex_nibble
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
_print_hex_nibble:
|
||||||
|
lli 10, rg3
|
||||||
|
cmp rg0, rg3
|
||||||
|
jlt _print_hex_nibble_number
|
||||||
|
addi rg0, 0x37, rg0
|
||||||
|
stb rg0, rg1
|
||||||
|
addi rg1, 1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
_print_hex_nibble_number:
|
||||||
|
addi rg0, 0x30, rg0
|
||||||
|
stb rg0, rg1
|
||||||
|
addi rg1, 1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the value of arg[0] to the screen in hex.
|
||||||
|
print_hex_word:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
ldw current, rg1
|
||||||
|
|
||||||
|
stw rg0, rg1
|
||||||
|
addi rg1, 4
|
||||||
|
jmp _end
|
||||||
|
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
// resets the cursor position on the screen to 0x20000. (0,0)
|
// resets the cursor position on the screen to 0x20000. (0,0)
|
||||||
reset:
|
reset:
|
||||||
@@ -109,7 +161,7 @@ _clear_loop:
|
|||||||
// return
|
// return
|
||||||
_end:
|
_end:
|
||||||
stw rg1, current
|
stw rg1, current
|
||||||
|
|
||||||
mov bpr, spr
|
mov bpr, spr
|
||||||
pop bpr
|
pop bpr
|
||||||
return
|
return
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// multiply.dsa
|
||||||
|
// usage:
|
||||||
|
//
|
||||||
|
// include multiply "<relative path>"
|
||||||
|
//
|
||||||
|
// usage for multiply:
|
||||||
|
// push (arg1)
|
||||||
|
// push (arg0)
|
||||||
|
// call multiply::multiply
|
||||||
|
// pop (arg0)
|
||||||
|
// pop (arg1)
|
||||||
|
|
||||||
|
multiply:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8 // load op 2
|
||||||
|
ldw bpr, rg1, 12 // load op 1
|
||||||
|
|
||||||
|
_multiply_loop:
|
||||||
|
add rg2, rg0, rg2
|
||||||
|
dec rg1
|
||||||
|
|
||||||
|
cmp rg1, zero
|
||||||
|
jgt _multiply_loop
|
||||||
|
|
||||||
|
_multiply_end:
|
||||||
|
stw rg2, bpr, 8
|
||||||
|
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
return
|
||||||
|
|
||||||
|
divmod:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg1, 8 // load op 2
|
||||||
|
ldw bpr, rg0, 12 // load op 1
|
||||||
|
|
||||||
|
lli 0, rg3
|
||||||
|
|
||||||
|
_divmod_loop:
|
||||||
|
cmp rg0, rg1
|
||||||
|
jlt _divmod_end
|
||||||
|
|
||||||
|
sub rg0, rg1, rg0
|
||||||
|
inc rg3
|
||||||
|
|
||||||
|
jmp _divmod_loop
|
||||||
|
|
||||||
|
_divmod_end:
|
||||||
|
// store div in first arg
|
||||||
|
// store mod in second arg
|
||||||
|
stw rg3, bpr, 8
|
||||||
|
stw rg0, bpr, 12
|
||||||
|
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
return
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// multiply.dsa
|
|
||||||
// usage:
|
|
||||||
//
|
|
||||||
// include multiply "<relative path>"
|
|
||||||
//
|
|
||||||
// usage for multiply:
|
|
||||||
// push (arg1)
|
|
||||||
// push (arg0)
|
|
||||||
// call multiply::multiply
|
|
||||||
// pop (arg0)
|
|
||||||
// pop (arg1)
|
|
||||||
|
|
||||||
multiply:
|
|
||||||
push bpr
|
|
||||||
mov spr, bpr
|
|
||||||
|
|
||||||
ldw bpr, rg0, 8 // load op 1
|
|
||||||
ldw bpr, rg1, 12 // load op 2
|
|
||||||
|
|
||||||
start:
|
|
||||||
add acc, rg0, acc
|
|
||||||
dec rg1
|
|
||||||
|
|
||||||
cmp rg1, zero
|
|
||||||
jgt start
|
|
||||||
|
|
||||||
end:
|
|
||||||
mov bpr, spr
|
|
||||||
pop bpr
|
|
||||||
return
|
|
||||||
+21
-6
@@ -1,7 +1,8 @@
|
|||||||
include print "./lib/print.dsa"
|
include print "./lib/io/print.dsa"
|
||||||
|
|
||||||
|
dw idt: 0xFFFF0000
|
||||||
dw stack: 0x10000
|
dw stack: 0x10000
|
||||||
db string: "Hello world"
|
db interrupt: "INT: Hello world"
|
||||||
|
|
||||||
init:
|
init:
|
||||||
// set up a stack.
|
// set up a stack.
|
||||||
@@ -9,10 +10,24 @@ init:
|
|||||||
mov bpr, spr
|
mov bpr, spr
|
||||||
|
|
||||||
start:
|
start:
|
||||||
lwi string, rg1
|
ldw idt, idr
|
||||||
|
|
||||||
push rg1
|
lwi handle_hard_fault, rg0
|
||||||
call print::print
|
stw rg0, idr, 4
|
||||||
pop rg1
|
|
||||||
|
|
||||||
|
|
||||||
|
lli 0x20, rg0
|
||||||
|
push rg0
|
||||||
|
call print::print_hex_byte
|
||||||
|
pop zero
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
dw hard_fault_err: "FATAL: Illegal Instruction or Memory Access!"
|
||||||
|
handle_hard_fault:
|
||||||
|
call print::reset
|
||||||
|
lwi hard_fault_err, rg0
|
||||||
|
push rg0
|
||||||
|
call print::print
|
||||||
|
pop zero
|
||||||
hlt
|
hlt
|
||||||
|
|||||||
Reference in New Issue
Block a user