- fixed some clippy lints
- updated comments in compiler codegen - deleted old dsa compiler outputs - settings for zed
This commit is contained in:
@@ -83,34 +83,27 @@ impl CodeGenerator {
|
||||
let mut block = IB::new();
|
||||
|
||||
block.extend(vec![
|
||||
I::comment("GENERATED BY DSC COMPILER"),
|
||||
I::comment(format!(
|
||||
"Generated at {}\n",
|
||||
I::global_comment(format!(
|
||||
"GENERATED BY DSC COMPILER
|
||||
Generated at {}",
|
||||
datetime.format("%Y-%m-%d %H:%M:%S")
|
||||
)),
|
||||
I::comment("Imports"),
|
||||
I::Newline,
|
||||
I::global_comment("Imports"),
|
||||
]);
|
||||
|
||||
block.extend(
|
||||
self.imports
|
||||
.iter()
|
||||
.map(|(_name, instruction)| instruction.clone())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
block.push(I::comment(""));
|
||||
block.push(I::comment("Globals & Reserved Memory"));
|
||||
|
||||
block.extend(
|
||||
self.globals
|
||||
.iter()
|
||||
.map(|(_name, instruction)| instruction.clone())
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
block.extend(self.imports.values().cloned().collect::<Vec<_>>());
|
||||
|
||||
block.extend(vec![
|
||||
I::comment(""),
|
||||
I::comment("Entry Point"),
|
||||
I::Newline,
|
||||
I::global_comment("Globals & Reserved Memory"),
|
||||
]);
|
||||
|
||||
block.extend(self.globals.values().cloned().collect::<Vec<_>>());
|
||||
|
||||
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.
|
||||
@@ -127,8 +120,9 @@ impl CodeGenerator {
|
||||
I::call("print::print_hex_word"),
|
||||
I::pop(Register::Zero),
|
||||
I::Hlt,
|
||||
I::Newline,
|
||||
// default return block boilerplate
|
||||
I::comment("Return"),
|
||||
I::global_comment("Return"),
|
||||
I::label("_ret"),
|
||||
I::mov(Register::Bpr, Register::Spr),
|
||||
I::pop(Register::Bpr),
|
||||
@@ -199,11 +193,8 @@ impl CodeGenerator {
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
|
||||
code.push(I::comment(format!(
|
||||
"fn {name}({fmtparams}) -> {return_type}"
|
||||
)));
|
||||
|
||||
code.extend(vec![
|
||||
I::global_comment(format!("fn {name}({fmtparams}) -> {return_type}")),
|
||||
I::label(name),
|
||||
I::push(Register::Bpr),
|
||||
I::mov(Register::Spr, Register::Bpr),
|
||||
@@ -233,6 +224,8 @@ impl CodeGenerator {
|
||||
code.push(I::jmp("_ret"));
|
||||
}
|
||||
|
||||
code.insert(0, I::Newline);
|
||||
|
||||
code
|
||||
}
|
||||
|
||||
@@ -336,19 +329,19 @@ impl CodeGenerator {
|
||||
I::sub(var_reg, result_reg, temp_reg)
|
||||
}
|
||||
AssignmentOperator::MulAssign => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"TODO: implement multiplication for assignment"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"TODO: implement multiplication for assignment".to_string(),
|
||||
));
|
||||
}
|
||||
AssignmentOperator::DivAssign => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"TODO: write proper div function for DSA"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"TODO: write proper div function for DSA".to_string(),
|
||||
));
|
||||
}
|
||||
AssignmentOperator::ModAssign => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"TODO: write proper mod function for DSA"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"TODO: write proper mod function for DSA".to_string(),
|
||||
));
|
||||
}
|
||||
AssignmentOperator::AndAssign => {
|
||||
I::and(var_reg, result_reg, temp_reg)
|
||||
@@ -428,7 +421,7 @@ impl CodeGenerator {
|
||||
code.append(self.generate_statement(s, func_body)?);
|
||||
}
|
||||
|
||||
if then_stmt.len() == 0 {
|
||||
if then_stmt.is_empty() {
|
||||
code.push(I::Nop);
|
||||
}
|
||||
|
||||
@@ -440,7 +433,7 @@ impl CodeGenerator {
|
||||
code.append(self.generate_statement(s, func_body)?);
|
||||
}
|
||||
|
||||
if else_stmt.len() == 0 {
|
||||
if else_stmt.is_empty() {
|
||||
code.push(I::Nop);
|
||||
}
|
||||
|
||||
@@ -620,9 +613,9 @@ impl CodeGenerator {
|
||||
code.push(I::pop(Register::Zero));
|
||||
}
|
||||
BinaryOperator::Div => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"TODO: write proper div function for DSA"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"TODO: write proper div function for DSA".to_string(),
|
||||
));
|
||||
// self.include("maths", "./lib/maths/core.dsa");
|
||||
// // Call divide function
|
||||
// code.push(format!("\tpush {}", right_reg));
|
||||
@@ -632,9 +625,9 @@ impl CodeGenerator {
|
||||
// code.push("\tpop zero".to_string());
|
||||
}
|
||||
BinaryOperator::Mod => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"TODO: write proper mod function for DSA"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"TODO: write proper mod function for DSA".to_string(),
|
||||
));
|
||||
// self.include("maths", "./lib/maths/core.dsa");
|
||||
// // Call modulo function
|
||||
// code.push(format!("\tpush {}", right_reg));
|
||||
@@ -653,14 +646,14 @@ impl CodeGenerator {
|
||||
code.push(I::xor(left_reg, right_reg, result_reg));
|
||||
}
|
||||
BinaryOperator::LogicalAnd => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"assembler/ISA does not yet support logical and!"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"assembler/ISA does not yet support logical and!".to_string(),
|
||||
));
|
||||
}
|
||||
BinaryOperator::LogicalOr => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"assembler/ISA does not yet support logical or!"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"assembler/ISA does not yet support logical or!".to_string(),
|
||||
));
|
||||
}
|
||||
BinaryOperator::LeftShift => {
|
||||
code.push(I::shl(left_reg, right_reg, 0, result_reg));
|
||||
@@ -816,9 +809,9 @@ impl CodeGenerator {
|
||||
code.push(I::not(operand_reg, result_reg));
|
||||
}
|
||||
UnaryOperator::LogicalNot => {
|
||||
return Err(CompilerError::Unimplemented(format!(
|
||||
"Assembler/ISA does not yet support logical not"
|
||||
)));
|
||||
return Err(CompilerError::Unimplemented(
|
||||
"Assembler/ISA does not yet support logical not".to_string(),
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
return Err(CompilerError::Generic(format!(
|
||||
@@ -932,9 +925,9 @@ impl CodeGenerator {
|
||||
expr,
|
||||
field_name,
|
||||
type_id,
|
||||
} => Err(CompilerError::Unimplemented(format!(
|
||||
"Structs are not yet implemented!"
|
||||
))),
|
||||
} => Err(CompilerError::Unimplemented(
|
||||
"Structs are not yet implemented!".to_string(),
|
||||
)),
|
||||
|
||||
Expression::TypeCast {
|
||||
expr,
|
||||
|
||||
@@ -60,7 +60,11 @@ impl From<Instruction> for InsBlock {
|
||||
pub enum Instruction {
|
||||
// Labels and comments
|
||||
Label(Label),
|
||||
Comment(String),
|
||||
Comment {
|
||||
text: String,
|
||||
top_level: bool,
|
||||
},
|
||||
Newline,
|
||||
|
||||
// Data Directives
|
||||
Db {
|
||||
@@ -287,7 +291,20 @@ impl fmt::Display for Instruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::Label(l) => write!(f, "{}:", l),
|
||||
Self::Comment(c) => write!(f, "// {}", c),
|
||||
Self::Newline => write!(f, ""), /* empty string as newlines are inserted */
|
||||
// automatically.
|
||||
Self::Comment { text, top_level } => write!(
|
||||
f,
|
||||
"{}",
|
||||
text.lines()
|
||||
.map(|line| format!(
|
||||
"{}// {}",
|
||||
if *top_level { "" } else { " " },
|
||||
line.trim(),
|
||||
))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
),
|
||||
|
||||
Self::Include { name, path } => write!(f, "include {name}: \"{}\"", path),
|
||||
|
||||
@@ -455,6 +472,7 @@ impl fmt::Display for Instruction {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
// data directives
|
||||
pub fn db_string(label: impl Into<String>, data: impl Into<String>) -> Self {
|
||||
@@ -590,7 +608,7 @@ impl Instruction {
|
||||
}
|
||||
|
||||
pub fn iadd(src: Register, value: i64) -> Self {
|
||||
let imm = Imm(value.abs() as u32);
|
||||
let imm = Imm(value.unsigned_abs() as u32);
|
||||
|
||||
if value < 0 {
|
||||
Self::ISub {
|
||||
@@ -608,7 +626,7 @@ impl Instruction {
|
||||
}
|
||||
|
||||
pub fn iadd_dest(src: Register, value: i32, dest: Register) -> Self {
|
||||
let imm = Imm(value.abs() as u32);
|
||||
let imm = Imm(value.unsigned_abs());
|
||||
|
||||
if value < 0 {
|
||||
Self::ISub {
|
||||
@@ -702,7 +720,17 @@ impl Instruction {
|
||||
|
||||
// Utilities
|
||||
pub fn comment(text: impl Into<String>) -> Self {
|
||||
Self::Comment(text.into())
|
||||
Self::Comment {
|
||||
text: text.into(),
|
||||
top_level: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn global_comment(text: impl Into<String>) -> Self {
|
||||
Self::Comment {
|
||||
text: text.into(),
|
||||
top_level: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn include(name: impl Into<String>, path: impl Into<String>) -> Self {
|
||||
|
||||
@@ -186,8 +186,7 @@ impl RegisterAllocator {
|
||||
// Update location to register
|
||||
self.variable_locations
|
||||
.insert(var_name.to_string(), location);
|
||||
self.register_contents
|
||||
.insert(reg.clone(), var_name.to_string());
|
||||
self.register_contents.insert(reg, var_name.to_string());
|
||||
|
||||
return Ok((reg, code));
|
||||
}
|
||||
@@ -197,8 +196,7 @@ impl RegisterAllocator {
|
||||
let (reg, code) = self.alloc_temp()?;
|
||||
self.variable_locations
|
||||
.insert(var_name.to_string(), Location::register(reg));
|
||||
self.register_contents
|
||||
.insert(reg.clone(), var_name.to_string());
|
||||
self.register_contents.insert(reg, var_name.to_string());
|
||||
|
||||
Ok((reg, code))
|
||||
}
|
||||
@@ -225,11 +223,12 @@ impl RegisterAllocator {
|
||||
// Check if variable already has a location
|
||||
if let Some(location) = self.variable_locations.get(var_name) {
|
||||
// if the variable exists in a register we write to that.
|
||||
if let Some(reg) = location.register {
|
||||
if reg == *source_reg {
|
||||
match location.register {
|
||||
Some(reg) if reg == *source_reg => {
|
||||
block.push(Instruction::mov(*source_reg, reg));
|
||||
return block;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// if the variable exists on the stack but not a register we write here.
|
||||
@@ -263,7 +262,7 @@ impl RegisterAllocator {
|
||||
self.variable_locations
|
||||
.insert(var_name.to_string(), Location::register(free_reg));
|
||||
self.register_contents
|
||||
.insert(free_reg.clone(), var_name.to_string());
|
||||
.insert(free_reg, var_name.to_string());
|
||||
self.in_use[free_reg as usize].1 = true;
|
||||
|
||||
block.push(Instruction::mov(*source_reg, free_reg));
|
||||
@@ -428,17 +427,6 @@ impl RegisterAllocator {
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Mark a variable as dead (no longer needed)
|
||||
/// Frees its register if it's in one
|
||||
// pub fn _free_var(&mut self, var_name: &str) {
|
||||
// if let Some(Location::Register(reg)) = self.variable_locations.get(var_name) {
|
||||
// let reg = reg.clone();
|
||||
// self.register_contents.remove(®);
|
||||
// self.in_use.insert(reg, false);
|
||||
// }
|
||||
// self.variable_locations.remove(var_name);
|
||||
// }
|
||||
|
||||
/// Get list of registers that contain variables and are in use
|
||||
/// These need to be saved before function calls
|
||||
pub fn get_caller_saved_registers(&self) -> Vec<Register> {
|
||||
@@ -450,7 +438,7 @@ impl RegisterAllocator {
|
||||
.unwrap_or(&(Register::Null, false))
|
||||
.1
|
||||
})
|
||||
.map(|(reg, _)| reg.clone())
|
||||
.map(|(reg, _)| *reg)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,8 +592,7 @@ impl<'a> Lexer<'a> {
|
||||
if c.is_ascii_digit() {
|
||||
self.advance();
|
||||
num_str.push(c);
|
||||
} else if c == '_'
|
||||
&& self.peek_second().map_or(false, |ch| ch.is_ascii_digit())
|
||||
} else if c == '_' && self.peek_second().is_some_and(|ch| ch.is_ascii_digit())
|
||||
{
|
||||
// Allow underscores as separators only between digits
|
||||
self.advance();
|
||||
@@ -611,10 +610,11 @@ impl<'a> Lexer<'a> {
|
||||
let mut num_str = String::new();
|
||||
|
||||
// Read the first hex digit (current character)
|
||||
if let Some(c) = self.current {
|
||||
if c.is_ascii_hexdigit() {
|
||||
match self.current {
|
||||
Some(c) if c.is_ascii_hexdigit() => {
|
||||
num_str.push(c);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
while let Some(c) = self.peek() {
|
||||
@@ -640,10 +640,11 @@ impl<'a> Lexer<'a> {
|
||||
let mut num_str = String::new();
|
||||
|
||||
// Read the first binary digit (current character)
|
||||
if let Some(c) = self.current {
|
||||
if c == '0' || c == '1' {
|
||||
match self.current {
|
||||
Some(c) if c == '0' || c == '1' => {
|
||||
num_str.push(c);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
while let Some(c) = self.peek() {
|
||||
|
||||
@@ -123,7 +123,7 @@ impl Parser {
|
||||
}
|
||||
|
||||
let _ = expect_tt!(self.next()?, RightBrace)?;
|
||||
return ParseResult::Accept(Declaration::Struct { name, fields });
|
||||
ParseResult::Accept(Declaration::Struct { name, fields })
|
||||
}
|
||||
|
||||
fn parse_func(&mut self) -> ParseResult<Declaration, CompilerError> {
|
||||
@@ -403,7 +403,7 @@ impl Parser {
|
||||
let expr = self.parse_expression()?;
|
||||
let _ = expect_tt!(self.next()?, Semicolon)?;
|
||||
|
||||
return ParseResult::Accept(Statement::Expression { expr });
|
||||
ParseResult::Accept(Statement::Expression { expr })
|
||||
}
|
||||
|
||||
fn parse_expression(&mut self) -> ParseResult<Expression, CompilerError> {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use std::path::Path;
|
||||
|
||||
use compiler;
|
||||
|
||||
fn main() {
|
||||
// read from input file: syntax "c_compiler <src.c> [output.dsa]"
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
Reference in New Issue
Block a user