added some documentation and started on compiler for custom language (not C) based on previous prototypes. pretty broken state rn.
This commit is contained in:
+21
-5
@@ -4,12 +4,15 @@ use std::str::Chars;
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
// Keywords
|
||||
Fn,
|
||||
Let,
|
||||
If,
|
||||
Else,
|
||||
Loop,
|
||||
Break,
|
||||
Return,
|
||||
Continue,
|
||||
Include,
|
||||
|
||||
// Identifiers and literals
|
||||
Identifier(String),
|
||||
@@ -24,7 +27,7 @@ pub enum Token {
|
||||
Semicolon, // ;
|
||||
Colon, // :
|
||||
Comma, // ,
|
||||
Pipe, // |
|
||||
// Pipe, // |
|
||||
|
||||
// Operators
|
||||
Plus, // +
|
||||
@@ -39,6 +42,7 @@ pub enum Token {
|
||||
LessEqual, // <=
|
||||
Greater, // >
|
||||
GreaterEqual, // >=
|
||||
RightArrow, // ->
|
||||
|
||||
// Special
|
||||
Eof,
|
||||
@@ -47,7 +51,10 @@ pub enum Token {
|
||||
impl Token {
|
||||
pub fn tt(&self) -> &str {
|
||||
match self {
|
||||
Token::Include => "Include",
|
||||
Token::Fn => "Fn",
|
||||
Token::If => "If",
|
||||
Token::Let => "Let",
|
||||
Token::Else => "Else",
|
||||
Token::Loop => "Loop",
|
||||
Token::Break => "Break",
|
||||
@@ -63,7 +70,8 @@ impl Token {
|
||||
Token::Semicolon => "Semicolon",
|
||||
Token::Colon => "Colon",
|
||||
Token::Comma => "Comma",
|
||||
Token::Pipe => "Pipe",
|
||||
Token::RightArrow => "RightArrow",
|
||||
// Token::Pipe => "Pipe",
|
||||
Token::Plus => "Plus",
|
||||
Token::Minus => "Minus",
|
||||
Token::Star => "Star",
|
||||
@@ -168,11 +176,17 @@ impl<'a> Lexer<'a> {
|
||||
Some(';') => Token::Semicolon,
|
||||
Some(':') => Token::Colon,
|
||||
Some(',') => Token::Comma,
|
||||
Some('|') => Token::Pipe,
|
||||
// Some('|') => Token::Pipe,
|
||||
Some('+') => Token::Plus,
|
||||
Some('-') => Token::Minus,
|
||||
Some('*') => Token::Star,
|
||||
Some('/') => Token::Slash,
|
||||
Some('-') => {
|
||||
if self.match_next('>') {
|
||||
Token::RightArrow
|
||||
} else {
|
||||
Token::Minus
|
||||
}
|
||||
}
|
||||
Some('!') => {
|
||||
if self.match_next('=') {
|
||||
Token::BangEqual
|
||||
@@ -218,12 +232,14 @@ impl<'a> Lexer<'a> {
|
||||
let mut ident = c.to_string();
|
||||
ident.push_str(&self.read_identifier());
|
||||
match ident.as_str() {
|
||||
"fn" => Token::Fn,
|
||||
"if" => Token::If,
|
||||
"else" => Token::Else,
|
||||
"loop" => Token::Loop,
|
||||
"break" => Token::Break,
|
||||
"return" => Token::Return,
|
||||
"continue" => Token::Continue,
|
||||
"include" => Token::Include,
|
||||
_ => Token::Identifier(ident),
|
||||
}
|
||||
} else if c.is_ascii_digit() {
|
||||
@@ -331,7 +347,7 @@ mod tests {
|
||||
assert_eq!(lexer.next_token(), Token::Colon);
|
||||
assert_eq!(lexer.next_token(), Token::Identifier("Func".to_string()));
|
||||
assert_eq!(lexer.next_token(), Token::Assign);
|
||||
assert_eq!(lexer.next_token(), Token::Pipe);
|
||||
// assert_eq!(lexer.next_token(), Token::Pipe);
|
||||
assert_eq!(lexer.next_token(), Token::Identifier("x".to_string()));
|
||||
assert_eq!(lexer.next_token(), Token::Colon);
|
||||
assert_eq!(lexer.next_token(), Token::Identifier("U32".to_string()));
|
||||
|
||||
+12
-4
@@ -1,7 +1,12 @@
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::{fs, path::Path};
|
||||
|
||||
pub mod lexer;
|
||||
pub mod parser;
|
||||
pub mod parserprototype;
|
||||
use parserprototype::Parser;
|
||||
|
||||
use crate::parserprototype::ParseResult;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
@@ -13,13 +18,16 @@ fn main() {
|
||||
let tokens = lexer.collect::<Vec<_>>();
|
||||
println!("{tokens:?}");
|
||||
|
||||
let mut parser = parser::Parser::new(tokens);
|
||||
let mut parser = Parser::new(tokens);
|
||||
let ast = match parser.parse() {
|
||||
Ok(ast) => ast,
|
||||
Err(e) => {
|
||||
ParseResult::Accept(ast) => ast,
|
||||
ParseResult::Reject(e) => {
|
||||
eprintln!("Error: {e:?}");
|
||||
return;
|
||||
}
|
||||
ParseResult::Deny => {
|
||||
panic!("Parser denied parsing")
|
||||
}
|
||||
};
|
||||
println!("{ast:?}");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,435 @@
|
||||
use crate::lexer::Token;
|
||||
use crate::{expect_tt, expect_value};
|
||||
use core::fmt;
|
||||
use std::ops::{ControlFlow, FromResidual, Try};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ParseResult<T, E> {
|
||||
Accept(T),
|
||||
Deny,
|
||||
Reject(E),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CompilerError {
|
||||
UnexpectedToken(Token),
|
||||
UnexpectedEndOfInput,
|
||||
UnexpectedCharacter(char),
|
||||
InvalidSyntax(String),
|
||||
Generic(String),
|
||||
}
|
||||
|
||||
pub struct Parser {
|
||||
tokens: Vec<Token>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
pub fn new(tokens: Vec<Token>) -> Self {
|
||||
Self { tokens, idx: 0 }
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> ParseResult<Program, CompilerError> {
|
||||
let mut declarations = Vec::new();
|
||||
|
||||
while let ParseResult::Accept(_) = self.peek_next() {
|
||||
declarations.push(self.parse_declaration()?);
|
||||
}
|
||||
|
||||
ParseResult::Accept(Program {
|
||||
imports: vec![],
|
||||
declarations,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_declaration(&mut self) -> ParseResult<Declaration, CompilerError> {
|
||||
if expect_tt!(self.peek_next()?, Fn).accepted() {
|
||||
let x = self.parse_func();
|
||||
println!("function {:?}", x);
|
||||
return x;
|
||||
}
|
||||
|
||||
println!("{:?}", self.peek_next()?);
|
||||
|
||||
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
||||
}
|
||||
|
||||
fn parse_func(&mut self) -> ParseResult<Declaration, CompilerError> {
|
||||
// expect function keyword
|
||||
//
|
||||
println!("pre name! {:?}", self.peek_next()?);
|
||||
|
||||
let _ = expect_tt!(self.next()?, Fn);
|
||||
|
||||
println!("this is the name! {:?}", self.peek_next()?);
|
||||
|
||||
// expect function name
|
||||
let name = match self.next()? {
|
||||
Token::Identifier(name) => name,
|
||||
id => return ParseResult::Reject(CompilerError::UnexpectedToken(id)),
|
||||
};
|
||||
|
||||
// expect left paren
|
||||
let _ = expect_tt!(self.next()?, LParen);
|
||||
|
||||
let mut params = Vec::new();
|
||||
while expect_tt!(self.peek_next()?, Identifier).accepted() {
|
||||
let arg = self.parse_var_decl()?;
|
||||
params.push(arg);
|
||||
}
|
||||
|
||||
// expect right paren
|
||||
let _ = expect_tt!(self.next()?, RParen);
|
||||
|
||||
// see if we can parse the return type!
|
||||
let mut return_type = TypeId::Void;
|
||||
|
||||
if expect_tt!(self.peek_next()?, RightArrow).accepted() {
|
||||
let _ = self.next();
|
||||
return_type = self.parse_type()?;
|
||||
}
|
||||
|
||||
// expect left brace
|
||||
let _ = expect_tt!(self.next()?, LBrace);
|
||||
|
||||
let mut body = Vec::new();
|
||||
|
||||
// expect right brace
|
||||
let _ = expect_tt!(self.next()?, RBrace);
|
||||
|
||||
ParseResult::Accept(Declaration::Function {
|
||||
name,
|
||||
params,
|
||||
return_type,
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_var_decl(&mut self) -> ParseResult<Variable, CompilerError> {
|
||||
let name = match self.next()? {
|
||||
Token::Identifier(name) => name,
|
||||
id => return ParseResult::Reject(CompilerError::UnexpectedToken(id)),
|
||||
};
|
||||
|
||||
let _ = expect_tt!(self.next()?, Colon);
|
||||
|
||||
let type_ = self.parse_type()?;
|
||||
|
||||
ParseResult::Accept(Variable {
|
||||
name,
|
||||
param_type: Some(type_),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_type(&mut self) -> ParseResult<TypeId, CompilerError> {
|
||||
// get the type name incl namespace
|
||||
let typename = self.parse_identifier()?;
|
||||
|
||||
match typename.name.as_str() {
|
||||
"u32" => ParseResult::Accept(TypeId::U32),
|
||||
"u16" => ParseResult::Accept(TypeId::U16),
|
||||
"u8" => ParseResult::Accept(TypeId::U8),
|
||||
"i32" => ParseResult::Accept(TypeId::I32),
|
||||
"i16" => ParseResult::Accept(TypeId::I16),
|
||||
"i8" => ParseResult::Accept(TypeId::I8),
|
||||
"void" => ParseResult::Accept(TypeId::Void),
|
||||
"char" => ParseResult::Accept(TypeId::Char),
|
||||
_ => todo!("Implement parsing for other types!!"),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_identifier(&mut self) -> ParseResult<Name, CompilerError> {
|
||||
let primary = match self.next()? {
|
||||
Token::Identifier(namespace) => namespace,
|
||||
id => return ParseResult::Reject(CompilerError::UnexpectedToken(id)),
|
||||
};
|
||||
|
||||
if expect_tt!(self.peek_next()?, Colon).accepted() {
|
||||
let _ = expect_tt!(self.next()?, Colon);
|
||||
let _ = expect_tt!(self.next()?, Colon);
|
||||
|
||||
let secondary = match self.next()? {
|
||||
Token::Identifier(name) => name,
|
||||
id => return ParseResult::Reject(CompilerError::UnexpectedToken(id)),
|
||||
};
|
||||
|
||||
ParseResult::Accept(Name {
|
||||
namespace: Some(primary),
|
||||
name: secondary,
|
||||
})
|
||||
} else {
|
||||
ParseResult::Accept(Name {
|
||||
namespace: None,
|
||||
name: primary,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> ParseResult<Token, CompilerError> {
|
||||
if self.idx >= self.tokens.len() {
|
||||
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
||||
} else {
|
||||
let token = self.tokens[self.idx].clone();
|
||||
println!("NEXT {:?}", token);
|
||||
self.idx += 1;
|
||||
ParseResult::Accept(token)
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_next(&self) -> ParseResult<Token, CompilerError> {
|
||||
if self.idx >= self.tokens.len() {
|
||||
ParseResult::Reject(CompilerError::UnexpectedEndOfInput)
|
||||
} else {
|
||||
ParseResult::Accept(self.tokens[self.idx].clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Program {
|
||||
pub imports: Vec<Dependency>,
|
||||
pub declarations: Vec<Declaration>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Declaration {
|
||||
Function {
|
||||
name: String,
|
||||
return_type: TypeId,
|
||||
params: Vec<Variable>,
|
||||
body: Block,
|
||||
},
|
||||
Variable {
|
||||
name: String,
|
||||
init: Option<ConstExpr>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Dependency {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Variable {
|
||||
pub name: String,
|
||||
pub param_type: Option<TypeId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Name {
|
||||
pub name: String,
|
||||
pub namespace: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeId {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
Char,
|
||||
Void,
|
||||
Ptr(Box<TypeId>),
|
||||
Ref(Box<TypeId>),
|
||||
Array(Box<TypeId>, usize),
|
||||
Struct {
|
||||
name: Name,
|
||||
fields: Vec<(String, TypeId)>,
|
||||
},
|
||||
}
|
||||
|
||||
pub type Block = Vec<Statement>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Statement {
|
||||
Block(Block),
|
||||
Assign {
|
||||
var: Variable,
|
||||
value: Option<Box<Expression>>,
|
||||
},
|
||||
Expression {
|
||||
expr: Expression,
|
||||
},
|
||||
If {
|
||||
condition: Expression,
|
||||
then_stmt: Block,
|
||||
else_stmt: Block,
|
||||
},
|
||||
While {
|
||||
condition: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
Loop(Block),
|
||||
Break,
|
||||
Continue,
|
||||
Return(Option<Expression>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConstExpr {
|
||||
Number(i32),
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConstExpr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ConstExpr::Number(n) => write!(f, "{}", n),
|
||||
ConstExpr::String(s) => write!(f, "\"{}\"", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expression {
|
||||
Empty,
|
||||
Binary {
|
||||
op: BinaryOperator,
|
||||
left: Box<Expression>,
|
||||
right: Box<Expression>,
|
||||
},
|
||||
Unary {
|
||||
op: UnaryOperator,
|
||||
operand: Box<Expression>,
|
||||
},
|
||||
Variable {
|
||||
name: Name,
|
||||
expr_type: Option<TypeId>,
|
||||
},
|
||||
Number {
|
||||
value: i32,
|
||||
},
|
||||
Call {
|
||||
name: Name,
|
||||
args: Vec<Expression>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BinaryOperator {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Eq,
|
||||
Ne,
|
||||
Lt,
|
||||
Gt,
|
||||
Le,
|
||||
Ge,
|
||||
}
|
||||
|
||||
impl fmt::Display for BinaryOperator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BinaryOperator::Add => write!(f, "+"),
|
||||
BinaryOperator::Sub => write!(f, "-"),
|
||||
BinaryOperator::Mul => write!(f, "*"),
|
||||
BinaryOperator::Div => write!(f, "/"),
|
||||
BinaryOperator::Eq => write!(f, "=="),
|
||||
BinaryOperator::Ne => write!(f, "!="),
|
||||
BinaryOperator::Lt => write!(f, "<"),
|
||||
BinaryOperator::Gt => write!(f, ">"),
|
||||
BinaryOperator::Le => write!(f, "<="),
|
||||
BinaryOperator::Ge => write!(f, ">="),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum UnaryOperator {
|
||||
Plus,
|
||||
Minus,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnaryOperator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
UnaryOperator::Plus => write!(f, "+"),
|
||||
UnaryOperator::Minus => write!(f, "-"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> ParseResult<T, E> {
|
||||
pub fn accepted(&self) -> bool {
|
||||
matches!(self, ParseResult::Accept(_))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ParseResultResidual<T> {
|
||||
Deny,
|
||||
Reject(T),
|
||||
}
|
||||
|
||||
impl<T, E> Try for ParseResult<T, E> {
|
||||
type Output = T;
|
||||
type Residual = ParseResultResidual<E>;
|
||||
|
||||
fn from_output(output: T) -> Self {
|
||||
ParseResult::Accept(output)
|
||||
}
|
||||
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
ParseResult::Accept(v) => ControlFlow::Continue(v),
|
||||
ParseResult::Deny => ControlFlow::Break(ParseResultResidual::Deny),
|
||||
ParseResult::Reject(e) => ControlFlow::Break(ParseResultResidual::Reject(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> FromResidual for ParseResult<T, E> {
|
||||
fn from_residual(residual: ParseResultResidual<E>) -> Self {
|
||||
match residual {
|
||||
ParseResultResidual::Deny => ParseResult::Deny,
|
||||
ParseResultResidual::Reject(e) => ParseResult::Reject(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! expect_tt {
|
||||
($token:expr, $($variant:ident),+) => {{
|
||||
let tt = $token.tt().to_string();
|
||||
|
||||
// for some reason the code trips tf out without this line
|
||||
|
||||
println!("token {:?}", $token);
|
||||
|
||||
let mut vs = String::new();
|
||||
$(
|
||||
let s = stringify!($variant);
|
||||
vs.push_str(s);
|
||||
vs.push_str("|");
|
||||
)+
|
||||
|
||||
match tt.as_str() {
|
||||
$(
|
||||
stringify!($variant) => ParseResult::Accept($token.clone()),
|
||||
)+
|
||||
_ => {
|
||||
println!("EXPECTED!! {} [{}]", tt, vs);
|
||||
// let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | "));
|
||||
ParseResult::Reject(CompilerError::UnexpectedToken($token.clone()))
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! expect_value {
|
||||
($token:expr, $variant:expr) => {{
|
||||
match $token {
|
||||
$variant(x) => ParseResult::Accept(x),
|
||||
_ => {
|
||||
let expected = format!("[{}]")
|
||||
ParseResult::Reject(CompilerError::UnexpectedToken($token.clone()))
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
@@ -1,8 +1,2 @@
|
||||
main: Func = | x: U32, y: U32 | {
|
||||
res = add(x, y);
|
||||
print(res);
|
||||
|
||||
if res > 10 {
|
||||
print("res is greater than 10");
|
||||
}
|
||||
}
|
||||
fn factorial(n: u32) -> u32 {}
|
||||
fn main(x: u32, y: u32) -> u32 {}
|
||||
|
||||
@@ -0,0 +1,843 @@
|
||||
# DSA Project Roadmap & Task Breakdown
|
||||
|
||||
> **Damn Simple Architecture** — Full ecosystem development plan including emulator, assembler, compiler, debugger, and tooling infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Phase 1: Foundation & Core Infrastructure](#phase-1-foundation--core-infrastructure)
|
||||
- [1.1 Binary Format & Linking System](#11-binary-format--linking-system)
|
||||
- [1.2 Assembler Rewrite](#12-assembler-rewrite)
|
||||
- [1.3 Documentation Updates](#13-documentation-updates)
|
||||
2. [Phase 2: Compiler Development](#phase-2-compiler-development)
|
||||
- [2.1 Language Design & Implementation](#21-language-design--implementation)
|
||||
- [2.2 Standard Library](#22-standard-library)
|
||||
3. [Phase 3: Build System & Package Management](#phase-3-build-system--package-management)
|
||||
- [3.1 Build System](#31-build-system)
|
||||
- [3.2 Package Management System](#32-package-management-system)
|
||||
4. [Phase 4: Debugger & Development Tools](#phase-4-debugger--development-tools)
|
||||
- [4.1 Debug Symbol System](#41-debug-symbol-system)
|
||||
- [4.2 Debugger Implementation](#42-debugger-implementation)
|
||||
- [4.3 Enhanced Editor Integration](#43-enhanced-editor-integration)
|
||||
5. [Phase 5: Integration & Polish](#phase-5-integration--polish)
|
||||
6. [Phase 6: Future Enhancements (NTH)](#phase-6-future-enhancements-nth)
|
||||
7. [Summary Timeline](#summary-timeline)
|
||||
8. [Critical Path](#critical-path)
|
||||
9. [Recommended Work Order](#recommended-work-order)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation & Core Infrastructure
|
||||
|
||||
**Estimated Duration: 3–4 weeks**
|
||||
|
||||
---
|
||||
|
||||
### 1.1 Binary Format & Linking System
|
||||
|
||||
> **Priority: CRITICAL** — Everything depends on this.
|
||||
> **Total Estimate: 1.5 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 1.1.1 Design New Binary Format Specification
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** None
|
||||
**Deliverable:** `docs/binary-format-spec.md`
|
||||
|
||||
- [ ] Research existing object file formats (ELF, COFF, Mach-O) for inspiration
|
||||
- [ ] Design `.dsb` object file format specification
|
||||
- [ ] Symbol table structure
|
||||
- [ ] Relocation table format
|
||||
- [ ] Section definitions (code, data, rodata, bss)
|
||||
- [ ] Debug information structure
|
||||
- [ ] Metadata headers
|
||||
- [ ] Design `.dse` executable format specification
|
||||
- [ ] Entry point definition
|
||||
- [ ] Memory layout requirements
|
||||
- [ ] Linking metadata
|
||||
- [ ] Document format specifications in markdown
|
||||
- [ ] Create format version strategy for future compatibility
|
||||
|
||||
---
|
||||
|
||||
#### 1.1.2 Implement DSB Object File Writer
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 1.1.1
|
||||
**Deliverable:** `dsa-binary-format` crate v0.1.0
|
||||
|
||||
- [ ] Create new crate: `dsa-binary-format`
|
||||
- [ ] Implement object file structures
|
||||
- [ ] Header structure
|
||||
- [ ] Symbol table builder
|
||||
- [ ] Section manager
|
||||
- [ ] Relocation entry creator
|
||||
- [ ] Write serialization logic
|
||||
- [ ] Add validation and error handling
|
||||
- [ ] Write unit tests for each structure
|
||||
- [ ] Integration tests for complete object files
|
||||
|
||||
---
|
||||
|
||||
#### 1.1.3 Build Linker Program
|
||||
|
||||
**Estimate: 4 days**
|
||||
**Dependencies:** 1.1.2
|
||||
**Deliverable:** `dsa-link` executable
|
||||
|
||||
- [ ] Create new crate: `dsa-linker`
|
||||
- [ ] Implement symbol resolution
|
||||
- [ ] Global symbol table
|
||||
- [ ] Symbol conflict detection
|
||||
- [ ] Weak symbol handling
|
||||
- [ ] Implement relocation processing
|
||||
- [ ] Address calculation
|
||||
- [ ] Patch generation
|
||||
- [ ] Cross-section references
|
||||
- [ ] Build executable generator
|
||||
- [ ] Combine sections
|
||||
- [ ] Generate final memory layout
|
||||
- [ ] Write `.dse` output
|
||||
- [ ] Add linker script support (basic)
|
||||
- [ ] Comprehensive error messages
|
||||
- [ ] Test suite with complex linking scenarios
|
||||
|
||||
---
|
||||
|
||||
### 1.2 Assembler Rewrite
|
||||
|
||||
> **Priority: HIGH** — Required for all compiled code.
|
||||
> **Total Estimate: 1.5 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 1.2.1 Assembler Architecture Design
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** 1.1.1
|
||||
**Deliverable:** `docs/assembler-architecture.md`
|
||||
|
||||
- [ ] Design multi-pass architecture
|
||||
- [ ] Pass 1: Symbol collection
|
||||
- [ ] Pass 2: Macro expansion
|
||||
- [ ] Pass 3: Code generation
|
||||
- [ ] Pass 4: Relocation generation
|
||||
- [ ] Plan error handling strategy
|
||||
- [ ] Design threading model for parallel file processing
|
||||
- [ ] Define module/import resolution system
|
||||
- [ ] Plan integration points with DSC compiler
|
||||
|
||||
---
|
||||
|
||||
#### 1.2.2 Implement Core Assembler
|
||||
|
||||
**Estimate: 5 days**
|
||||
**Dependencies:** 1.1.2, 1.2.1
|
||||
**Deliverable:** `dsa-asm` executable v2.0.0
|
||||
|
||||
- [ ] Create new crate: `dsa-assembler-ng` (next-gen)
|
||||
- [ ] Implement lexer with better error recovery
|
||||
- [ ] Build parser with detailed error messages
|
||||
- [ ] Instruction parsing
|
||||
- [ ] Directive handling
|
||||
- [ ] Macro system
|
||||
- [ ] Include resolution
|
||||
- [ ] Symbol table management
|
||||
- [ ] Code generator outputting to DSB format
|
||||
- [ ] Multi-threading for file parsing
|
||||
- [ ] Comprehensive test suite
|
||||
- [ ] Error message testing
|
||||
|
||||
---
|
||||
|
||||
#### 1.2.3 Import System & DSC Integration
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 1.2.2, 2.1.2
|
||||
**Deliverable:** Working import system
|
||||
|
||||
- [ ] Design import protocol between DSC and assembler
|
||||
- [ ] Implement symbol table merging
|
||||
- [ ] Handle pre-compiled object imports
|
||||
- [ ] Test DSC → Assembly → Object pipeline
|
||||
- [ ] Document integration process
|
||||
|
||||
---
|
||||
|
||||
### 1.3 Documentation Updates
|
||||
|
||||
> **Priority: MEDIUM** — Can be done alongside development.
|
||||
> **Total Estimate: 3 days (distributed)**
|
||||
|
||||
---
|
||||
|
||||
#### 1.3.1 Update Assembly Documentation
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** 1.2.2
|
||||
**Deliverable:** Updated `docs/dsa-assembly-reference.md`
|
||||
|
||||
- [ ] Review all instruction documentation
|
||||
- [ ] Document new pseudo-instructions
|
||||
- [ ] Update calling convention docs
|
||||
- [ ] Add examples for new features
|
||||
- [ ] Document assembler directives
|
||||
- [ ] Macro system documentation
|
||||
|
||||
---
|
||||
|
||||
#### 1.3.2 Architecture Documentation
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** None (can start anytime)
|
||||
**Deliverable:** `docs/dsa-architecture.md`
|
||||
|
||||
- [ ] Document ISA specification
|
||||
- [ ] Memory model documentation
|
||||
- [ ] Interrupt handling
|
||||
- [ ] Hardware peripheral specs
|
||||
- [ ] Timing/performance characteristics
|
||||
|
||||
---
|
||||
|
||||
#### 1.3.3 Build Tools Documentation
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** 1.2.2, 1.1.3, 3.1.2
|
||||
**Deliverable:** `docs/build-tools-guide.md`
|
||||
|
||||
- [ ] Assembler usage guide
|
||||
- [ ] Linker usage guide
|
||||
- [ ] Build system guide
|
||||
- [ ] Tutorial: Building a simple program
|
||||
- [ ] Tutorial: Multi-file projects
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Compiler Development
|
||||
|
||||
**Estimated Duration: 3–4 weeks**
|
||||
|
||||
---
|
||||
|
||||
### 2.1 Language Design & Implementation
|
||||
|
||||
> **Priority: HIGH** — Core functionality.
|
||||
> **Total Estimate: 2.5 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 2.1.1 Language Syntax Design
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** None
|
||||
**Deliverable:** `docs/language-spec.md`
|
||||
|
||||
- [ ] Define syntax goals (simplicity, systems programming)
|
||||
- [ ] Design type system
|
||||
- [ ] Primitive types
|
||||
- [ ] Pointers/references
|
||||
- [ ] Structs
|
||||
- [ ] Arrays
|
||||
- [ ] Function types
|
||||
- [ ] Control flow syntax
|
||||
- [ ] Function declaration syntax
|
||||
- [ ] Module/import system
|
||||
- [ ] Operator precedence
|
||||
- [ ] Write EBNF grammar
|
||||
- [ ] Create example programs
|
||||
|
||||
---
|
||||
|
||||
#### 2.1.2 Lexer & Parser Implementation
|
||||
|
||||
**Estimate: 4 days**
|
||||
**Dependencies:** 2.1.1
|
||||
**Deliverable:** Parser in `dsc-compiler` crate
|
||||
|
||||
- [ ] Adapt existing C lexer to new syntax
|
||||
- [ ] Implement new parser for designed syntax
|
||||
- [ ] AST node definitions
|
||||
- [ ] Error recovery mechanisms
|
||||
- [ ] Comprehensive parser tests
|
||||
- [ ] Syntax error message quality testing
|
||||
|
||||
---
|
||||
|
||||
#### 2.1.3 Code Generation Improvements
|
||||
|
||||
**Estimate: 5 days**
|
||||
**Dependencies:** 2.1.2, 1.2.2
|
||||
**Deliverable:** Working code generator
|
||||
|
||||
- [ ] Review and fix existing codegen issues
|
||||
- [ ] Implement missing language features
|
||||
- [ ] Structs
|
||||
- [ ] Arrays
|
||||
- [ ] Pointers/memory operations
|
||||
- [ ] For loops
|
||||
- [ ] Switch statements
|
||||
- [ ] Break/continue
|
||||
- [ ] Optimize register allocation further
|
||||
- [ ] Implement proper function calling conventions
|
||||
- [ ] Add constant folding optimization
|
||||
- [ ] Dead code elimination
|
||||
- [ ] Test each feature thoroughly
|
||||
|
||||
---
|
||||
|
||||
#### 2.1.4 Type Checking & Semantic Analysis
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 2.1.2
|
||||
**Deliverable:** Type checker integrated in compiler
|
||||
|
||||
- [ ] Implement type checker
|
||||
- [ ] Symbol table for scoping
|
||||
- [ ] Type inference where applicable
|
||||
- [ ] Const checking
|
||||
- [ ] Definite assignment analysis
|
||||
- [ ] Comprehensive semantic error messages
|
||||
- [ ] Test suite for type errors
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Standard Library
|
||||
|
||||
> **Priority: MEDIUM** — Needed for useful programs.
|
||||
> **Total Estimate: 1 week**
|
||||
|
||||
---
|
||||
|
||||
#### 2.2.1 Core Runtime Library (in Assembly)
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 1.2.2
|
||||
**Deliverable:** `lib/runtime/` directory
|
||||
|
||||
- [ ] Memory allocation (malloc/free)
|
||||
- [ ] String operations
|
||||
- [ ] Math functions
|
||||
- [ ] I/O functions (improved print, read)
|
||||
- [ ] System call interface
|
||||
- [ ] Tests for each function
|
||||
|
||||
---
|
||||
|
||||
#### 2.2.2 Standard Library (in DSC)
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 2.1.3, 2.2.1
|
||||
**Deliverable:** `lib/std/` directory
|
||||
|
||||
- [ ] String module
|
||||
- [ ] Collections (array utilities, maybe simple list)
|
||||
- [ ] File I/O module
|
||||
- [ ] Math utilities
|
||||
- [ ] Tests and examples
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Build System & Package Management
|
||||
|
||||
**Estimated Duration: 2–3 weeks**
|
||||
|
||||
---
|
||||
|
||||
### 3.1 Build System
|
||||
|
||||
> **Priority: HIGH** — Required for complex projects.
|
||||
> **Total Estimate: 1.5 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 3.1.1 Build System Design
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** None
|
||||
**Deliverable:** `docs/build-system-design.md`
|
||||
|
||||
- [ ] Define project structure conventions
|
||||
- [ ] Design build manifest format (`dsa-project.toml` or similar)
|
||||
- [ ] Dependency resolution strategy
|
||||
- [ ] Build cache design
|
||||
- [ ] Incremental build strategy
|
||||
- [ ] Multi-target support
|
||||
|
||||
---
|
||||
|
||||
#### 3.1.2 Build Tool Implementation
|
||||
|
||||
**Estimate: 5 days**
|
||||
**Dependencies:** 3.1.1, 1.2.2, 1.1.3, 2.1.3
|
||||
**Deliverable:** `dsa-build` executable
|
||||
|
||||
- [ ] Create crate: `dsa-build`
|
||||
- [ ] Manifest parser
|
||||
- [ ] Dependency graph builder
|
||||
- [ ] Task orchestrator
|
||||
- [ ] Compilation tasks
|
||||
- [ ] Assembly tasks
|
||||
- [ ] Linking tasks
|
||||
- [ ] Build cache implementation
|
||||
- [ ] Parallel build support
|
||||
- [ ] Clean, rebuild commands
|
||||
- [ ] Watch mode for development
|
||||
- [ ] Comprehensive tests
|
||||
|
||||
---
|
||||
|
||||
#### 3.1.3 Project Management Commands
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 3.1.2
|
||||
**Deliverable:** Enhanced `dsa-build` with project management
|
||||
|
||||
- [ ] `dsa new <project>` — Create new project
|
||||
- [ ] `dsa init` — Initialize in existing directory
|
||||
- [ ] `dsa add <dependency>` — Add dependency
|
||||
- [ ] Binary vs library project types
|
||||
- [ ] Template system for project scaffolding
|
||||
- [ ] Documentation for each command
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Package Management System
|
||||
|
||||
> **Priority: MEDIUM** — Enables code sharing.
|
||||
> **Total Estimate: 1.5 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 3.2.1 Package Registry Design
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 3.1.1
|
||||
**Deliverable:** `docs/package-registry-design.md`
|
||||
|
||||
- [ ] Decide: Git monorepo vs custom hosting
|
||||
- [ ] Design package naming conventions
|
||||
- [ ] Version resolution strategy (semver)
|
||||
- [ ] Package manifest format
|
||||
- [ ] Security considerations
|
||||
- [ ] Package storage format (source/binary/both)
|
||||
- [ ] API design for registry server
|
||||
|
||||
---
|
||||
|
||||
#### 3.2.2 Local Package Manager Tool
|
||||
|
||||
**Estimate: 4 days**
|
||||
**Dependencies:** 3.2.1, 3.1.2
|
||||
**Deliverable:** `dsa-pkg` tool integrated with `dsa-build`
|
||||
|
||||
- [ ] Create crate: `dsa-pkg`
|
||||
- [ ] Package index synchronization
|
||||
- [ ] Dependency resolver
|
||||
- [ ] Package download/cache system
|
||||
- [ ] Integration with build system
|
||||
- [ ] Commands:
|
||||
- [ ] `dsa install <package>`
|
||||
- [ ] `dsa publish`
|
||||
- [ ] `dsa search <query>`
|
||||
- [ ] `dsa update`
|
||||
- [ ] Lock file generation
|
||||
- [ ] Test with mock registry
|
||||
|
||||
---
|
||||
|
||||
#### 3.2.3 Package Registry Implementation
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 3.2.1
|
||||
**Deliverable:** Package registry (URL or repo)
|
||||
|
||||
- [ ] If **Git monorepo** approach:
|
||||
- [ ] Set up repository structure
|
||||
- [ ] CI/CD for validation
|
||||
- [ ] Submission process
|
||||
- [ ] Package browser website
|
||||
- [ ] If **custom hosting**:
|
||||
- [ ] Simple web server (Rust + Axum/Actix)
|
||||
- [ ] Package upload API
|
||||
- [ ] Package search API
|
||||
- [ ] Basic web UI
|
||||
- [ ] Database for metadata
|
||||
- [ ] Documentation for publishing
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Debugger & Development Tools
|
||||
|
||||
**Estimated Duration: 3–4 weeks**
|
||||
|
||||
---
|
||||
|
||||
### 4.1 Debug Symbol System
|
||||
|
||||
> **Priority: HIGH** — Foundation for debugging.
|
||||
> **Total Estimate: 1 week**
|
||||
|
||||
---
|
||||
|
||||
#### 4.1.1 Debug Symbol Format Design
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** 1.1.1
|
||||
**Deliverable:** `docs/debug-symbol-format.md`
|
||||
|
||||
- [ ] Design symbol table format
|
||||
- [ ] Function addresses → names
|
||||
- [ ] Line number → address mapping
|
||||
- [ ] Variable location information
|
||||
- [ ] Type information
|
||||
- [ ] Define symbol table file format
|
||||
- [ ] Plan for embedding in DSE/DSB files
|
||||
|
||||
---
|
||||
|
||||
#### 4.1.2 Symbol Generation in Tools
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 4.1.1, 1.2.2, 2.1.3
|
||||
**Deliverable:** Debug symbols in build output
|
||||
|
||||
- [ ] Modify assembler to emit debug symbols
|
||||
- [ ] Modify compiler to emit debug symbols
|
||||
- [ ] Source file/line tracking
|
||||
- [ ] Variable scope tracking
|
||||
- [ ] Linker merges debug symbols
|
||||
- [ ] Test symbol generation pipeline
|
||||
|
||||
---
|
||||
|
||||
#### 4.1.3 Symbol Table Loader in Emulator
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 4.1.2
|
||||
**Deliverable:** Symbol loading in emulator crate
|
||||
|
||||
- [ ] Implement symbol table parser
|
||||
- [ ] Build address → symbol lookup (HashMap)
|
||||
- [ ] Build symbol → address lookup
|
||||
- [ ] Memory efficient storage
|
||||
- [ ] Tests for symbol resolution
|
||||
|
||||
---
|
||||
|
||||
### 4.2 Debugger Implementation
|
||||
|
||||
> **Priority: HIGH** — Major productivity boost.
|
||||
> **Total Estimate: 2 weeks**
|
||||
|
||||
---
|
||||
|
||||
#### 4.2.1 Core Debugger Features
|
||||
|
||||
**Estimate: 5 days**
|
||||
**Dependencies:** 4.1.3
|
||||
**Deliverable:** Debugger backend
|
||||
|
||||
- [ ] Execution control
|
||||
- [ ] Step instruction
|
||||
- [ ] Step over function calls
|
||||
- [ ] Continue to breakpoint
|
||||
- [ ] Run to cursor
|
||||
- [ ] Breakpoint system
|
||||
- [ ] Address breakpoints
|
||||
- [ ] Conditional breakpoints
|
||||
- [ ] Watchpoints (memory access)
|
||||
- [ ] Register inspection
|
||||
- [ ] Memory inspection
|
||||
- [ ] Stack trace generation
|
||||
- [ ] Test debugger commands
|
||||
|
||||
---
|
||||
|
||||
#### 4.2.2 Disassembler with Symbol Resolution
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** 4.1.3
|
||||
**Deliverable:** Enhanced disassembler
|
||||
|
||||
- [ ] Instruction decoder
|
||||
- [ ] Format with labels instead of addresses
|
||||
- [ ] Show function names at call sites
|
||||
- [ ] Inline comments with variable names
|
||||
- [ ] Color coding for instruction types
|
||||
- [ ] Tests for disassembly output
|
||||
|
||||
---
|
||||
|
||||
#### 4.2.3 Pseudo-Instruction Decompiler
|
||||
|
||||
> ⚠️ **COMPLEX TASK** — Separate pass to decompile assembly into readable pseudo-instructions.
|
||||
|
||||
**Estimate: 4 days**
|
||||
**Dependencies:** 4.2.2
|
||||
**Deliverable:** Pseudo-instruction view mode
|
||||
|
||||
- [ ] Pattern recognition for common sequences
|
||||
- [ ] Function prologue/epilogue
|
||||
- [ ] Multiplication using shifts/adds
|
||||
- [ ] Division
|
||||
- [ ] Conditional moves
|
||||
- [ ] Control flow reconstruction
|
||||
- [ ] If/else detection
|
||||
- [ ] Loop detection
|
||||
- [ ] Switch statement detection
|
||||
- [ ] Expression reconstruction
|
||||
- [ ] Format as higher-level pseudo-code
|
||||
- [ ] Extensive pattern testing
|
||||
|
||||
---
|
||||
|
||||
#### 4.2.4 Execution History Tracking
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 4.2.1
|
||||
**Deliverable:** Execution trace feature
|
||||
|
||||
- [ ] Circular buffer for instruction history
|
||||
- [ ] Register state snapshots over time
|
||||
- [ ] Configurable history depth
|
||||
- [ ] Efficient memory usage
|
||||
- [ ] Playback/reverse debugging (basic)
|
||||
- [ ] Export trace to file
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Enhanced Editor Integration
|
||||
|
||||
> **Priority: MEDIUM** — UX improvement.
|
||||
> **Total Estimate: 1 week**
|
||||
|
||||
---
|
||||
|
||||
#### 4.3.1 Tiling Window System
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** None (UI work)
|
||||
**Deliverable:** Panel system in emulator
|
||||
|
||||
- [ ] Research Rust tiling libraries (`egui_tiles`, or custom)
|
||||
- [ ] Design panel layout system
|
||||
- [ ] Code editor panel
|
||||
- [ ] Disassembly panel
|
||||
- [ ] Register panel
|
||||
- [ ] Memory panel
|
||||
- [ ] Console panel
|
||||
- [ ] Implement drag-and-drop panel management
|
||||
- [ ] Save/load layouts
|
||||
|
||||
---
|
||||
|
||||
#### 4.3.2 Assembly Editor Improvements
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 4.3.1
|
||||
**Deliverable:** Enhanced assembly editor
|
||||
|
||||
- [ ] Syntax highlighting for DSA assembly
|
||||
- [ ] Auto-completion for instructions
|
||||
- [ ] Label/symbol auto-completion
|
||||
- [ ] Error highlighting
|
||||
- [ ] Inline documentation tooltips
|
||||
- [ ] Jump-to-definition for labels
|
||||
|
||||
---
|
||||
|
||||
#### 4.3.3 High-Level Language Editor
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 4.3.1, 2.1.4
|
||||
**Deliverable:** DSC language editor
|
||||
|
||||
- [ ] Syntax highlighting for DSC language
|
||||
- [ ] Basic auto-completion
|
||||
- [ ] Bracket matching
|
||||
- [ ] Error highlighting from compiler
|
||||
- [ ] Go-to-definition (using debug symbols)
|
||||
- [ ] Inline type hints
|
||||
|
||||
---
|
||||
|
||||
#### 4.3.4 Integrate Build Tools in Editor
|
||||
|
||||
**Estimate: 1 day**
|
||||
**Dependencies:** 4.3.1, 3.1.2
|
||||
**Deliverable:** Integrated build experience
|
||||
|
||||
- [ ] Build button/command in UI
|
||||
- [ ] Show build output in console panel
|
||||
- [ ] Error navigation (click to jump to source)
|
||||
- [ ] Hot reload on successful build
|
||||
- [ ] Build status indicator
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Integration & Polish
|
||||
|
||||
**Estimated Duration: 1–2 weeks**
|
||||
|
||||
---
|
||||
|
||||
### 5.1 Tool Integration
|
||||
|
||||
> **Priority: HIGH** — Everything works together.
|
||||
> **Total Estimate: 1 week**
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.1 Unified Toolchain
|
||||
|
||||
**Estimate: 3 days**
|
||||
**Dependencies:** All previous phases
|
||||
**Deliverable:** `dsa` unified command-line tool
|
||||
|
||||
- [ ] Create meta-crate: `dsa-tools`
|
||||
- [ ] Unified CLI with subcommands
|
||||
- [ ] `dsa build`
|
||||
- [ ] `dsa run`
|
||||
- [ ] `dsa debug`
|
||||
- [ ] `dsa test`
|
||||
- [ ] `dsa pkg`
|
||||
- [ ] Shared configuration system
|
||||
- [ ] Tool interop testing
|
||||
- [ ] Documentation for workflow
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.2 Emulator Integration
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 5.1.1, 4.3.4
|
||||
**Deliverable:** Fully integrated development environment
|
||||
|
||||
- [ ] Add build tools as emulator dependencies
|
||||
- [ ] In-editor build triggered from emulator
|
||||
- [ ] Debugger uses build output directly
|
||||
- [ ] Source-level debugging with line mapping
|
||||
- [ ] Test full edit → build → debug cycle
|
||||
|
||||
---
|
||||
|
||||
#### 5.1.3 Documentation & Tutorials
|
||||
|
||||
**Estimate: 2 days**
|
||||
**Dependencies:** 5.1.2
|
||||
**Deliverable:** Complete documentation suite
|
||||
|
||||
- [ ] Getting started guide
|
||||
- [ ] Full tutorial: Building a simple game
|
||||
- [ ] Debugger usage guide
|
||||
- [ ] Best practices document
|
||||
- [ ] Troubleshooting guide
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Future Enhancements (NTH)
|
||||
|
||||
> **Priority: LOW** — Nice to have, long-term goal.
|
||||
> **Estimated Duration: 4+ weeks**
|
||||
|
||||
---
|
||||
|
||||
### 6.1 Command-Line Emulator
|
||||
|
||||
> ⚠️ **COMPLEX LONG-TERM GOAL** — Requires significant design and UX consideration.
|
||||
|
||||
---
|
||||
|
||||
#### 6.1.1 Design Phase
|
||||
|
||||
**Estimate: 1 week**
|
||||
**Dependencies:** None
|
||||
**Deliverable:** `docs/cli-emulator-design.md`
|
||||
|
||||
- [ ] UX research for terminal-based debuggers
|
||||
- [ ] Design TUI layout (using `ratatui` or similar)
|
||||
- [ ] Command syntax design
|
||||
- [ ] Scripting support design
|
||||
- [ ] Accessibility considerations
|
||||
|
||||
---
|
||||
|
||||
#### 6.1.2 Implementation
|
||||
|
||||
**Estimate: 3+ weeks**
|
||||
**Dependencies:** 6.1.1, Phase 4 complete
|
||||
**Deliverable:** `dsa-emu-cli` executable
|
||||
|
||||
- [ ] TUI framework setup
|
||||
- [ ] Core emulator integration
|
||||
- [ ] Command parser
|
||||
- [ ] Panel rendering (code, registers, memory, etc.)
|
||||
- [ ] Keyboard shortcuts
|
||||
- [ ] Mouse support
|
||||
- [ ] Configuration system
|
||||
- [ ] Extensive usability testing
|
||||
|
||||
---
|
||||
|
||||
## Summary Timeline
|
||||
|
||||
| Phase | Duration | Key Dependencies |
|
||||
|---|---|---|
|
||||
| Phase 1: Foundation | 3–4 weeks | None |
|
||||
| Phase 2: Compiler | 3–4 weeks | Phase 1 complete |
|
||||
| Phase 3: Build System | 2–3 weeks | Phases 1–2 complete |
|
||||
| Phase 4: Debugger | 3–4 weeks | Phases 1–3 complete |
|
||||
| Phase 5: Integration | 1–2 weeks | Phases 1–4 complete |
|
||||
| Phase 6: CLI Emulator *(NTH)* | 4+ weeks | Phase 4 complete |
|
||||
|
||||
**Total Estimated Time: 12–17 weeks (3–4 months) for Phases 1–5**
|
||||
|
||||
---
|
||||
|
||||
## Critical Path
|
||||
|
||||
The following tasks are on the critical path and will block other work if delayed:
|
||||
|
||||
```
|
||||
1.1.1 Binary format design
|
||||
└── 1.1.2 Object file writer
|
||||
└── 1.1.3 Linker
|
||||
└── 1.2.2 Assembler rewrite
|
||||
└── 2.1.3 Compiler codegen
|
||||
└── 3.1.2 Build system
|
||||
└── 4.1.2 Debug symbols
|
||||
└── 4.2.1 Debugger
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommended Work Order
|
||||
|
||||
| Weeks | Focus | Tasks |
|
||||
|---|---|---|
|
||||
| 1–2 | Binary Format & Linker | 1.1.1 → 1.1.2 → 1.1.3 |
|
||||
| 3–4 | Assembler Rewrite | 1.2.1 → 1.2.2 |
|
||||
| 5–6 | Compiler Syntax & Parser | 2.1.1 → 2.1.2 *(start 1.3 docs in parallel)* |
|
||||
| 7–9 | Compiler Codegen & Types | 2.1.3 → 2.1.4 *(start 2.2.1 runtime in parallel)* |
|
||||
| 10–11 | Build System | 3.1.1 → 3.1.2 → 3.1.3 |
|
||||
| 12–13 | Package Management *(if desired now)* | 3.2.1 → 3.2.2 → 3.2.3 |
|
||||
| 14–15 | Debug Symbols | 4.1.1 → 4.1.2 → 4.1.3 |
|
||||
| 16–18 | Core Debugger | 4.2.1 → 4.2.2 → 4.2.4 |
|
||||
| 19–20 | Editor Enhancements | 4.3.1 → 4.3.2 → 4.3.3 → 4.3.4 |
|
||||
| 21–22 | Integration & Polish | 5.1.1 → 5.1.2 → 5.1.3 |
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Time estimates assume ~6–8 productive hours per day.
|
||||
- Add **20–30% buffer** for unexpected issues.
|
||||
- Testing time is included in each estimate.
|
||||
- Documentation is distributed throughout rather than batched at the end.
|
||||
- Package management (3.2) can be deferred if time-constrained.
|
||||
- Pseudo-instruction decompiler (4.2.3) can be a stretch goal.
|
||||
- CLI emulator (Phase 6) is explicitly a "nice to have" and should not block other work.
|
||||
Binary file not shown.
@@ -0,0 +1,427 @@
|
||||
# DSA Assembly Language Instruction Reference
|
||||
|
||||
## Overview
|
||||
|
||||
This document provides a comprehensive reference for the DSA (Damn Simple Architecture) assembly language, including all hardware instructions and pseudo-instructions with their syntax variations and usage examples.
|
||||
|
||||
## Calling Convention
|
||||
|
||||
| Step | Responsibility | Action | Description |
|
||||
|------|----------------|--------|-------------|
|
||||
| 1 | **Caller** | Push arguments | Push exactly n arguments to the stack (in order, last argument pushed first) |
|
||||
| 2 | **Caller** | Call function | Execute `call namespace::function` - this automatically pushes the return address (pcx) and jumps to the function |
|
||||
| 3 | **Function** | Set up stack frame | Execute `push bpr; mov spr, bpr` to establish new stack frame |
|
||||
| 4 | **Function** | Access arguments | Read arguments starting at `spr+8` (first 3 args at offsets 8, 12, 16) |
|
||||
| 5 | **Function** | Execute function | Perform the function's operations using the arguments |
|
||||
| 6 | **Function** | Store return value | Write return value (if any) to `spr+8` |
|
||||
| 7 | **Function** | Restore stack frame | Execute `mov bpr, spr; pop bpr` to restore previous stack frame |
|
||||
| 8 | **Function** | Return | Execute `return` pseudo-instruction to return to caller |
|
||||
| 9 | **Caller** | Clean up stack | Pop exactly n arguments from the stack to clean up |
|
||||
| 10 | **Caller** | Handle unused values | Use `pop zero` to discard any unused stack values if needed |
|
||||
|
||||
**Notes:**
|
||||
- The namespace in step 2 is the name assigned in the `include` statement
|
||||
- The `call` pseudo-instruction automatically handles return address management so long as the callee does not mess with the stack
|
||||
- Arguments are accessed by the callee using offsets from the base pointer (bpr)
|
||||
|
||||
## Registers
|
||||
|
||||
| Register | Type | Description |
|
||||
|----------|------|---------------------------------------------------------------------------------------------------|
|
||||
| `rg0-rgf` | General Purpose | General-purpose registers. |
|
||||
| `acc` | Special | Accumulator for calculations and temporary storage - don't use this for variables as pseudo instructions may overwrite this implicitly! |
|
||||
| `spr` | Special | Stack pointer |
|
||||
| `bpr` | Special | Base pointer for stack frames |
|
||||
| `ret` | Special | Return address register |
|
||||
| `idr` | Privileged | Interrupt descriptor table address<br/>**on-read/write: protection fault (unless in kernel mode)** |
|
||||
| `mmr` | Privileged | Hardware memory map table address<br/>**on-read/write: protection fault (unless in kernel mode)** |
|
||||
| `zero` | Read-only | Always contains zero<br/>**on-read: always returns zero**<br/>**on-write: value is voided** |
|
||||
| `pcx` | Read-only | Program counter<br/>**on-write: protection fault** |
|
||||
| `noreg` | Placeholder | Indicates absence of register argument<br/>**on-read/write: illegal instruction fault** |
|
||||
|
||||
## Hardware Instructions
|
||||
|
||||
### Data Movement Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **MOV** | `src_reg, dest_reg` | Copy value from source to destination register |
|
||||
| **MOVS** | `src_reg, dest_reg` | Copy with sign extension |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
mov rg0, rg1 ; Copy rg0 to rg1
|
||||
movs rg0, rg1 ; Copy rg0 to rg1 with sign extension
|
||||
```
|
||||
### Memory Access Instructions
|
||||
|
||||
#### Load Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **LDB** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load byte from memory |
|
||||
| **LDBS** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load byte with sign extension |
|
||||
| **LDH** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load half-word (16-bit) |
|
||||
| **LDHS** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load half-word with sign extension |
|
||||
| **LDW** | `base_reg, dest_reg [, offset]`<br>`label, dest_reg [, offset]` | Load word (32-bit) |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
; Direct register addressing
|
||||
ldb rg0, rg1 ; Load byte from address in rg0
|
||||
ldw rg0, rg1, 8 ; Load word from (rg0 + 8)
|
||||
|
||||
; Label addressing
|
||||
ldb buffer, rg2 ; Load byte from label 'buffer'
|
||||
ldw stack, bpr ; Load stack address into base pointer
|
||||
```
|
||||
**Label Expansions:**
|
||||
```asm
|
||||
; ldb buffer, rg2 expands to:
|
||||
lli buffer, rg2 ; Load lower 16 bits of buffer address
|
||||
lui buffer, rg2 ; Load upper 16 bits of buffer address
|
||||
ldb rg2, rg2 ; Load byte from address in rg2
|
||||
|
||||
; ldw stack, bpr expands to:
|
||||
lli stack, bpr ; Load lower 16 bits of stack address
|
||||
lui stack, bpr ; Load upper 16 bits of stack address
|
||||
ldw bpr, bpr ; Load word from address in bpr
|
||||
```
|
||||
#### Store Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **STB** | `src_reg, base_reg [, offset]`<br>`src_reg, label [, offset]` | Store byte to memory |
|
||||
| **STH** | `src_reg, base_reg [, offset]`<br>`src_reg, label [, offset]` | Store half-word to memory |
|
||||
| **STW** | `src_reg, base_reg [, offset]`<br>`src_reg, label [, offset]` | Store word to memory |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
; Direct register addressing
|
||||
stb rg0, rg1 ; Store byte from rg0 to address in rg1
|
||||
stw rg0, rg1, 12 ; Store word to (rg1 + 12)
|
||||
|
||||
; Label addressing
|
||||
stb acc, buffer ; Store byte from accumulator to 'buffer'
|
||||
stw rg1, current ; Store word to 'current' variable
|
||||
```
|
||||
**Label Expansions:**
|
||||
```asm
|
||||
; stb acc, buffer expands to:
|
||||
lli buffer, rgf ; Load lower 16 bits of buffer address
|
||||
lui buffer, rgf ; Load upper 16 bits of buffer address
|
||||
stb acc, rgf ; Store byte from acc to address in rgf
|
||||
|
||||
; stw rg1, current expands to:
|
||||
lli current, rgf ; Load lower 16 bits of current address
|
||||
lui current, rgf ; Load upper 16 bits of current address
|
||||
stw rg1, rgf ; Store word from rg1 to address in rgf
|
||||
```
|
||||
### Immediate Load Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|------------------------------------------------------------------------|
|
||||
| **LLI** | `imm, dest_reg` | Load 16-bit immediate into lower 16 bits<br/>**Clears upper 16 bits!** |
|
||||
| **LUI** | `imm, dest_reg` | Load 16-bit immediate into upper 16 bits |
|
||||
|
||||
**Usage**
|
||||
|
||||
ensure that you always run **Lli** before **Lui** as **Lli** clears the upper 16 bits.
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
lli 0x1234, rg0 ; Load 0x1234 into lower 16 bits of rg0
|
||||
lui 0xABCD, rg0 ; Load 0xABCD into upper 16 bits of rg0
|
||||
```
|
||||
### Jump Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **JMP** | `addr [, offset_reg]`<br>`imm, offset_reg` | Unconditional jump |
|
||||
| **JEQ** | `addr [, offset_reg]` | Jump if equal flag set |
|
||||
| **JNE** | `addr [, offset_reg]` | Jump if not equal flag set |
|
||||
| **JGT** | `addr [, offset_reg]` | Jump if greater than flag set |
|
||||
| **JGE** | `addr [, offset_reg]` | Jump if greater or equal flags set |
|
||||
| **JLT** | `addr [, offset_reg]` | Jump if less than flag set |
|
||||
| **JLE** | `addr [, offset_reg]` | Jump if less or equal flags set |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
jmp start ; Jump to label 'start'
|
||||
jmp 4, ret ; Jump to address (4 + ret register)
|
||||
jeq end ; Jump to 'end' if equal flag set
|
||||
jgt loop ; Jump to 'loop' if greater than flag set
|
||||
```
|
||||
### Arithmetic Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **ADD** | `src1_reg, src2_reg, dest_reg` | Addition |
|
||||
| **SUB** | `src1_reg, src2_reg, dest_reg` | Subtraction |
|
||||
| **IADD** | `src_reg, imm [, dest_reg]` | Immediate addition |
|
||||
| **ISUB** | `src_reg, imm [, dest_reg]` | Immediate subtraction |
|
||||
| **INC** | `reg` | Increment register by 1 |
|
||||
| **DEC** | `reg` | Decrement register by 1 |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
add rg0, rg1, rg2 ; rg2 = rg0 + rg1
|
||||
sub rg0, rg1, rg2 ; rg2 = rg0 - rg1
|
||||
iadd rg0, 10 ; rg0 = rg0 + 10
|
||||
// or using alternate syntax
|
||||
addi rg0, 1 ; rg0 = rg0 + 1
|
||||
inc rg0 ; rg0 = rg0 + 1
|
||||
```
|
||||
### Bitwise Operations
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **AND** | `src1_reg, src2_reg, dest_reg` | Bitwise AND |
|
||||
| **OR** | `src1_reg, src2_reg, dest_reg` | Bitwise OR |
|
||||
| **XOR** | `src1_reg, src2_reg, dest_reg` | Bitwise XOR |
|
||||
| **NOT** | `src_reg, dest_reg` | Bitwise NOT |
|
||||
| **NAND** | `src1_reg, src2_reg, dest_reg` | Bitwise NAND |
|
||||
| **NOR** | `src1_reg, src2_reg, dest_reg` | Bitwise NOR |
|
||||
| **XNOR** | `src1_reg, src2_reg, dest_reg` | Bitwise XNOR |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
and rg0, rg1, rg2 ; rg2 = rg0 & rg1
|
||||
not rg0, rg1 ; rg1 = ~rg0
|
||||
```
|
||||
### Shift Operations
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **SHL** | `reg, shift_amount` | Shift left |
|
||||
| **SHR** | `reg, shift_amount` | Shift right |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
shl rg0, 2 ; Shift rg0 left by 2 bits
|
||||
shr rg0, 3 ; Shift rg0 right by 3 bits
|
||||
```
|
||||
### Comparison and Control
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **CMP** | `reg1, reg2` | Compare registers and set flags |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
cmp rg0, zero ; Compare rg0 with zero register
|
||||
cmp rg1, rg2 ; Compare rg1 with rg2
|
||||
```
|
||||
### System Instructions
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **HLT** | - | Halt processor execution |
|
||||
| **NOP** | - | No operation |
|
||||
| **INT** | `interrupt_code` | Trigger interrupt |
|
||||
| **IRT** | - | Return from interrupt |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
hlt ; Stop processor execution
|
||||
int 0x21 ; Trigger interrupt 0x21
|
||||
```
|
||||
## Pseudo-Instructions
|
||||
|
||||
### Data Definition
|
||||
|
||||
| Mnemonic | Syntax | Description |
|
||||
|----------|--------|-------------|
|
||||
| **DB** | `name: value1 [, value2, ...]` | Define bytes |
|
||||
| **DH** | `name: value1 [, value2, ...]` | Define half-words |
|
||||
| **DW** | `name: value1 [, value2, ...]` | Define words |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
db message: "Hello World", 0
|
||||
dh numbers: 1000, 2000, 3000
|
||||
dw stack: 0x10000
|
||||
```
|
||||
### Memory Reservation
|
||||
|
||||
| Mnemonic | Syntax | Description |
|
||||
|----------|--------|-------------|
|
||||
| **RESB** | `name: size` | Reserve bytes |
|
||||
| **RESH** | `name: size` | Reserve half-words |
|
||||
| **RESW** | `name: size` | Reserve words |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
resb buffer: 256 ; Reserve 256 bytes
|
||||
resh array: 100 ; Reserve space for 100 half-words
|
||||
resw heap: 1024 ; Reserve space for 1024 words
|
||||
```
|
||||
### Stack Operations
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **PUSH** | `reg` | Push register value onto stack |
|
||||
| **POP** | `reg` | Pop stack value into register |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
push rg0 ; Push rg0 value onto stack
|
||||
pop ret ; Pop return address
|
||||
```
|
||||
### Memory Access Shortcuts
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **LWI** | `name, reg` | Load address into register |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
lwi string, rg1 ; Load address of 'string' into rg1
|
||||
```
|
||||
|
||||
### Function Control
|
||||
|
||||
| Mnemonic | Operands | Description |
|
||||
|----------|----------|-------------|
|
||||
| **CALL** | `namespace::function` | Call a function with automatic return address management |
|
||||
| **RETURN** | - | Return from a function to the caller |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
call print::print ; Call the print function from the print namespace
|
||||
return ; Return from the current function
|
||||
```
|
||||
|
||||
### Module System
|
||||
|
||||
| Mnemonic | Syntax | Description |
|
||||
|----------|--------|-------------|
|
||||
| **INCLUDE** | `module_name "path"` | Include module |
|
||||
|
||||
**Examples:**
|
||||
```asm
|
||||
include print "print.dsa"
|
||||
include fib "fib.dsa"
|
||||
```
|
||||
## Library Examples
|
||||
|
||||
### Multiplication Library (multiply.dsa)
|
||||
|
||||
```asm
|
||||
// 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
|
||||
|
||||
lli 0, acc // initialize accumulator
|
||||
|
||||
start:
|
||||
add acc, rg0, acc
|
||||
dec rg1
|
||||
|
||||
cmp rg1, zero
|
||||
jgt start
|
||||
|
||||
end:
|
||||
stw acc, bpr, 8 // store result for caller
|
||||
mov bpr, spr
|
||||
pop bpr
|
||||
return
|
||||
```
|
||||
|
||||
### Print Library (print.dsa)
|
||||
|
||||
```asm
|
||||
// print.dsa
|
||||
// usage:
|
||||
//
|
||||
// include print "<relative path>"
|
||||
//
|
||||
// usage for print:
|
||||
// push (register containing address of string)
|
||||
// call print::print
|
||||
// pop zero
|
||||
//
|
||||
// usage for reset:
|
||||
// call print::reset
|
||||
|
||||
dw display: 0x20000
|
||||
dw current: 0x20000
|
||||
|
||||
// prints the given text to the screen.
|
||||
print:
|
||||
push bpr
|
||||
mov spr, bpr
|
||||
|
||||
ldw bpr, rg0, 8 // get string address argument
|
||||
ldw current, rg1 // get current display position
|
||||
|
||||
print_loop:
|
||||
ldb rg0, acc
|
||||
stb acc, rg1
|
||||
|
||||
iadd rg0, 1
|
||||
iadd rg1, 1
|
||||
|
||||
cmp acc, zero
|
||||
jne print_loop
|
||||
jmp end
|
||||
|
||||
// return
|
||||
end:
|
||||
stw rg1, current
|
||||
|
||||
mov bpr, spr
|
||||
pop bpr
|
||||
return
|
||||
|
||||
// resets the cursor position on the screen
|
||||
reset:
|
||||
push bpr
|
||||
mov spr, bpr
|
||||
ldw display, rg1
|
||||
stw rg1, current
|
||||
mov bpr, spr
|
||||
pop bpr
|
||||
return
|
||||
```
|
||||
|
||||
### Example Program (main.dsa)
|
||||
|
||||
```asm
|
||||
include print "./print.dsa"
|
||||
|
||||
dw stack: 0x10000
|
||||
db string: "'To confuse your enemy, you must first confuse yourself' - Probably Sun Tzu."
|
||||
|
||||
init:
|
||||
// set up a stack.
|
||||
ldw stack, bpr
|
||||
mov bpr, spr
|
||||
|
||||
start:
|
||||
lwi string, rg1
|
||||
|
||||
// push string address argument
|
||||
push rg1
|
||||
// call print function
|
||||
call print::print
|
||||
// clean up stack
|
||||
pop rg1
|
||||
|
||||
hlt
|
||||
```
|
||||
@@ -0,0 +1,10 @@
|
||||
# DSA File formatting specification.
|
||||
|
||||
First, a clarification on what formats this document references.
|
||||
|
||||
- .dsb: DSA Binary object, similar to a .o object file
|
||||
- .dse: DSA Executable file, similar to a .exe/ELF binary
|
||||
|
||||
## Format Specification
|
||||
|
||||
### DSB binary format
|
||||
Reference in New Issue
Block a user