Assign statements ir and fixing some things.
This commit is contained in:
parent
7e613b1b90
commit
5a123419bd
@ -114,7 +114,7 @@ fn compile_expression(
|
|||||||
let mut ir_builder = IrBuilder::new();
|
let mut ir_builder = IrBuilder::new();
|
||||||
let entry_block_id = ir_builder.new_block();
|
let entry_block_id = ir_builder.new_block();
|
||||||
|
|
||||||
let maybe_ir_expression = expression.to_ir(&mut ir_builder, &symbol_table);
|
let maybe_ir_expression = expression.to_ir_expression(&mut ir_builder, &symbol_table);
|
||||||
|
|
||||||
// if Some, return the value
|
// if Some, return the value
|
||||||
ir_builder
|
ir_builder
|
||||||
|
|||||||
@ -83,11 +83,11 @@ impl AddExpression {
|
|||||||
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrAdd {
|
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrAdd {
|
||||||
let lhs_ir_expression = self
|
let lhs_ir_expression = self
|
||||||
.lhs
|
.lhs
|
||||||
.to_ir(builder, symbol_table)
|
.to_ir_expression(builder, symbol_table)
|
||||||
.expect("Attempt to add non-expression");
|
.expect("Attempt to add non-expression");
|
||||||
let rhs_ir_expression = self
|
let rhs_ir_expression = self
|
||||||
.rhs
|
.rhs
|
||||||
.to_ir(builder, symbol_table)
|
.to_ir_expression(builder, symbol_table)
|
||||||
.expect("Attempt to add non-expression");
|
.expect("Attempt to add non-expression");
|
||||||
IrAdd::new(lhs_ir_expression, rhs_ir_expression)
|
IrAdd::new(lhs_ir_expression, rhs_ir_expression)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
use crate::ast::expression::Expression;
|
use crate::ast::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
|
use crate::ast::ir_util::get_or_init_mut_field_pointer_variable;
|
||||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||||
use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE};
|
use crate::error_codes::{ASSIGN_LHS_IMMUTABLE, ASSIGN_MISMATCHED_TYPES, ASSIGN_NO_L_VALUE};
|
||||||
|
use crate::ir::ir_assign::IrAssign;
|
||||||
|
use crate::ir::ir_set_field::IrSetField;
|
||||||
|
use crate::ir::ir_statement::IrStatement;
|
||||||
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
|
|
||||||
pub struct AssignStatement {
|
pub struct AssignStatement {
|
||||||
@ -157,6 +163,38 @@ impl AssignStatement {
|
|||||||
Err(diagnostics)
|
Err(diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) {
|
||||||
|
let destination_symbol = match &*self.destination {
|
||||||
|
Expression::Identifier(identifier) => identifier.expressible_symbol(),
|
||||||
|
_ => unreachable!("Destination must be a mutable L value"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let ir_statement = match destination_symbol {
|
||||||
|
ExpressibleSymbol::Field(field_symbol) => {
|
||||||
|
let mut_field_pointer_variable =
|
||||||
|
get_or_init_mut_field_pointer_variable(builder, field_symbol).clone();
|
||||||
|
let ir_set_field = IrSetField::new(
|
||||||
|
&mut_field_pointer_variable,
|
||||||
|
self.value
|
||||||
|
.to_ir_expression(builder, symbol_table)
|
||||||
|
.expect("Attempt to convert non-value to value"),
|
||||||
|
);
|
||||||
|
IrStatement::SetField(ir_set_field)
|
||||||
|
}
|
||||||
|
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||||
|
let vr_variable = variable_symbol.borrow().vr_variable().clone();
|
||||||
|
let ir_assign = IrAssign::new(
|
||||||
|
vr_variable,
|
||||||
|
self.value.to_ir_operation(builder, symbol_table),
|
||||||
|
);
|
||||||
|
IrStatement::Assign(ir_assign)
|
||||||
|
}
|
||||||
|
_ => unreachable!("Destination must be a mutable L value"),
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.current_block_mut().add_statement(ir_statement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::diagnostic::Diagnostic;
|
|||||||
use crate::ir::ir_call::IrCall;
|
use crate::ir::ir_call::IrCall;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
use crate::symbol::Symbol;
|
|
||||||
use crate::symbol::callable_symbol::CallableSymbol;
|
use crate::symbol::callable_symbol::CallableSymbol;
|
||||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
@ -176,7 +175,7 @@ impl Call {
|
|||||||
let arguments: Vec<IrExpression> = self
|
let arguments: Vec<IrExpression> = self
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|argument| argument.to_ir(builder, symbol_table))
|
.map(|argument| argument.to_ir_expression(builder, symbol_table))
|
||||||
.inspect(|expression| {
|
.inspect(|expression| {
|
||||||
if expression.is_none() {
|
if expression.is_none() {
|
||||||
panic!("Attempt to pass non-expression")
|
panic!("Attempt to pass non-expression")
|
||||||
|
|||||||
@ -200,13 +200,19 @@ impl Constructor {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, parameter)| {
|
.map(|(i, parameter)| {
|
||||||
let parameter_symbol = parameter.parameter_symbol().borrow();
|
let mut parameter_symbol = parameter.parameter_symbol().borrow_mut();
|
||||||
let offset = (parameters_count as isize).neg() + i as isize;
|
let offset = (parameters_count as isize).neg() + i as isize;
|
||||||
Rc::new(IrParameter::new(
|
let ir_parameter = Rc::new(IrParameter::new(
|
||||||
parameter_symbol.declared_name(),
|
parameter_symbol.declared_name(),
|
||||||
parameter_symbol.type_info().clone(),
|
parameter_symbol.type_info().clone(),
|
||||||
offset,
|
offset,
|
||||||
))
|
));
|
||||||
|
|
||||||
|
// make sure to save ir_parameter to symbol so others can access it
|
||||||
|
let to_save = ir_parameter.clone();
|
||||||
|
parameter_symbol.set_ir_parameter(to_save);
|
||||||
|
|
||||||
|
ir_parameter
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -219,6 +225,11 @@ impl Constructor {
|
|||||||
&TypeInfo::ClassInstance(class_symbol.clone()),
|
&TypeInfo::ClassInstance(class_symbol.clone()),
|
||||||
);
|
);
|
||||||
let self_variable = Rc::new(RefCell::new(alloc_assign_destination));
|
let self_variable = Rc::new(RefCell::new(alloc_assign_destination));
|
||||||
|
|
||||||
|
// save self variable so statements can assign stuff to self's fields
|
||||||
|
ir_builder
|
||||||
|
.set_self_parameter_or_variable(IrParameterOrVariable::Variable(self_variable.clone()));
|
||||||
|
|
||||||
let alloc_assign = IrAssign::new(
|
let alloc_assign = IrAssign::new(
|
||||||
self_variable.clone(),
|
self_variable.clone(),
|
||||||
IrOperation::Allocate(IrAllocate::new(class_symbol.borrow().declared_name_owned())),
|
IrOperation::Allocate(IrAllocate::new(class_symbol.borrow().declared_name_owned())),
|
||||||
@ -252,16 +263,18 @@ impl Constructor {
|
|||||||
// save the mut ref to the builder for other uses if needed
|
// save the mut ref to the builder for other uses if needed
|
||||||
ir_builder
|
ir_builder
|
||||||
.field_mut_pointer_variables_mut()
|
.field_mut_pointer_variables_mut()
|
||||||
.insert(field_mut_ref_variable_name.clone(), field_mut_ref_variable);
|
.insert(field.declared_name_owned(), field_mut_ref_variable); // n.b. field name, not t var name
|
||||||
|
|
||||||
// now write the initializer result to the field
|
// now write the initializer result to the field
|
||||||
let field_mut_ref_variable = ir_builder
|
let field_mut_ref_variable = ir_builder
|
||||||
.field_mut_pointer_variables()
|
.field_mut_pointer_variables()
|
||||||
.get(&field_mut_ref_variable_name)
|
.get(field.declared_name())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let ir_expression = initializer.to_ir(&mut ir_builder, symbol_table).unwrap();
|
let ir_expression = initializer
|
||||||
|
.to_ir_expression(&mut ir_builder, symbol_table)
|
||||||
|
.unwrap();
|
||||||
let ir_set_field = IrSetField::new(
|
let ir_set_field = IrSetField::new(
|
||||||
&field_mut_ref_variable, // dumb that we clone it and then ref it
|
&field_mut_ref_variable, // dumb that we clone it and then ref it
|
||||||
ir_expression,
|
ir_expression,
|
||||||
@ -272,6 +285,11 @@ impl Constructor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do "declared" statements of constructor
|
||||||
|
for statement in &self.statements {
|
||||||
|
statement.to_ir(&mut ir_builder, symbol_table, false);
|
||||||
|
}
|
||||||
|
|
||||||
// return complete self object
|
// return complete self object
|
||||||
let ir_return_statement = IrStatement::Return(IrReturn::new(Some(IrExpression::Variable(
|
let ir_return_statement = IrStatement::Return(IrReturn::new(Some(IrExpression::Variable(
|
||||||
self_variable.clone(),
|
self_variable.clone(),
|
||||||
|
|||||||
@ -111,7 +111,38 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(
|
pub fn to_ir_operation(
|
||||||
|
&self,
|
||||||
|
builder: &mut IrBuilder,
|
||||||
|
symbol_table: &SymbolTable,
|
||||||
|
) -> IrOperation {
|
||||||
|
match self {
|
||||||
|
Expression::Call(call) => IrOperation::Call(call.to_ir(builder, symbol_table)),
|
||||||
|
Expression::Integer(integer_literal) => {
|
||||||
|
IrOperation::Load(IrExpression::Int(integer_literal.value()))
|
||||||
|
}
|
||||||
|
Expression::Double(double_literal) => {
|
||||||
|
IrOperation::Load(IrExpression::Double(double_literal.value()))
|
||||||
|
}
|
||||||
|
Expression::String(string_literal) => {
|
||||||
|
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
||||||
|
}
|
||||||
|
Expression::Identifier(identifier) => {
|
||||||
|
IrOperation::Load(identifier.expressible_symbol().ir_expression(builder))
|
||||||
|
}
|
||||||
|
Expression::Add(additive_expression) => {
|
||||||
|
IrOperation::Add(additive_expression.to_ir(builder, symbol_table))
|
||||||
|
}
|
||||||
|
Expression::Subtract(subtract_expression) => {
|
||||||
|
IrOperation::Subtract(subtract_expression.to_ir_subtract(builder, symbol_table))
|
||||||
|
}
|
||||||
|
Expression::Negative(negative_expression) => {
|
||||||
|
IrOperation::Load(negative_expression.to_ir(builder, symbol_table))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ir_expression(
|
||||||
&self,
|
&self,
|
||||||
builder: &mut IrBuilder,
|
builder: &mut IrBuilder,
|
||||||
symbol_table: &SymbolTable,
|
symbol_table: &SymbolTable,
|
||||||
|
|||||||
@ -62,7 +62,7 @@ impl ExpressionStatement {
|
|||||||
symbol_table: &SymbolTable,
|
symbol_table: &SymbolTable,
|
||||||
should_return_value: bool,
|
should_return_value: bool,
|
||||||
) {
|
) {
|
||||||
let ir_expression = self.expression.to_ir(builder, symbol_table);
|
let ir_expression = self.expression.to_ir_expression(builder, symbol_table);
|
||||||
if ir_expression.is_some() && should_return_value {
|
if ir_expression.is_some() && should_return_value {
|
||||||
builder
|
builder
|
||||||
.current_block_mut()
|
.current_block_mut()
|
||||||
|
|||||||
@ -42,6 +42,10 @@ impl Field {
|
|||||||
&self.declared_name
|
&self.declared_name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn declared_name_owned(&self) -> Rc<str> {
|
||||||
|
self.declared_name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn declared_name_source_range(&self) -> &SourceRange {
|
pub fn declared_name_source_range(&self) -> &SourceRange {
|
||||||
&self.declared_name_source_range
|
&self.declared_name_source_range
|
||||||
}
|
}
|
||||||
|
|||||||
83
dmc-lib/src/ast/ir_util.rs
Normal file
83
dmc-lib/src/ast/ir_util.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
|
use crate::ir::ir_assign::IrAssign;
|
||||||
|
use crate::ir::ir_get_field_ref::IrGetFieldRef;
|
||||||
|
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
|
||||||
|
use crate::ir::ir_operation::IrOperation;
|
||||||
|
use crate::ir::ir_statement::IrStatement;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use crate::symbol::Symbol;
|
||||||
|
use crate::symbol::field_symbol::FieldSymbol;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub fn get_or_init_field_pointer_variable<'a>(
|
||||||
|
builder: &'a mut IrBuilder,
|
||||||
|
field_symbol: &Rc<RefCell<FieldSymbol>>,
|
||||||
|
) -> &'a Rc<RefCell<IrVariable>> {
|
||||||
|
// This following should work because blocks are flat in the ir; if a variable is defined in the
|
||||||
|
// ir block from this point forward, it's available to all subsequent blocks.
|
||||||
|
if !builder
|
||||||
|
.field_pointer_variables()
|
||||||
|
.contains_key(field_symbol.borrow().declared_name())
|
||||||
|
{
|
||||||
|
let field_ref_variable = IrVariable::new_vr(
|
||||||
|
builder.new_t_var().into(),
|
||||||
|
builder.current_block().id(),
|
||||||
|
field_symbol.borrow().type_info(),
|
||||||
|
);
|
||||||
|
let as_rc = Rc::new(RefCell::new(field_ref_variable));
|
||||||
|
let to_insert = as_rc.clone();
|
||||||
|
let self_parameter_or_variable = builder.self_parameter_or_variable().clone();
|
||||||
|
builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Assign(IrAssign::new(
|
||||||
|
as_rc,
|
||||||
|
IrOperation::GetFieldRef(IrGetFieldRef::new(
|
||||||
|
self_parameter_or_variable.clone(),
|
||||||
|
field_symbol.borrow().field_index(),
|
||||||
|
)),
|
||||||
|
)));
|
||||||
|
builder
|
||||||
|
.field_pointer_variables_mut()
|
||||||
|
.insert(field_symbol.borrow().declared_name_owned(), to_insert);
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.field_pointer_variables()
|
||||||
|
.get(field_symbol.borrow().declared_name())
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_init_mut_field_pointer_variable<'a>(
|
||||||
|
builder: &'a mut IrBuilder,
|
||||||
|
field_symbol: &Rc<RefCell<FieldSymbol>>,
|
||||||
|
) -> &'a Rc<RefCell<IrVariable>> {
|
||||||
|
if !builder
|
||||||
|
.field_mut_pointer_variables()
|
||||||
|
.contains_key(field_symbol.borrow().declared_name())
|
||||||
|
{
|
||||||
|
let mut_field_pointer_variable = IrVariable::new_vr(
|
||||||
|
builder.new_t_var().into(),
|
||||||
|
builder.current_block().id(),
|
||||||
|
field_symbol.borrow().type_info(),
|
||||||
|
);
|
||||||
|
let as_rc = Rc::new(RefCell::new(mut_field_pointer_variable));
|
||||||
|
let to_insert = as_rc.clone();
|
||||||
|
let self_parameter_or_variable = builder.self_parameter_or_variable().clone();
|
||||||
|
builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Assign(IrAssign::new(
|
||||||
|
as_rc,
|
||||||
|
IrOperation::GetFieldRefMut(IrGetFieldRefMut::new(
|
||||||
|
self_parameter_or_variable.clone(),
|
||||||
|
field_symbol.borrow().field_index(),
|
||||||
|
)),
|
||||||
|
)));
|
||||||
|
builder
|
||||||
|
.field_mut_pointer_variables_mut()
|
||||||
|
.insert(field_symbol.borrow().declared_name_owned(), to_insert);
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.field_mut_pointer_variables()
|
||||||
|
.get(field_symbol.borrow().declared_name())
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
@ -2,8 +2,6 @@ use crate::ast::expression::Expression;
|
|||||||
use crate::ast::ir_builder::IrBuilder;
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::ir::ir_assign::IrAssign;
|
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_statement::IrStatement;
|
||||||
use crate::ir::ir_variable::IrVariable;
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
@ -106,28 +104,7 @@ impl LetStatement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) {
|
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) {
|
||||||
let init_operation = match self.initializer() {
|
let init_operation = self.initializer.to_ir_operation(builder, symbol_table);
|
||||||
Expression::Call(call) => IrOperation::Call(call.to_ir(builder, symbol_table)),
|
|
||||||
Expression::Integer(integer_literal) => {
|
|
||||||
IrOperation::Load(IrExpression::Int(integer_literal.value()))
|
|
||||||
}
|
|
||||||
Expression::Double(double_literal) => {
|
|
||||||
IrOperation::Load(IrExpression::Double(double_literal.value()))
|
|
||||||
}
|
|
||||||
Expression::String(string_literal) => {
|
|
||||||
IrOperation::Load(IrExpression::String(string_literal.content().into()))
|
|
||||||
}
|
|
||||||
Expression::Identifier(identifier) => {
|
|
||||||
IrOperation::Load(identifier.expressible_symbol().ir_expression(builder))
|
|
||||||
}
|
|
||||||
Expression::Add(additive_expression) => {
|
|
||||||
IrOperation::Add(additive_expression.to_ir(builder, symbol_table))
|
|
||||||
}
|
|
||||||
Expression::Subtract(subtract_expression) => {
|
|
||||||
IrOperation::Subtract(subtract_expression.to_ir_subtract(builder, symbol_table))
|
|
||||||
}
|
|
||||||
Expression::Negative(_) => todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let destination_symbol =
|
let destination_symbol =
|
||||||
symbol_table.get_variable_symbol(self.scope_id.unwrap(), &self.declared_name);
|
symbol_table.get_variable_symbol(self.scope_id.unwrap(), &self.declared_name);
|
||||||
|
|||||||
@ -16,6 +16,7 @@ pub mod function;
|
|||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub mod integer_literal;
|
pub mod integer_literal;
|
||||||
pub mod ir_builder;
|
pub mod ir_builder;
|
||||||
|
pub(crate) mod ir_util;
|
||||||
pub mod let_statement;
|
pub mod let_statement;
|
||||||
pub mod negative_expression;
|
pub mod negative_expression;
|
||||||
pub mod parameter;
|
pub mod parameter;
|
||||||
|
|||||||
@ -70,7 +70,7 @@ impl NegativeExpression {
|
|||||||
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrExpression {
|
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrExpression {
|
||||||
let operand_as_ir = self
|
let operand_as_ir = self
|
||||||
.operand
|
.operand
|
||||||
.to_ir(builder, symbol_table)
|
.to_ir_expression(builder, symbol_table)
|
||||||
.expect("Attempt to negate non-value expression");
|
.expect("Attempt to negate non-value expression");
|
||||||
|
|
||||||
match operand_as_ir {
|
match operand_as_ir {
|
||||||
|
|||||||
@ -66,7 +66,7 @@ impl Statement {
|
|||||||
expression_statement.to_ir(builder, symbol_table, should_return_value);
|
expression_statement.to_ir(builder, symbol_table, should_return_value);
|
||||||
}
|
}
|
||||||
Statement::Assign(assign_statement) => {
|
Statement::Assign(assign_statement) => {
|
||||||
todo!()
|
assign_statement.to_ir(builder, symbol_table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,11 +105,11 @@ impl SubtractExpression {
|
|||||||
) -> IrSubtract {
|
) -> IrSubtract {
|
||||||
let lhs = self
|
let lhs = self
|
||||||
.lhs
|
.lhs
|
||||||
.to_ir(builder, symbol_table)
|
.to_ir_expression(builder, symbol_table)
|
||||||
.expect("Attempt to subtract non-expression");
|
.expect("Attempt to subtract non-expression");
|
||||||
let rhs = self
|
let rhs = self
|
||||||
.rhs
|
.rhs
|
||||||
.to_ir(builder, symbol_table)
|
.to_ir_expression(builder, symbol_table)
|
||||||
.expect("Attempt to subtract non-expression");
|
.expect("Attempt to subtract non-expression");
|
||||||
IrSubtract::new(lhs, rhs)
|
IrSubtract::new(lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,9 @@ impl VrUser for IrAssign {
|
|||||||
&mut self,
|
&mut self,
|
||||||
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
) {
|
) {
|
||||||
|
// Have to isolate the following, because when the destination and the value are the same,
|
||||||
|
// we get a BorrowMutError
|
||||||
|
{
|
||||||
let mut borrowed_destination = self.destination.borrow_mut();
|
let mut borrowed_destination = self.destination.borrow_mut();
|
||||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
borrowed_destination.descriptor_mut()
|
borrowed_destination.descriptor_mut()
|
||||||
@ -66,6 +69,7 @@ impl VrUser for IrAssign {
|
|||||||
vr_variable.set_assigned_register(assignments[vr_variable]);
|
vr_variable.set_assigned_register(assignments[vr_variable]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
self.initializer.propagate_register_assignments(assignments);
|
self.initializer.propagate_register_assignments(assignments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::ast::ir_builder::IrBuilder;
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
|
use crate::ast::ir_util::get_or_init_field_pointer_variable;
|
||||||
use crate::ir::ir_assign::IrAssign;
|
use crate::ir::ir_assign::IrAssign;
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_get_field_ref::IrGetFieldRef;
|
|
||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
use crate::ir::ir_read_field::IrReadField;
|
use crate::ir::ir_read_field::IrReadField;
|
||||||
use crate::ir::ir_statement::IrStatement;
|
use crate::ir::ir_statement::IrStatement;
|
||||||
@ -79,34 +79,6 @@ impl ExpressibleSymbol {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
ExpressibleSymbol::Field(field_symbol) => {
|
ExpressibleSymbol::Field(field_symbol) => {
|
||||||
// This following should work because blocks are flat in the ir; if a variable is
|
|
||||||
// defined in the ir block from this point forward, it's available to all subsequent
|
|
||||||
// blocks.
|
|
||||||
if !builder
|
|
||||||
.field_pointer_variables()
|
|
||||||
.contains_key(field_symbol.borrow().declared_name())
|
|
||||||
{
|
|
||||||
let field_ref_variable = IrVariable::new_vr(
|
|
||||||
builder.new_t_var().into(),
|
|
||||||
builder.current_block().id(),
|
|
||||||
field_symbol.borrow().type_info(),
|
|
||||||
);
|
|
||||||
let as_rc = Rc::new(RefCell::new(field_ref_variable));
|
|
||||||
let to_insert = as_rc.clone();
|
|
||||||
let self_parameter_or_variable = builder.self_parameter_or_variable().clone();
|
|
||||||
builder
|
|
||||||
.current_block_mut()
|
|
||||||
.add_statement(IrStatement::Assign(IrAssign::new(
|
|
||||||
as_rc,
|
|
||||||
IrOperation::GetFieldRef(IrGetFieldRef::new(
|
|
||||||
self_parameter_or_variable.clone(),
|
|
||||||
field_symbol.borrow().field_index(),
|
|
||||||
)),
|
|
||||||
)));
|
|
||||||
builder
|
|
||||||
.field_pointer_variables_mut()
|
|
||||||
.insert(field_symbol.borrow().declared_name_owned(), to_insert);
|
|
||||||
}
|
|
||||||
// now we need to read the field into a variable and return an expression pointing
|
// now we need to read the field into a variable and return an expression pointing
|
||||||
// to that variable
|
// to that variable
|
||||||
let read_destination = IrVariable::new_vr(
|
let read_destination = IrVariable::new_vr(
|
||||||
@ -116,11 +88,7 @@ impl ExpressibleSymbol {
|
|||||||
);
|
);
|
||||||
let read_destination_as_rc = Rc::new(RefCell::new(read_destination));
|
let read_destination_as_rc = Rc::new(RefCell::new(read_destination));
|
||||||
let ir_read_field = IrReadField::new(
|
let ir_read_field = IrReadField::new(
|
||||||
builder
|
get_or_init_field_pointer_variable(builder, field_symbol).clone(),
|
||||||
.field_pointer_variables()
|
|
||||||
.get(field_symbol.borrow().declared_name())
|
|
||||||
.unwrap()
|
|
||||||
.clone(),
|
|
||||||
);
|
);
|
||||||
builder
|
builder
|
||||||
.current_block_mut()
|
.current_block_mut()
|
||||||
|
|||||||
@ -248,6 +248,48 @@ mod e2e_tests {
|
|||||||
assert_eq!(o.fields().len(), 1);
|
assert_eq!(o.fields().len(), 1);
|
||||||
assert_eq!(o.fields()[0].unwrap_int(), 42);
|
assert_eq!(o.fields()[0].unwrap_int(), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_assign() {
|
||||||
|
assert_result(
|
||||||
|
"
|
||||||
|
fn assign() -> Int
|
||||||
|
let mut x = 21
|
||||||
|
x = x + x
|
||||||
|
x
|
||||||
|
end
|
||||||
|
",
|
||||||
|
"assign",
|
||||||
|
&vec![],
|
||||||
|
Value::Int(42),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn assign_field() {
|
||||||
|
let context = prepare_context(
|
||||||
|
"
|
||||||
|
class Foo
|
||||||
|
mut bar = 21
|
||||||
|
|
||||||
|
ctor(_bar: Int)
|
||||||
|
bar = _bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fn foo() -> Foo
|
||||||
|
Foo(42)
|
||||||
|
end
|
||||||
|
",
|
||||||
|
);
|
||||||
|
let result = get_result(&context, "foo", &vec![]);
|
||||||
|
assert!(result.is_some());
|
||||||
|
let value = result.unwrap();
|
||||||
|
assert!(matches!(value, Value::Object(_)));
|
||||||
|
let o = value.unwrap_object().borrow();
|
||||||
|
assert_eq!(o.fields().len(), 1);
|
||||||
|
assert_eq!(o.fields()[0].unwrap_int(), 42);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
11
examples/assign_field.dm
Normal file
11
examples/assign_field.dm
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Foo
|
||||||
|
mut bar = 21
|
||||||
|
|
||||||
|
ctor(_bar: Int)
|
||||||
|
bar = _bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fn main() -> Foo
|
||||||
|
Foo(42)
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue
Block a user