- 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:
@@ -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" }
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 '['
|
||||
|
||||
@@ -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())),
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user