Skip to content

Commit

Permalink
structure: Restructure remaining source modules
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkajetanp committed Sep 15, 2024
1 parent 8304f03 commit effb820
Show file tree
Hide file tree
Showing 18 changed files with 695 additions and 684 deletions.
153 changes: 0 additions & 153 deletions src/ir.rs → src/codegen/ir/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,156 +544,3 @@ impl fmt::Display for Identifier {
write!(f, "{}", self.name)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn ir_program() {
let mut ctx = IrCtx::new();

let ast_program = ast::Program {
body: vec![ast::FunctionDeclaration {
name: ast::Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
body: Some(ast::Block {
body: vec![ast::BlockItem::Stmt(ast::Statement::Return(
ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
),
))],
}),
}],
};

let expected = Program {
body: vec![Function::generate(ast_program.body[0].clone(), &mut ctx).unwrap()],
};
let mut ctx = IrCtx::new();
let actual = Program::generate(ast_program, &mut ctx);
assert_eq!(actual, expected);
}

#[test]
fn ir_function() {
let mut ctx = IrCtx::new();

let stmt = ast::Statement::Return(ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
));

let ast_fn = ast::FunctionDeclaration {
name: ast::Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
body: Some(ast::Block {
body: vec![ast::BlockItem::Stmt(stmt.clone())],
}),
};

let expected = Function {
name: Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
instructions: vec![
Instruction::generate_from_statement(stmt, &mut ctx),
vec![Instruction::Return(Val::Constant(0))],
]
.into_iter()
.flatten()
.collect(),
};

let mut ctx = IrCtx::new();
let actual = Function::generate(ast_fn, &mut ctx);

assert_eq!(actual, Some(expected));
}

#[test]
fn ir_instruction_unary() {
let mut ctx = IrCtx::new();
let stmt = ast::Statement::Return(ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
));
let actual = Instruction::generate_from_statement(stmt, &mut ctx);
let expected = vec![
Instruction::Unary(
UnaryOperator::Negation,
Val::Constant(5),
Val::Var(Identifier::new("tmp.ir.0")),
),
Instruction::Return(Val::Var(Identifier::new("tmp.ir.0"))),
];
assert_eq!(actual, expected);
}

#[test]
fn ir_instruction_return() {
let mut ctx = IrCtx::new();
let stmt = ast::Statement::Return(ast::Expression::Constant(4));
let actual = Instruction::generate_from_statement(stmt, &mut ctx);
let expected = vec![Instruction::Return(Val::Constant(4))];
assert_eq!(actual, expected);
}

#[test]
fn ir_instruction_from_expression() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();
let expr = ast::Expression::Constant(5);
let expected = Val::generate(expr.clone(), &mut instructions, &mut ctx);
let (actual_instructions, actual) = Instruction::generate_from_expr(expr, &mut ctx);
assert_eq!(expected, actual);
assert_eq!(instructions, actual_instructions);
}

#[test]
fn ir_val_var() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();

let actual = Val::generate(
ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
),
&mut instructions,
&mut ctx,
);
let expected = Val::Var(Identifier::new("tmp.ir.0"));
assert_eq!(actual, expected);
let instr = instructions.pop().unwrap();
let expected_instr =
Instruction::Unary(UnaryOperator::Negation, Val::Constant(5), expected.clone());
assert_eq!(instr, expected_instr);
assert!(instructions.is_empty());
}

#[test]
fn ir_val_constant() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();

let actual = Val::generate(ast::Expression::Constant(5), &mut instructions, &mut ctx);
let expected = Val::Constant(5);
assert_eq!(actual, expected);
assert!(instructions.is_empty());
}

#[test]
fn ir_unary() {
let actual = UnaryOperator::generate(ast::UnaryOperator::Complement);
let expected = UnaryOperator::Complement;
assert_eq!(actual, expected);

let actual = UnaryOperator::generate(ast::UnaryOperator::Negation);
let expected = UnaryOperator::Negation;
assert_eq!(actual, expected);
}
}
4 changes: 4 additions & 0 deletions src/codegen/ir/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod ir;
#[cfg(test)]
mod tests;
pub use ir::*;
150 changes: 150 additions & 0 deletions src/codegen/ir/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use super::*;
use crate::parser::ast;

#[test]
fn ir_program() {
let mut ctx = IrCtx::new();

let ast_program = ast::Program {
body: vec![ast::FunctionDeclaration {
name: ast::Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
body: Some(ast::Block {
body: vec![ast::BlockItem::Stmt(ast::Statement::Return(
ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
),
))],
}),
}],
};

let expected = Program {
body: vec![Function::generate(ast_program.body[0].clone(), &mut ctx).unwrap()],
};
let mut ctx = IrCtx::new();
let actual = Program::generate(ast_program, &mut ctx);
assert_eq!(actual, expected);
}

#[test]
fn ir_function() {
let mut ctx = IrCtx::new();

let stmt = ast::Statement::Return(ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
));

let ast_fn = ast::FunctionDeclaration {
name: ast::Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
body: Some(ast::Block {
body: vec![ast::BlockItem::Stmt(stmt.clone())],
}),
};

let expected = Function {
name: Identifier::new("main"),
params: vec![],
return_type: "Int".to_owned(),
instructions: vec![
Instruction::generate_from_statement(stmt, &mut ctx),
vec![Instruction::Return(Val::Constant(0))],
]
.into_iter()
.flatten()
.collect(),
};

let mut ctx = IrCtx::new();
let actual = Function::generate(ast_fn, &mut ctx);

assert_eq!(actual, Some(expected));
}

#[test]
fn ir_instruction_unary() {
let mut ctx = IrCtx::new();
let stmt = ast::Statement::Return(ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
));
let actual = Instruction::generate_from_statement(stmt, &mut ctx);
let expected = vec![
Instruction::Unary(
UnaryOperator::Negation,
Val::Constant(5),
Val::Var(Identifier::new("tmp.ir.0")),
),
Instruction::Return(Val::Var(Identifier::new("tmp.ir.0"))),
];
assert_eq!(actual, expected);
}

#[test]
fn ir_instruction_return() {
let mut ctx = IrCtx::new();
let stmt = ast::Statement::Return(ast::Expression::Constant(4));
let actual = Instruction::generate_from_statement(stmt, &mut ctx);
let expected = vec![Instruction::Return(Val::Constant(4))];
assert_eq!(actual, expected);
}

#[test]
fn ir_instruction_from_expression() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();
let expr = ast::Expression::Constant(5);
let expected = Val::generate(expr.clone(), &mut instructions, &mut ctx);
let (actual_instructions, actual) = Instruction::generate_from_expr(expr, &mut ctx);
assert_eq!(expected, actual);
assert_eq!(instructions, actual_instructions);
}

#[test]
fn ir_val_var() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();

let actual = Val::generate(
ast::Expression::Unary(
ast::UnaryOperator::Negation,
Box::new(ast::Expression::Constant(5)),
),
&mut instructions,
&mut ctx,
);
let expected = Val::Var(Identifier::new("tmp.ir.0"));
assert_eq!(actual, expected);
let instr = instructions.pop().unwrap();
let expected_instr =
Instruction::Unary(UnaryOperator::Negation, Val::Constant(5), expected.clone());
assert_eq!(instr, expected_instr);
assert!(instructions.is_empty());
}

#[test]
fn ir_val_constant() {
let mut instructions = vec![];
let mut ctx = IrCtx::new();

let actual = Val::generate(ast::Expression::Constant(5), &mut instructions, &mut ctx);
let expected = Val::Constant(5);
assert_eq!(actual, expected);
assert!(instructions.is_empty());
}

#[test]
fn ir_unary() {
let actual = UnaryOperator::generate(ast::UnaryOperator::Complement);
let expected = UnaryOperator::Complement;
assert_eq!(actual, expected);

let actual = UnaryOperator::generate(ast::UnaryOperator::Negation);
let expected = UnaryOperator::Negation;
assert_eq!(actual, expected);
}
2 changes: 2 additions & 0 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod ir;
pub mod x86_64;
4 changes: 4 additions & 0 deletions src/codegen/x86_64/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mod x86_64;
pub use x86_64::*;
#[cfg(test)]
mod tests;
Loading

0 comments on commit effb820

Please sign in to comment.