From 15089a15d210931f69301a421bc6a268b0a28403 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 5 Mar 2026 12:41:05 -0600 Subject: [PATCH] Re-introduce ir with goal of doing register allocation. --- dm/src/main.rs | 13 ++++ dmc-lib/src/ast/additive_expression.rs | 17 ++++++ dmc-lib/src/ast/ast_to_ir_util.rs | 52 ++++++++++++++++ dmc-lib/src/ast/call.rs | 37 +++++++++++- dmc-lib/src/ast/expression_statement.rs | 13 ++++ dmc-lib/src/ast/function.rs | 15 +++++ dmc-lib/src/ast/ir_builder.rs | 80 +++++++++++++++++++++++++ dmc-lib/src/ast/let_statement.rs | 36 +++++++++++ dmc-lib/src/ast/mod.rs | 2 + dmc-lib/src/ast/statement.rs | 12 ++++ dmc-lib/src/ir/ir_add.rs | 22 +++++++ dmc-lib/src/ir/ir_assign.rs | 23 +++++++ dmc-lib/src/ir/ir_block.rs | 42 +++++++++++++ dmc-lib/src/ir/ir_call.rs | 31 ++++++++++ dmc-lib/src/ir/ir_expression.rs | 25 ++++++++ dmc-lib/src/ir/ir_function.rs | 22 +++++++ dmc-lib/src/ir/ir_operation.rs | 26 ++++++++ dmc-lib/src/ir/ir_return.rs | 22 +++++++ dmc-lib/src/ir/ir_statement.rs | 26 ++++++++ dmc-lib/src/ir/ir_variable.rs | 19 ++++++ dmc-lib/src/ir/mod.rs | 10 ++++ dmc-lib/src/lib.rs | 1 + 22 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 dmc-lib/src/ast/ast_to_ir_util.rs create mode 100644 dmc-lib/src/ast/ir_builder.rs create mode 100644 dmc-lib/src/ir/ir_add.rs create mode 100644 dmc-lib/src/ir/ir_assign.rs create mode 100644 dmc-lib/src/ir/ir_block.rs create mode 100644 dmc-lib/src/ir/ir_call.rs create mode 100644 dmc-lib/src/ir/ir_expression.rs create mode 100644 dmc-lib/src/ir/ir_function.rs create mode 100644 dmc-lib/src/ir/ir_operation.rs create mode 100644 dmc-lib/src/ir/ir_return.rs create mode 100644 dmc-lib/src/ir/ir_statement.rs create mode 100644 dmc-lib/src/ir/ir_variable.rs create mode 100644 dmc-lib/src/ir/mod.rs diff --git a/dm/src/main.rs b/dm/src/main.rs index 070b7e7..eecbe36 100644 --- a/dm/src/main.rs +++ b/dm/src/main.rs @@ -4,6 +4,7 @@ use codespan_reporting::files::SimpleFiles; use codespan_reporting::term; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use dm_std_lib::add_all_std_core; +use dmc_lib::ast::module_level_declaration::ModuleLevelDeclaration; use dmc_lib::constants_table::ConstantsTable; use dmc_lib::diagnostic::Diagnostic; use dmc_lib::parser::parse_compilation_unit; @@ -21,6 +22,9 @@ struct Cli { #[arg(long)] show_asm: bool, + + #[arg(long)] + show_ir: bool, } fn main() { @@ -50,6 +54,15 @@ fn main() { let type_check_diagnostics = compilation_unit.type_check(&symbol_table); check_and_report_diagnostics(&files, script_file_id, &type_check_diagnostics); + if args.show_ir { + for declaration in compilation_unit.declarations() { + if let ModuleLevelDeclaration::Function(function) = declaration { + let ir_function = function.to_ir(&symbol_table); + println!("{}", ir_function) + } + } + } + let mut constants_table = ConstantsTable::new(); let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table); diff --git a/dmc-lib/src/ast/additive_expression.rs b/dmc-lib/src/ast/additive_expression.rs index e765a96..9008296 100644 --- a/dmc-lib/src/ast/additive_expression.rs +++ b/dmc-lib/src/ast/additive_expression.rs @@ -1,12 +1,21 @@ use crate::asm::asm_instruction::{Add, AsmInstruction, LoadConstant, Move, Operand, Pop}; use crate::ast::assemble_context::AssembleContext; +use crate::ast::ast_to_ir_util::expression_to_ir_expression; use crate::ast::expression::Expression; +use crate::ast::ir_builder::IrBuilder; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::ir::ir_add::IrAdd; +use crate::ir::ir_assign::IrAssign; +use crate::ir::ir_expression::IrExpression; +use crate::ir::ir_operation::IrOperation; +use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; use crate::symbol::ExpressibleSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; +use std::ops::Deref; pub struct AdditiveExpression { lhs: Box, @@ -65,6 +74,14 @@ impl AdditiveExpression { } } + pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrAdd { + let lhs_ir_expression = expression_to_ir_expression(&self.lhs, builder, symbol_table) + .expect("Attempt to add non-expression"); + let rhs_ir_expression = expression_to_ir_expression(&self.rhs, builder, symbol_table) + .expect("Attempt to add non-expression"); + IrAdd::new(lhs_ir_expression, rhs_ir_expression) + } + fn assemble_side( expression: &Expression, context: &mut AssembleContext, diff --git a/dmc-lib/src/ast/ast_to_ir_util.rs b/dmc-lib/src/ast/ast_to_ir_util.rs new file mode 100644 index 0000000..855969f --- /dev/null +++ b/dmc-lib/src/ast/ast_to_ir_util.rs @@ -0,0 +1,52 @@ +use crate::ast::expression::Expression; +use crate::ast::ir_builder::IrBuilder; +use crate::ir::ir_assign::IrAssign; +use crate::ir::ir_expression::IrExpression; +use crate::ir::ir_operation::IrOperation; +use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; +use crate::symbol_table::SymbolTable; +use crate::type_info::TypeInfo; + +pub fn expression_to_ir_expression( + expression: &Expression, + builder: &mut IrBuilder, + symbol_table: &SymbolTable, +) -> Option { + match expression { + Expression::Call(call) => { + let ir_call = call.to_ir(builder, symbol_table); + if matches!(call.type_info(), TypeInfo::Void) { + builder + .current_block_mut() + .add_statement(IrStatement::Call(ir_call)); + None + } else { + let t_var = IrVariable::new(&builder.new_t_var()); + let assign = IrAssign::new(t_var.clone(), IrOperation::Call(ir_call)); + builder + .current_block_mut() + .add_statement(IrStatement::Assign(assign)); + Some(IrExpression::Variable(t_var)) + } + } + Expression::IntegerLiteral(integer_literal) => { + Some(IrExpression::Int(integer_literal.value())) + } + Expression::String(string_literal) => { + Some(IrExpression::String(string_literal.content().into())) + } + Expression::Identifier(identifier) => Some(IrExpression::Variable(IrVariable::new( + identifier.name().into(), + ))), + Expression::Additive(additive_expression) => { + let ir_add = additive_expression.to_ir(builder, symbol_table); + let t_var = IrVariable::new(&builder.new_t_var()); + let assign = IrAssign::new(t_var.clone(), IrOperation::Add(ir_add)); + builder + .current_block_mut() + .add_statement(IrStatement::Assign(assign)); + Some(IrExpression::Variable(t_var)) + } + } +} diff --git a/dmc-lib/src/ast/call.rs b/dmc-lib/src/ast/call.rs index 2805795..aa0c235 100644 --- a/dmc-lib/src/ast/call.rs +++ b/dmc-lib/src/ast/call.rs @@ -2,13 +2,19 @@ use crate::asm::asm_instruction::{ AsmInstruction, InvokePlatformStatic, InvokeStatic, LoadConstant, Operand, Push, }; use crate::ast::assemble_context::AssembleContext; +use crate::ast::ast_to_ir_util::expression_to_ir_expression; use crate::ast::expression::Expression; +use crate::ast::ir_builder::IrBuilder; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::ir::ir_call::IrCall; +use crate::ir::ir_expression::IrExpression; use crate::source_range::SourceRange; -use crate::symbol::ExpressibleSymbol; +use crate::symbol::{ExpressibleSymbol, FunctionSymbol}; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; +use std::cell::RefCell; +use std::rc::Rc; pub struct Call { callee: Box, @@ -121,6 +127,35 @@ impl Call { } } + fn get_callee_symbol(&self) -> Rc> { + match self.callee() { + Expression::Identifier(identifier) => { + let expressible_symbol = identifier.expressible_symbol(); + match expressible_symbol { + ExpressibleSymbol::Function(function_symbol) => function_symbol.clone(), + _ => panic!("Calling things other than functions not yet supported."), + } + } + _ => panic!("Calling things other than identifiers not yet supported."), + } + } + + pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrCall { + let arguments: Vec = self + .arguments + .iter() + .map(|argument| expression_to_ir_expression(argument, builder, symbol_table)) + .inspect(|expression| { + if expression.is_none() { + panic!("Attempt to pass non-expression") + } + }) + .map(Option::unwrap) + .collect(); + let function_symbol = self.get_callee_symbol(); + IrCall::new(function_symbol.borrow().name_owned(), arguments) + } + pub fn assemble( &self, context: &mut AssembleContext, diff --git a/dmc-lib/src/ast/expression_statement.rs b/dmc-lib/src/ast/expression_statement.rs index 4474c24..d76e600 100644 --- a/dmc-lib/src/ast/expression_statement.rs +++ b/dmc-lib/src/ast/expression_statement.rs @@ -1,8 +1,12 @@ use crate::asm::asm_instruction::{AsmInstruction, Pop, SetReturnValue}; use crate::ast::assemble_context::AssembleContext; +use crate::ast::ast_to_ir_util::expression_to_ir_expression; use crate::ast::expression::Expression; +use crate::ast::ir_builder::IrBuilder; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::ir::ir_return::IrReturn; +use crate::ir::ir_statement::IrStatement; use crate::symbol::FunctionSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; @@ -36,6 +40,15 @@ impl ExpressionStatement { self.expression.type_check(symbol_table) } + pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable, is_last: bool) { + let ir_expression = expression_to_ir_expression(self.expression(), builder, symbol_table); + if ir_expression.is_some() && is_last { + builder + .current_block_mut() + .add_statement(IrStatement::Return(IrReturn::new(ir_expression))); + } + } + pub fn assemble( &self, context: &mut AssembleContext, diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index 61cc40e..eed1004 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -1,10 +1,12 @@ use crate::asm::asm_instruction::{AsmInstruction, Return}; use crate::ast::assemble_context::AssembleContext; +use crate::ast::ir_builder::IrBuilder; use crate::ast::parameter::Parameter; use crate::ast::statement::Statement; use crate::ast::type_use::TypeUse; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::ir::ir_function::IrFunction; use crate::source_range::SourceRange; use crate::symbol::FunctionSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; @@ -158,6 +160,19 @@ impl Function { diagnostics } + pub fn to_ir(&self, symbol_table: &SymbolTable) -> IrFunction { + let mut builder = IrBuilder::new(); + let entry_block_id = builder.new_block(); + for (i, statement) in self.statements.iter().enumerate() { + let is_last = i == self.statements.len() - 1; + statement.to_ir(&mut builder, symbol_table, is_last); + } + builder.finish_block(); + + let entry_block = builder.get_block(entry_block_id); + IrFunction::new(Rc::from(self.declared_name()), entry_block.clone()) + } + pub fn assemble( &self, context: &mut AssembleContext, diff --git a/dmc-lib/src/ast/ir_builder.rs b/dmc-lib/src/ast/ir_builder.rs new file mode 100644 index 0000000..101dd0a --- /dev/null +++ b/dmc-lib/src/ast/ir_builder.rs @@ -0,0 +1,80 @@ +use crate::ir::ir_block::IrBlock; +use crate::ir::ir_statement::IrStatement; +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +pub struct IrBuilder { + block_counter: usize, + t_var_counter: usize, + blocks: HashMap>>, + current_block_builder: Option, +} + +impl IrBuilder { + pub fn new() -> Self { + Self { + block_counter: 0, + t_var_counter: 0, + blocks: HashMap::new(), + current_block_builder: None, + } + } + + pub fn new_block(&mut self) -> usize { + let block_id = self.block_counter; + self.block_counter += 1; + let block_builder = IrBlockBuilder::new(block_id); + self.current_block_builder = Some(block_builder); + block_id + } + + pub fn get_block(&mut self, block_id: usize) -> &Rc> { + self.blocks + .get(&block_id) + .expect(&format!("Block {} not found", block_id)) + } + + pub fn current_block_mut(&mut self) -> &mut IrBlockBuilder { + self.current_block_builder + .as_mut() + .expect("No current block builder") + } + + pub fn finish_block(&mut self) { + let builder = self + .current_block_builder + .take() + .expect("No current block builder"); + let block = builder.build(); + self.blocks.insert(block.id(), Rc::new(RefCell::new(block))); + } + + pub fn new_t_var(&mut self) -> String { + let id = self.t_var_counter; + self.t_var_counter += 1; + format!("t{}", id) + } +} + +pub struct IrBlockBuilder { + id: usize, + statements: Vec, +} + +impl IrBlockBuilder { + pub fn new(id: usize) -> Self { + Self { + id, + statements: vec![], + } + } + + pub fn add_statement(&mut self, statement: IrStatement) { + self.statements.push(statement); + } + + pub fn build(self) -> IrBlock { + IrBlock::new(self.id, &format!("b{}:", self.id), self.statements) + } +} diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index f9a6ad9..8a5fb2f 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -1,11 +1,20 @@ use crate::asm::asm_instruction::{AsmInstruction, LoadConstant, Move, Operand, Pop}; use crate::ast::assemble_context::AssembleContext; use crate::ast::expression::Expression; +use crate::ast::ir_builder::IrBuilder; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::ir::ir_add::IrAdd; +use crate::ir::ir_assign::IrAssign; +use crate::ir::ir_call::IrCall; +use crate::ir::ir_expression::IrExpression; +use crate::ir::ir_operation::IrOperation; +use crate::ir::ir_statement::IrStatement; +use crate::ir::ir_variable::IrVariable; use crate::source_range::SourceRange; use crate::symbol::{ExpressibleSymbol, VariableSymbol}; use crate::symbol_table::{SymbolInsertError, SymbolTable}; +use std::process::id; pub struct LetStatement { declared_name: String, @@ -81,6 +90,33 @@ impl LetStatement { vec![] } + pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) { + let init_operation = match self.initializer() { + Expression::Call(call) => IrOperation::Call(call.to_ir(builder, symbol_table)), + Expression::IntegerLiteral(integer_literal) => { + IrOperation::Load(IrExpression::Int(integer_literal.value())) + } + Expression::String(string_literal) => { + IrOperation::Load(IrExpression::String(string_literal.content().into())) + } + Expression::Identifier(identifier) => { + IrOperation::Load(IrExpression::Variable(IrVariable::new(identifier.name()))) + } + Expression::Additive(additive_expression) => { + IrOperation::Add(additive_expression.to_ir(builder, symbol_table)) + } + }; + + let destination_variable = IrVariable::new(self.declared_name()); + + builder + .current_block_mut() + .add_statement(IrStatement::Assign(IrAssign::new( + destination_variable, + init_operation, + ))) + } + pub fn assemble( &self, context: &mut AssembleContext, diff --git a/dmc-lib/src/ast/mod.rs b/dmc-lib/src/ast/mod.rs index 83f5ba5..10559b9 100644 --- a/dmc-lib/src/ast/mod.rs +++ b/dmc-lib/src/ast/mod.rs @@ -1,5 +1,6 @@ pub mod additive_expression; pub mod assemble_context; +mod ast_to_ir_util; pub mod call; pub mod compilation_unit; pub mod expression; @@ -9,6 +10,7 @@ pub mod fqn; pub mod function; pub mod identifier; pub mod integer_literal; +mod ir_builder; pub mod let_statement; pub mod module_level_declaration; pub mod parameter; diff --git a/dmc-lib/src/ast/statement.rs b/dmc-lib/src/ast/statement.rs index 807bf36..6d6cf76 100644 --- a/dmc-lib/src/ast/statement.rs +++ b/dmc-lib/src/ast/statement.rs @@ -1,5 +1,6 @@ use crate::ast::assemble_context::AssembleContext; use crate::ast::expression_statement::ExpressionStatement; +use crate::ast::ir_builder::IrBuilder; use crate::ast::let_statement::LetStatement; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; @@ -41,6 +42,17 @@ impl Statement { } } + pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable, is_last: bool) { + match self { + Statement::Let(let_statement) => { + let_statement.to_ir(builder, symbol_table); + } + Statement::Expression(expression_statement) => { + expression_statement.to_ir(builder, symbol_table, is_last); + } + } + } + pub fn assemble( &self, context: &mut AssembleContext, diff --git a/dmc-lib/src/ir/ir_add.rs b/dmc-lib/src/ir/ir_add.rs new file mode 100644 index 0000000..ae70f6b --- /dev/null +++ b/dmc-lib/src/ir/ir_add.rs @@ -0,0 +1,22 @@ +use crate::ir::ir_expression::IrExpression; +use std::fmt::{Display, Formatter}; + +pub struct IrAdd { + left: Box, + right: Box, +} + +impl IrAdd { + pub fn new(left: IrExpression, right: IrExpression) -> Self { + Self { + left: left.into(), + right: right.into(), + } + } +} + +impl Display for IrAdd { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} + {}", self.left, self.right) + } +} diff --git a/dmc-lib/src/ir/ir_assign.rs b/dmc-lib/src/ir/ir_assign.rs new file mode 100644 index 0000000..d8f6bd4 --- /dev/null +++ b/dmc-lib/src/ir/ir_assign.rs @@ -0,0 +1,23 @@ +use crate::ir::ir_operation::IrOperation; +use crate::ir::ir_variable::IrVariable; +use std::fmt::{Display, Formatter}; + +pub struct IrAssign { + destination: Box, + initializer: Box, +} + +impl IrAssign { + pub fn new(destination: IrVariable, initializer: IrOperation) -> Self { + Self { + destination: destination.into(), + initializer: initializer.into(), + } + } +} + +impl Display for IrAssign { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} = {}", self.destination, self.initializer) + } +} diff --git a/dmc-lib/src/ir/ir_block.rs b/dmc-lib/src/ir/ir_block.rs new file mode 100644 index 0000000..2f4f692 --- /dev/null +++ b/dmc-lib/src/ir/ir_block.rs @@ -0,0 +1,42 @@ +use crate::ir::ir_statement::IrStatement; +use std::cell::RefCell; +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +pub struct IrBlock { + id: usize, + debug_label: String, + predecessors: Vec>>, + successors: Vec>>, + statements: Vec, +} + +impl IrBlock { + pub fn new(id: usize, debug_label: &str, statements: Vec) -> Self { + Self { + id, + debug_label: debug_label.into(), + predecessors: vec![], + successors: vec![], + statements, + } + } + + pub fn id(&self) -> usize { + self.id + } + + pub fn statements(&self) -> &[IrStatement] { + &self.statements + } +} + +impl Display for IrBlock { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + writeln!(f, " {}", self.debug_label)?; + for statement in &self.statements { + writeln!(f, " {}", statement)?; + } + Ok(()) + } +} diff --git a/dmc-lib/src/ir/ir_call.rs b/dmc-lib/src/ir/ir_call.rs new file mode 100644 index 0000000..5338424 --- /dev/null +++ b/dmc-lib/src/ir/ir_call.rs @@ -0,0 +1,31 @@ +use crate::ir::ir_expression::IrExpression; +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +pub struct IrCall { + function_name: Rc, + arguments: Vec, +} + +impl IrCall { + pub fn new(function_name: Rc, arguments: Vec) -> Self { + Self { + function_name, + arguments, + } + } +} + +impl Display for IrCall { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}(", self.function_name)?; + for (i, argument) in self.arguments.iter().enumerate() { + write!(f, "{}", argument)?; + if i < self.arguments.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ")")?; + Ok(()) + } +} diff --git a/dmc-lib/src/ir/ir_expression.rs b/dmc-lib/src/ir/ir_expression.rs new file mode 100644 index 0000000..9e0b0ad --- /dev/null +++ b/dmc-lib/src/ir/ir_expression.rs @@ -0,0 +1,25 @@ +use crate::ir::ir_variable::IrVariable; +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +pub enum IrExpression { + Variable(IrVariable), + Int(i32), + String(Rc), +} + +impl Display for IrExpression { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrExpression::Variable(ir_variable) => { + write!(f, "{}", ir_variable) + } + IrExpression::Int(i) => { + write!(f, "{}", i) + } + IrExpression::String(s) => { + write!(f, "\"{}\"", s) + } + } + } +} diff --git a/dmc-lib/src/ir/ir_function.rs b/dmc-lib/src/ir/ir_function.rs new file mode 100644 index 0000000..919a21a --- /dev/null +++ b/dmc-lib/src/ir/ir_function.rs @@ -0,0 +1,22 @@ +use crate::ir::ir_block::IrBlock; +use std::cell::RefCell; +use std::fmt::Display; +use std::rc::Rc; + +pub struct IrFunction { + name: Rc, + entry: Rc>, +} + +impl IrFunction { + pub fn new(name: Rc, entry: Rc>) -> Self { + Self { name, entry } + } +} + +impl Display for IrFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "fn {}\n{}", self.name, self.entry.borrow())?; + Ok(()) + } +} diff --git a/dmc-lib/src/ir/ir_operation.rs b/dmc-lib/src/ir/ir_operation.rs new file mode 100644 index 0000000..cac9be5 --- /dev/null +++ b/dmc-lib/src/ir/ir_operation.rs @@ -0,0 +1,26 @@ +use crate::ir::ir_add::IrAdd; +use crate::ir::ir_call::IrCall; +use crate::ir::ir_expression::IrExpression; +use std::fmt::{Display, Formatter}; + +pub enum IrOperation { + Load(IrExpression), + Add(IrAdd), + Call(IrCall), +} + +impl Display for IrOperation { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrOperation::Load(ir_expression) => { + write!(f, "{}", ir_expression) + } + IrOperation::Add(ir_add) => { + write!(f, "{}", ir_add) + } + IrOperation::Call(ir_call) => { + write!(f, "{}", ir_call) + } + } + } +} diff --git a/dmc-lib/src/ir/ir_return.rs b/dmc-lib/src/ir/ir_return.rs new file mode 100644 index 0000000..fcf0332 --- /dev/null +++ b/dmc-lib/src/ir/ir_return.rs @@ -0,0 +1,22 @@ +use crate::ir::ir_expression::IrExpression; +use std::fmt::{Display, Formatter}; + +pub struct IrReturn { + value: Option, +} + +impl IrReturn { + pub fn new(value: Option) -> Self { + Self { value } + } +} + +impl Display for IrReturn { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "return")?; + if let Some(value) = &self.value { + write!(f, " {}", value)?; + } + Ok(()) + } +} diff --git a/dmc-lib/src/ir/ir_statement.rs b/dmc-lib/src/ir/ir_statement.rs new file mode 100644 index 0000000..128b9a5 --- /dev/null +++ b/dmc-lib/src/ir/ir_statement.rs @@ -0,0 +1,26 @@ +use crate::ir::ir_assign::IrAssign; +use crate::ir::ir_call::IrCall; +use crate::ir::ir_return::IrReturn; +use std::fmt::{Display, Formatter}; + +pub enum IrStatement { + Assign(IrAssign), + Call(IrCall), + Return(IrReturn), +} + +impl Display for IrStatement { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + IrStatement::Assign(ir_assign) => { + write!(f, "{}", ir_assign) + } + IrStatement::Call(ir_call) => { + write!(f, "{}", ir_call) + } + IrStatement::Return(ir_return) => { + write!(f, "{}", ir_return) + } + } + } +} diff --git a/dmc-lib/src/ir/ir_variable.rs b/dmc-lib/src/ir/ir_variable.rs new file mode 100644 index 0000000..5180c21 --- /dev/null +++ b/dmc-lib/src/ir/ir_variable.rs @@ -0,0 +1,19 @@ +use std::fmt::{Display, Formatter}; +use std::rc::Rc; + +#[derive(Clone)] +pub struct IrVariable { + name: Rc, +} + +impl IrVariable { + pub fn new(name: &str) -> Self { + Self { name: name.into() } + } +} + +impl Display for IrVariable { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } +} diff --git a/dmc-lib/src/ir/mod.rs b/dmc-lib/src/ir/mod.rs new file mode 100644 index 0000000..ecf90dc --- /dev/null +++ b/dmc-lib/src/ir/mod.rs @@ -0,0 +1,10 @@ +pub mod ir_add; +pub mod ir_assign; +pub mod ir_block; +pub mod ir_call; +pub mod ir_expression; +pub mod ir_function; +pub mod ir_operation; +pub mod ir_return; +pub mod ir_statement; +pub mod ir_variable; diff --git a/dmc-lib/src/lib.rs b/dmc-lib/src/lib.rs index 2b90830..5578421 100644 --- a/dmc-lib/src/lib.rs +++ b/dmc-lib/src/lib.rs @@ -2,6 +2,7 @@ pub mod asm; pub mod ast; pub mod constants_table; pub mod diagnostic; +pub mod ir; pub mod lexer; pub mod parser; pub mod scope;