- added support for args in Builder trait

- added is_lib arg for compiler to produce non-main assembly outputs
- updated templates to use include_str
This commit is contained in:
2026-02-23 22:06:07 +00:00
parent 71b36dc6b5
commit 4bee36eb7f
28 changed files with 889 additions and 525 deletions
+5
View File
@@ -4,6 +4,11 @@ version.workspace = true
edition.workspace = true
authors.workspace = true
[[bin]]
name = "dsa-c"
path = "src/main.rs"
[dependencies]
chrono = "0.4.43"
common = { path = "../dsa_common" }
+29 -20
View File
@@ -20,10 +20,11 @@ pub struct CodeGenerator {
functions: Vec<IB>,
symbols: Vec<String>,
allocator: RegisterAllocator,
is_library: bool,
}
impl CodeGenerator {
pub fn new(ast: Program) -> Self {
pub fn new(ast: Program, is_lib: bool) -> Self {
CodeGenerator {
ast,
imports: HashMap::new(),
@@ -31,6 +32,7 @@ impl CodeGenerator {
functions: Vec::new(),
symbols: Vec::new(),
allocator: RegisterAllocator::new(),
is_library: is_lib,
}
}
@@ -46,7 +48,9 @@ impl CodeGenerator {
pub fn generate(&mut self) -> Result<String, CompilerError> {
// always include the print library for debugging!
self.include("print", "./lib/io/print.dsa");
if !self.is_library {
self.include("print", "./lib/print.dsa");
}
for block in self.ast.clone().declarations {
match block {
@@ -101,25 +105,30 @@ impl CodeGenerator {
block.extend(self.globals.values().cloned().collect::<Vec<_>>());
if !self.is_library {
block.extend(vec![
I::Newline,
I::global_comment("Entry Point"),
I::db_word("stack", 0x10000),
I::db_string("message", "Process Exited with code:"),
// init function for stack setup.
I::label("_init"),
I::ldw_label("stack", Register::Bpr),
I::mov(Register::Bpr, Register::Spr),
I::push(Register::Zero),
I::call("main"),
I::call("print::print_newline"),
I::lwi_label("message", Register::Rg0),
I::push(Register::Rg0),
I::call("print::print"),
I::pop(Register::Zero),
I::call("print::print_hex_word"),
I::pop(Register::Zero),
I::Hlt,
]);
}
block.extend(vec![
I::Newline,
I::global_comment("Entry Point"),
I::db_word("stack", 0x10000),
I::db_string("message", "Process Exited with code:"),
// init function for stack setup.
I::label("_init"),
I::ldw_label("stack", Register::Bpr),
I::mov(Register::Bpr, Register::Spr),
I::push(Register::Zero),
I::call("main"),
I::call("print::print_newline"),
I::lwi_label("message", Register::Rg0),
I::push(Register::Rg0),
I::call("print::print"),
I::pop(Register::Zero),
I::call("print::print_hex_word"),
I::pop(Register::Zero),
I::Hlt,
I::Newline,
// default return block boilerplate
I::global_comment("Return"),
+2 -2
View File
@@ -5,7 +5,7 @@ mod instruction;
mod registers;
mod scope;
pub fn generate_code(ast: &Program) -> Result<String, CompilerError> {
let mut codegen = codegen::CodeGenerator::new(ast.clone());
pub fn generate_code(ast: &Program, is_lib: bool) -> Result<String, CompilerError> {
let mut codegen = codegen::CodeGenerator::new(ast.clone(), is_lib);
codegen.generate()
}
+6 -2
View File
@@ -2,9 +2,13 @@ use crate::model::{CompilerError, Program};
mod dsa;
pub fn compiler_backend(ext: &str, ast: &Program) -> Result<String, CompilerError> {
pub fn compiler_backend(
ext: &str,
ast: &Program,
is_lib: bool,
) -> Result<String, CompilerError> {
match ext {
"dsa" => Ok(dsa::generate_code(ast)?),
"dsa" => Ok(dsa::generate_code(ast, is_lib)?),
_ => Err(CompilerError::Generic(format!(
"File type {} not supported",
ext
+34 -29
View File
@@ -722,37 +722,42 @@ impl Parser {
// if the next token isn't the beginning of a struct literal this is just
// an identifier.
if !expect_tt!(self.peek_next()?, LeftBrace).accepted() {
return ParseResult::Accept(Expression::Variable {
name,
expr_type: None,
});
}
let _ = self.next()?;
let mut fields = Vec::new();
while !expect_tt!(self.peek_next()?, RightBrace).accepted() {
let name = expect_value!(self.next()?, Identifier)?;
let _ = expect_tt!(self.next()?, Colon)?;
let expr = self.parse_expression()?;
fields.push((name, expr));
if expect_tt!(self.peek_next()?, Comma).accepted() {
self.next()?;
} else {
break;
}
}
let _ = expect_tt!(self.next()?, RightBrace)?;
ParseResult::Accept(Expression::StructLiteral {
// if !expect_tt!(self.peek_next()?, LeftBrace).accepted() {
// return ParseResult::Accept(Expression::Variable {
// name,
// expr_type: None,
// });
// }
//
ParseResult::Accept(Expression::Variable {
name,
fields,
type_id: None,
expr_type: None,
})
// let _ = self.next()?;
// let mut fields = Vec::new();
// while !expect_tt!(self.peek_next()?, RightBrace).accepted() {
// let name = expect_value!(self.next()?, Identifier)?;
// let _ = expect_tt!(self.next()?, Colon)?;
// let expr = self.parse_expression()?;
// fields.push((name, expr));
// if expect_tt!(self.peek_next()?, Comma).accepted() {
// self.next()?;
// } else {
// break;
// }
// }
// let _ = expect_tt!(self.next()?, RightBrace)?;
// ParseResult::Accept(Expression::StructLiteral {
// name,
// fields,
// type_id: None,
// })
}
Token::LeftBracket => {
self.next()?; // consume '['
+5 -4
View File
@@ -21,7 +21,7 @@ pub struct Compiler {
}
impl Compiler {
fn build(&mut self) -> Result<String, Box<dyn std::error::Error>> {
fn build(&mut self, is_lib: bool) -> Result<String, Box<dyn std::error::Error>> {
let input =
std::fs::read_to_string(&self.src_path).expect("Failed to read input file");
@@ -46,7 +46,7 @@ impl Compiler {
// println!("Parsed AST: {:#?}", ast);
// Generate the output using the backend with the parsed result.
let result = match backend::compiler_backend("dsa", &ast) {
let result = match backend::compiler_backend("dsa", &ast, is_lib) {
Ok(result) => result,
Err(err) => return Err(format!("Compilation failed: {err:?}").into()),
};
@@ -57,6 +57,7 @@ impl Compiler {
impl Builder for Compiler {
type Output = String;
type Args = bool;
fn new(src_path: impl Into<PathBuf>) -> Self {
Self {
@@ -66,8 +67,8 @@ impl Builder for Compiler {
}
}
fn start(&mut self) {
match self.build() {
fn start(&mut self, args: bool) {
match self.build(args) {
Ok(x) => self.result = Some(Ok(x)),
Err(err) => self.result = Some(Err(err.into())),
}
+4 -2
View File
@@ -7,7 +7,7 @@ fn main() {
// read from input file: syntax "c_compiler <src.c> [output.dsa]"
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
eprintln!("Usage: c_compiler <src.dsc> [output.dsa]");
eprintln!("Usage: c_compiler [--lib | --bin] <src.dsc> [output.dsa]");
return;
}
@@ -19,8 +19,10 @@ fn main() {
};
{
let is_lib = args.contains(&"--lib".to_string());
let mut builder = Compiler::new(PathBuf::from(input_file));
builder.start();
builder.start(is_lib);
let result = builder.output().unwrap();
std::fs::write(output_file, &result).expect("Failed to write output");