Re-introduce ir with goal of doing register allocation.
This commit is contained in:
parent
cfff03e97d
commit
15089a15d2
@ -4,6 +4,7 @@ use codespan_reporting::files::SimpleFiles;
|
|||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
use dm_std_lib::add_all_std_core;
|
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::constants_table::ConstantsTable;
|
||||||
use dmc_lib::diagnostic::Diagnostic;
|
use dmc_lib::diagnostic::Diagnostic;
|
||||||
use dmc_lib::parser::parse_compilation_unit;
|
use dmc_lib::parser::parse_compilation_unit;
|
||||||
@ -21,6 +22,9 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
show_asm: bool,
|
show_asm: bool,
|
||||||
|
|
||||||
|
#[arg(long)]
|
||||||
|
show_ir: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@ -50,6 +54,15 @@ fn main() {
|
|||||||
let type_check_diagnostics = compilation_unit.type_check(&symbol_table);
|
let type_check_diagnostics = compilation_unit.type_check(&symbol_table);
|
||||||
check_and_report_diagnostics(&files, script_file_id, &type_check_diagnostics);
|
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 mut constants_table = ConstantsTable::new();
|
||||||
let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table);
|
let asm_functions = compilation_unit.assemble(&symbol_table, &mut constants_table);
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,21 @@
|
|||||||
use crate::asm::asm_instruction::{Add, AsmInstruction, LoadConstant, Move, Operand, Pop};
|
use crate::asm::asm_instruction::{Add, AsmInstruction, LoadConstant, Move, Operand, Pop};
|
||||||
use crate::ast::assemble_context::AssembleContext;
|
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::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
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::source_range::SourceRange;
|
||||||
use crate::symbol::ExpressibleSymbol;
|
use crate::symbol::ExpressibleSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub struct AdditiveExpression {
|
pub struct AdditiveExpression {
|
||||||
lhs: Box<Expression>,
|
lhs: Box<Expression>,
|
||||||
@ -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(
|
fn assemble_side(
|
||||||
expression: &Expression,
|
expression: &Expression,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
52
dmc-lib/src/ast/ast_to_ir_util.rs
Normal file
52
dmc-lib/src/ast/ast_to_ir_util.rs
Normal file
@ -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<IrExpression> {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,13 +2,19 @@ use crate::asm::asm_instruction::{
|
|||||||
AsmInstruction, InvokePlatformStatic, InvokeStatic, LoadConstant, Operand, Push,
|
AsmInstruction, InvokePlatformStatic, InvokeStatic, LoadConstant, Operand, Push,
|
||||||
};
|
};
|
||||||
use crate::ast::assemble_context::AssembleContext;
|
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::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_call::IrCall;
|
||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::ExpressibleSymbol;
|
use crate::symbol::{ExpressibleSymbol, FunctionSymbol};
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
callee: Box<Expression>,
|
callee: Box<Expression>,
|
||||||
@ -121,6 +127,35 @@ impl Call {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_callee_symbol(&self) -> Rc<RefCell<FunctionSymbol>> {
|
||||||
|
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<IrExpression> = 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(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
@ -1,8 +1,12 @@
|
|||||||
use crate::asm::asm_instruction::{AsmInstruction, Pop, SetReturnValue};
|
use crate::asm::asm_instruction::{AsmInstruction, Pop, SetReturnValue};
|
||||||
use crate::ast::assemble_context::AssembleContext;
|
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::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_return::IrReturn;
|
||||||
|
use crate::ir::ir_statement::IrStatement;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
@ -36,6 +40,15 @@ impl ExpressionStatement {
|
|||||||
self.expression.type_check(symbol_table)
|
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(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
use crate::asm::asm_instruction::{AsmInstruction, Return};
|
use crate::asm::asm_instruction::{AsmInstruction, Return};
|
||||||
use crate::ast::assemble_context::AssembleContext;
|
use crate::ast::assemble_context::AssembleContext;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::ast::type_use::TypeUse;
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
@ -158,6 +160,19 @@ impl Function {
|
|||||||
diagnostics
|
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(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
80
dmc-lib/src/ast/ir_builder.rs
Normal file
80
dmc-lib/src/ast/ir_builder.rs
Normal file
@ -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<usize, Rc<RefCell<IrBlock>>>,
|
||||||
|
current_block_builder: Option<IrBlockBuilder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<RefCell<IrBlock>> {
|
||||||
|
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<IrStatement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,20 @@
|
|||||||
use crate::asm::asm_instruction::{AsmInstruction, LoadConstant, Move, Operand, Pop};
|
use crate::asm::asm_instruction::{AsmInstruction, LoadConstant, Move, Operand, Pop};
|
||||||
use crate::ast::assemble_context::AssembleContext;
|
use crate::ast::assemble_context::AssembleContext;
|
||||||
use crate::ast::expression::Expression;
|
use crate::ast::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
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::source_range::SourceRange;
|
||||||
use crate::symbol::{ExpressibleSymbol, VariableSymbol};
|
use crate::symbol::{ExpressibleSymbol, VariableSymbol};
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
|
use std::process::id;
|
||||||
|
|
||||||
pub struct LetStatement {
|
pub struct LetStatement {
|
||||||
declared_name: String,
|
declared_name: String,
|
||||||
@ -81,6 +90,33 @@ impl LetStatement {
|
|||||||
vec![]
|
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(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
pub mod additive_expression;
|
pub mod additive_expression;
|
||||||
pub mod assemble_context;
|
pub mod assemble_context;
|
||||||
|
mod ast_to_ir_util;
|
||||||
pub mod call;
|
pub mod call;
|
||||||
pub mod compilation_unit;
|
pub mod compilation_unit;
|
||||||
pub mod expression;
|
pub mod expression;
|
||||||
@ -9,6 +10,7 @@ pub mod fqn;
|
|||||||
pub mod function;
|
pub mod function;
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub mod integer_literal;
|
pub mod integer_literal;
|
||||||
|
mod ir_builder;
|
||||||
pub mod let_statement;
|
pub mod let_statement;
|
||||||
pub mod module_level_declaration;
|
pub mod module_level_declaration;
|
||||||
pub mod parameter;
|
pub mod parameter;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use crate::ast::assemble_context::AssembleContext;
|
use crate::ast::assemble_context::AssembleContext;
|
||||||
use crate::ast::expression_statement::ExpressionStatement;
|
use crate::ast::expression_statement::ExpressionStatement;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
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(
|
pub fn assemble(
|
||||||
&self,
|
&self,
|
||||||
context: &mut AssembleContext,
|
context: &mut AssembleContext,
|
||||||
|
|||||||
22
dmc-lib/src/ir/ir_add.rs
Normal file
22
dmc-lib/src/ir/ir_add.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
pub struct IrAdd {
|
||||||
|
left: Box<IrExpression>,
|
||||||
|
right: Box<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
23
dmc-lib/src/ir/ir_assign.rs
Normal file
23
dmc-lib/src/ir/ir_assign.rs
Normal file
@ -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<IrVariable>,
|
||||||
|
initializer: Box<IrOperation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
42
dmc-lib/src/ir/ir_block.rs
Normal file
42
dmc-lib/src/ir/ir_block.rs
Normal file
@ -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<Rc<RefCell<IrBlock>>>,
|
||||||
|
successors: Vec<Rc<RefCell<IrBlock>>>,
|
||||||
|
statements: Vec<IrStatement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrBlock {
|
||||||
|
pub fn new(id: usize, debug_label: &str, statements: Vec<IrStatement>) -> 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
31
dmc-lib/src/ir/ir_call.rs
Normal file
31
dmc-lib/src/ir/ir_call.rs
Normal file
@ -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<str>,
|
||||||
|
arguments: Vec<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrCall {
|
||||||
|
pub fn new(function_name: Rc<str>, arguments: Vec<IrExpression>) -> 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
25
dmc-lib/src/ir/ir_expression.rs
Normal file
25
dmc-lib/src/ir/ir_expression.rs
Normal file
@ -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<str>),
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
dmc-lib/src/ir/ir_function.rs
Normal file
22
dmc-lib/src/ir/ir_function.rs
Normal file
@ -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<str>,
|
||||||
|
entry: Rc<RefCell<IrBlock>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrFunction {
|
||||||
|
pub fn new(name: Rc<str>, entry: Rc<RefCell<IrBlock>>) -> 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
26
dmc-lib/src/ir/ir_operation.rs
Normal file
26
dmc-lib/src/ir/ir_operation.rs
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
dmc-lib/src/ir/ir_return.rs
Normal file
22
dmc-lib/src/ir/ir_return.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
pub struct IrReturn {
|
||||||
|
value: Option<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrReturn {
|
||||||
|
pub fn new(value: Option<IrExpression>) -> 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
26
dmc-lib/src/ir/ir_statement.rs
Normal file
26
dmc-lib/src/ir/ir_statement.rs
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
dmc-lib/src/ir/ir_variable.rs
Normal file
19
dmc-lib/src/ir/ir_variable.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct IrVariable {
|
||||||
|
name: Rc<str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
10
dmc-lib/src/ir/mod.rs
Normal file
10
dmc-lib/src/ir/mod.rs
Normal file
@ -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;
|
||||||
@ -2,6 +2,7 @@ pub mod asm;
|
|||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod constants_table;
|
pub mod constants_table;
|
||||||
pub mod diagnostic;
|
pub mod diagnostic;
|
||||||
|
pub mod ir;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod scope;
|
pub mod scope;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user