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,
|
||||
// because I already wrote a compiler lol.
|
||||
|
||||
include print "./lib/print.dsa"
|
||||
include print "./lib/io/print.dsa"
|
||||
|
||||
// "print hello world"
|
||||
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:
|
||||
//
|
||||
// include print "<relative path>""
|
||||
//
|
||||
//
|
||||
// usage for print:
|
||||
// push (register containing address of string)
|
||||
// push pcx
|
||||
@@ -68,7 +68,7 @@ print_word:
|
||||
jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the last byte of arg[0] to the screen.
|
||||
// prints the last byte of arg[0] to the screen.
|
||||
print_byte:
|
||||
push bpr
|
||||
mov spr, bpr
|
||||
@@ -80,6 +80,58 @@ print_byte:
|
||||
addi rg1, 1
|
||||
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)
|
||||
reset:
|
||||
@@ -109,7 +161,7 @@ _clear_loop:
|
||||
// return
|
||||
_end:
|
||||
stw rg1, current
|
||||
|
||||
|
||||
mov bpr, spr
|
||||
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
|
||||
db string: "Hello world"
|
||||
db interrupt: "INT: Hello world"
|
||||
|
||||
init:
|
||||
// set up a stack.
|
||||
@@ -9,10 +10,24 @@ init:
|
||||
mov bpr, spr
|
||||
|
||||
start:
|
||||
lwi string, rg1
|
||||
ldw idt, idr
|
||||
|
||||
push rg1
|
||||
call print::print
|
||||
pop rg1
|
||||
lwi handle_hard_fault, rg0
|
||||
stw rg0, idr, 4
|
||||
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user