Giving more info to ir.

This commit is contained in:
Jesse Brault 2026-03-05 16:30:39 -06:00
parent 15089a15d2
commit c91bb35d8d
10 changed files with 186 additions and 36 deletions

View File

@ -5,6 +5,7 @@ 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::ExpressibleSymbol;
use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo;
@ -22,12 +23,13 @@ pub fn expression_to_ir_expression(
.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));
let t_var = IrVariable::new(&builder.new_t_var(), call.type_info());
let assign = IrAssign::new(t_var, IrOperation::Call(ir_call));
let destination = assign.destination().clone();
builder
.current_block_mut()
.add_statement(IrStatement::Assign(assign));
Some(IrExpression::Variable(t_var))
Some(IrExpression::Variable(destination))
}
}
Expression::IntegerLiteral(integer_literal) => {
@ -36,17 +38,19 @@ pub fn expression_to_ir_expression(
Expression::String(string_literal) => {
Some(IrExpression::String(string_literal.content().into()))
}
Expression::Identifier(identifier) => Some(IrExpression::Variable(IrVariable::new(
identifier.name().into(),
))),
Expression::Identifier(identifier) => {
let expressible_symbol = identifier.expressible_symbol();
Some(IrExpression::Variable(expressible_symbol.ir_variable()))
}
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));
let t_var = IrVariable::new(&builder.new_t_var(), additive_expression.type_info());
let assign = IrAssign::new(t_var, IrOperation::Add(ir_add));
let destination = assign.destination().clone();
builder
.current_block_mut()
.add_statement(IrStatement::Assign(assign));
Some(IrExpression::Variable(t_var))
Some(IrExpression::Variable(destination))
}
}
}

View File

@ -7,6 +7,7 @@ use crate::ast::type_use::TypeUse;
use crate::constants_table::ConstantsTable;
use crate::diagnostic::Diagnostic;
use crate::ir::ir_function::IrFunction;
use crate::ir::ir_variable::IrVariable;
use crate::source_range::SourceRange;
use crate::symbol::FunctionSymbol;
use crate::symbol_table::{SymbolInsertError, SymbolTable};
@ -162,6 +163,19 @@ impl Function {
pub fn to_ir(&self, symbol_table: &SymbolTable) -> IrFunction {
let mut builder = IrBuilder::new();
// parameters
for parameter in &self.parameters {
let parameter_symbol = parameter.parameter_symbol();
let ir_variable = IrVariable::new(
parameter_symbol.borrow().name(),
parameter_symbol.borrow().type_info().clone(),
);
let as_rc = Rc::new(RefCell::new(ir_variable));
builder.parameters_mut().push(as_rc.clone());
parameter_symbol.borrow_mut().set_ir_variable(as_rc);
}
let entry_block_id = builder.new_block();
for (i, statement) in self.statements.iter().enumerate() {
let is_last = i == self.statements.len() - 1;
@ -169,8 +183,18 @@ impl Function {
}
builder.finish_block();
let entry_block = builder.get_block(entry_block_id);
IrFunction::new(Rc::from(self.declared_name()), entry_block.clone())
let return_type_info = self
.return_type
.as_ref()
.map(|return_type| return_type.to_type_info())
.unwrap_or(TypeInfo::Void);
let entry_block = builder.get_block(entry_block_id).clone();
IrFunction::new(
Rc::from(self.declared_name()),
builder.parameters(),
return_type_info,
entry_block,
)
}
pub fn assemble(

View File

@ -1,10 +1,12 @@
use crate::ir::ir_block::IrBlock;
use crate::ir::ir_statement::IrStatement;
use crate::ir::ir_variable::IrVariable;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
pub struct IrBuilder {
parameters: Vec<Rc<RefCell<IrVariable>>>,
block_counter: usize,
t_var_counter: usize,
blocks: HashMap<usize, Rc<RefCell<IrBlock>>>,
@ -14,6 +16,7 @@ pub struct IrBuilder {
impl IrBuilder {
pub fn new() -> Self {
Self {
parameters: vec![],
block_counter: 0,
t_var_counter: 0,
blocks: HashMap::new(),
@ -21,6 +24,14 @@ impl IrBuilder {
}
}
pub fn parameters(&self) -> &[Rc<RefCell<IrVariable>>] {
&self.parameters
}
pub fn parameters_mut(&mut self) -> &mut Vec<Rc<RefCell<IrVariable>>> {
&mut self.parameters
}
pub fn new_block(&mut self) -> usize {
let block_id = self.block_counter;
self.block_counter += 1;

View File

@ -4,9 +4,7 @@ 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;
@ -14,7 +12,6 @@ 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,
@ -99,22 +96,28 @@ impl LetStatement {
Expression::String(string_literal) => {
IrOperation::Load(IrExpression::String(string_literal.content().into()))
}
Expression::Identifier(identifier) => {
IrOperation::Load(IrExpression::Variable(IrVariable::new(identifier.name())))
}
Expression::Identifier(identifier) => IrOperation::Load(IrExpression::Variable(
identifier.expressible_symbol().ir_variable(),
)),
Expression::Additive(additive_expression) => {
IrOperation::Add(additive_expression.to_ir(builder, symbol_table))
}
};
let destination_variable = IrVariable::new(self.declared_name());
let destination_symbol =
symbol_table.get_variable_symbol(self.scope_id.unwrap(), &self.declared_name);
let ir_assign = IrAssign::new(
IrVariable::new(self.declared_name(), self.initializer().type_info()),
init_operation,
);
let destination_ir_variable = ir_assign.destination();
destination_symbol
.borrow_mut()
.set_ir_variable(destination_ir_variable.clone());
builder
.current_block_mut()
.add_statement(IrStatement::Assign(IrAssign::new(
destination_variable,
init_operation,
)))
.add_statement(IrStatement::Assign(ir_assign));
}
pub fn assemble(

View File

@ -11,6 +11,7 @@ pub struct Parameter {
declared_name: String,
declared_name_source_range: SourceRange,
type_use: TypeUse,
parameter_symbol: Option<Rc<RefCell<ParameterSymbol>>>,
}
impl Parameter {
@ -23,6 +24,7 @@ impl Parameter {
declared_name: declared_name.into(),
declared_name_source_range,
type_use,
parameter_symbol: None,
}
}
@ -35,7 +37,10 @@ impl Parameter {
TypeInfo::from_declared_name(self.type_use.declared_name()),
));
match insert_result {
Ok(parameter_symbol) => Ok(parameter_symbol),
Ok(parameter_symbol) => {
self.parameter_symbol = Some(parameter_symbol.clone());
Ok(parameter_symbol)
}
Err(symbol_insert_error) => match symbol_insert_error {
SymbolInsertError::AlreadyDeclared(already_declared) => Err(vec![Diagnostic::new(
&format!("Parameter {} already declared.", already_declared.name()),
@ -46,11 +51,20 @@ impl Parameter {
}
}
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
pub fn check_name_usages(
&mut self,
_symbol_table: &SymbolTable,
) -> Result<(), Vec<Diagnostic>> {
Ok(()) // no-op for now
}
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
pub fn type_check(&mut self, _symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
Ok(()) // no-op for now
}
pub fn parameter_symbol(&self) -> &Rc<RefCell<ParameterSymbol>> {
self.parameter_symbol
.as_ref()
.expect("parameter symbol not initialized")
}
}

View File

@ -1,23 +1,35 @@
use crate::ir::ir_operation::IrOperation;
use crate::ir::ir_variable::IrVariable;
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
pub struct IrAssign {
destination: Box<IrVariable>,
destination: Rc<RefCell<IrVariable>>,
initializer: Box<IrOperation>,
}
impl IrAssign {
pub fn new(destination: IrVariable, initializer: IrOperation) -> Self {
Self {
destination: destination.into(),
destination: Rc::new(RefCell::new(destination)),
initializer: initializer.into(),
}
}
pub fn destination(&self) -> &Rc<RefCell<IrVariable>> {
&self.destination
}
}
impl Display for IrAssign {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} = {}", self.destination, self.initializer)
write!(
f,
"{}: {} = {}",
self.destination.borrow(),
self.destination.borrow().type_info(),
self.initializer
)
}
}

View File

@ -1,9 +1,10 @@
use crate::ir::ir_variable::IrVariable;
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
pub enum IrExpression {
Variable(IrVariable),
Variable(Rc<RefCell<IrVariable>>),
Int(i32),
String(Rc<str>),
}
@ -12,7 +13,7 @@ impl Display for IrExpression {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
IrExpression::Variable(ir_variable) => {
write!(f, "{}", ir_variable)
write!(f, "{}", ir_variable.borrow())
}
IrExpression::Int(i) => {
write!(f, "{}", i)

View File

@ -1,22 +1,48 @@
use crate::ir::ir_block::IrBlock;
use crate::ir::ir_variable::IrVariable;
use crate::type_info::TypeInfo;
use std::cell::RefCell;
use std::fmt::Display;
use std::rc::Rc;
pub struct IrFunction {
name: Rc<str>,
parameters: Vec<Rc<RefCell<IrVariable>>>,
return_type_info: TypeInfo,
entry: Rc<RefCell<IrBlock>>,
}
impl IrFunction {
pub fn new(name: Rc<str>, entry: Rc<RefCell<IrBlock>>) -> Self {
Self { name, entry }
pub fn new(
name: Rc<str>,
parameters: &[Rc<RefCell<IrVariable>>],
return_type_info: TypeInfo,
entry: Rc<RefCell<IrBlock>>,
) -> Self {
Self {
name,
parameters: parameters.to_vec(),
return_type_info,
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())?;
write!(f, "fn {}(", self.name)?;
for (i, parameter) in self.parameters.iter().enumerate() {
write!(
f,
"{}: {}",
parameter.borrow(),
parameter.borrow().type_info()
)?;
if i < self.parameters.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ") -> {}\n{}", self.return_type_info, self.entry.borrow())?;
Ok(())
}
}

View File

@ -1,14 +1,22 @@
use crate::type_info::TypeInfo;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
#[derive(Clone)]
pub struct IrVariable {
name: Rc<str>,
type_info: TypeInfo,
}
impl IrVariable {
pub fn new(name: &str) -> Self {
Self { name: name.into() }
pub fn new(name: &str, type_info: TypeInfo) -> Self {
Self {
name: name.into(),
type_info,
}
}
pub fn type_info(&self) -> &TypeInfo {
&self.type_info
}
}

View File

@ -1,3 +1,4 @@
use crate::ir::ir_variable::IrVariable;
use crate::type_info::TypeInfo;
use std::cell::RefCell;
use std::rc::Rc;
@ -47,6 +48,9 @@ impl FunctionSymbol {
pub struct ParameterSymbol {
name: Rc<str>,
type_info: TypeInfo,
ir_variable: Option<Rc<RefCell<IrVariable>>>,
#[deprecated]
stack_frame_offset: Option<isize>,
}
@ -55,6 +59,7 @@ impl ParameterSymbol {
Self {
name: name.into(),
type_info,
ir_variable: None,
stack_frame_offset: None,
}
}
@ -71,10 +76,22 @@ impl ParameterSymbol {
&self.type_info
}
pub fn set_ir_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
self.ir_variable = Some(ir_variable);
}
pub fn ir_variable(&self) -> &Rc<RefCell<IrVariable>> {
self.ir_variable
.as_ref()
.expect("ir_variable not yet initialized")
}
#[deprecated]
pub fn set_stack_frame_offset(&mut self, offset: isize) {
self.stack_frame_offset = Some(offset);
}
#[deprecated]
pub fn stack_frame_offset(&self) -> isize {
self.stack_frame_offset.unwrap()
}
@ -83,6 +100,9 @@ impl ParameterSymbol {
pub struct VariableSymbol {
name: Rc<str>,
type_info: Option<TypeInfo>,
ir_variable: Option<Rc<RefCell<IrVariable>>>,
#[deprecated]
register: Option<usize>,
}
@ -91,6 +111,7 @@ impl VariableSymbol {
Self {
name: name.into(),
type_info: None,
ir_variable: None,
register: None,
}
}
@ -113,6 +134,16 @@ impl VariableSymbol {
.expect("TypeInfo not initialized. Did you type check?")
}
pub fn set_ir_variable(&mut self, ir_variable: Rc<RefCell<IrVariable>>) {
self.ir_variable = Some(ir_variable);
}
pub fn ir_variable(&self) -> &Rc<RefCell<IrVariable>> {
self.ir_variable
.as_ref()
.expect("ir_variable not yet initialized")
}
pub fn set_register(&mut self, register: usize) {
self.register = Some(register);
}
@ -127,3 +158,19 @@ pub enum ExpressibleSymbol {
Parameter(Rc<RefCell<ParameterSymbol>>),
Variable(Rc<RefCell<VariableSymbol>>),
}
impl ExpressibleSymbol {
pub fn ir_variable(&self) -> Rc<RefCell<IrVariable>> {
match self {
ExpressibleSymbol::Function(_) => {
panic!("Cannot get ir_variable for FunctionSymbol");
}
ExpressibleSymbol::Parameter(parameter_symbol) => {
parameter_symbol.borrow().ir_variable().clone()
}
ExpressibleSymbol::Variable(variable_symbol) => {
variable_symbol.borrow().ir_variable().clone()
}
}
}
}