Compare commits
No commits in common. "f0c84fe0c8c72ab52af3de90e227eb2839d259d8" and "7e613b1b90d2a64886a25c330a338615c547f12c" have entirely different histories.
f0c84fe0c8
...
7e613b1b90
@ -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_expression(&mut ir_builder, &symbol_table);
|
let maybe_ir_expression = expression.to_ir(&mut ir_builder, &symbol_table);
|
||||||
|
|
||||||
// if Some, return the value
|
// if Some, return the value
|
||||||
ir_builder
|
ir_builder
|
||||||
|
|||||||
102
dmc-lib/src/ast/add_expression.rs
Normal file
102
dmc-lib/src/ast/add_expression.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use crate::ast::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
|
use crate::diagnostic::Diagnostic;
|
||||||
|
use crate::ir::ir_add::IrAdd;
|
||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol_table::SymbolTable;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
|
pub struct AddExpression {
|
||||||
|
lhs: Box<Expression>,
|
||||||
|
rhs: Box<Expression>,
|
||||||
|
source_range: SourceRange,
|
||||||
|
type_info: Option<TypeInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddExpression {
|
||||||
|
pub fn new(lhs: Expression, rhs: Expression, source_range: SourceRange) -> Self {
|
||||||
|
Self {
|
||||||
|
lhs: lhs.into(),
|
||||||
|
rhs: rhs.into(),
|
||||||
|
source_range,
|
||||||
|
type_info: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lhs(&self) -> &Expression {
|
||||||
|
&self.lhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rhs(&self) -> &Expression {
|
||||||
|
&self.rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gather_declared_names(
|
||||||
|
&mut self,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
let diagnostics: Vec<Diagnostic> = [self.lhs.as_mut(), self.rhs.as_mut()]
|
||||||
|
.iter_mut()
|
||||||
|
.map(|expression| expression.gather_declared_names(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
if diagnostics.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(diagnostics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
let diagnostics: Vec<Diagnostic> = [self.lhs.as_mut(), self.rhs.as_mut()]
|
||||||
|
.iter_mut()
|
||||||
|
.map(|expression| expression.check_name_usages(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
if diagnostics.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(diagnostics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
self.lhs.type_check(symbol_table)?;
|
||||||
|
self.rhs.type_check(symbol_table)?;
|
||||||
|
|
||||||
|
let lhs_type_info = self.lhs.type_info();
|
||||||
|
let rhs_type_info = self.rhs.type_info();
|
||||||
|
if lhs_type_info.can_add(rhs_type_info) {
|
||||||
|
self.type_info = Some(lhs_type_info.add_result(rhs_type_info));
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(vec![Diagnostic::new(
|
||||||
|
&format!("Cannot add {} to {}", rhs_type_info, lhs_type_info),
|
||||||
|
self.source_range.start(),
|
||||||
|
self.source_range.end(),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable) -> IrAdd {
|
||||||
|
let lhs_ir_expression = self
|
||||||
|
.lhs
|
||||||
|
.to_ir(builder, symbol_table)
|
||||||
|
.expect("Attempt to add non-expression");
|
||||||
|
let rhs_ir_expression = self
|
||||||
|
.rhs
|
||||||
|
.to_ir(builder, symbol_table)
|
||||||
|
.expect("Attempt to add non-expression");
|
||||||
|
IrAdd::new(lhs_ir_expression, rhs_ir_expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
|
self.type_info.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_range(&self) -> &SourceRange {
|
||||||
|
&self.source_range
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +1,6 @@
|
|||||||
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 {
|
||||||
@ -163,38 +157,6 @@ 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)]
|
||||||
|
|||||||
@ -1,223 +0,0 @@
|
|||||||
use crate::ast::expression::Expression;
|
|
||||||
use crate::ast::ir_builder::IrBuilder;
|
|
||||||
use crate::diagnostic::Diagnostic;
|
|
||||||
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
|
|
||||||
use crate::ir::ir_assign::IrAssign;
|
|
||||||
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
|
||||||
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_table::SymbolTable;
|
|
||||||
use crate::type_info::TypeInfo;
|
|
||||||
use crate::{diagnostics_result, handle_diagnostic, handle_diagnostics, maybe_return_diagnostics};
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub enum BinaryOperation {
|
|
||||||
Multiply,
|
|
||||||
Divide,
|
|
||||||
Modulo,
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
LeftShift,
|
|
||||||
RightShift,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct BinaryExpression {
|
|
||||||
lhs: Box<Expression>,
|
|
||||||
rhs: Box<Expression>,
|
|
||||||
op: BinaryOperation,
|
|
||||||
source_range: SourceRange,
|
|
||||||
type_info: Option<TypeInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BinaryExpression {
|
|
||||||
pub fn new(
|
|
||||||
lhs: Expression,
|
|
||||||
rhs: Expression,
|
|
||||||
op: BinaryOperation,
|
|
||||||
source_range: SourceRange,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
lhs: lhs.into(),
|
|
||||||
rhs: rhs.into(),
|
|
||||||
op,
|
|
||||||
source_range,
|
|
||||||
type_info: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lhs(&self) -> &Expression {
|
|
||||||
&self.lhs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rhs(&self) -> &Expression {
|
|
||||||
&self.rhs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn op(&self) -> &BinaryOperation {
|
|
||||||
&self.op
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn source_range(&self) -> &SourceRange {
|
|
||||||
&self.source_range
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_info(&self) -> &TypeInfo {
|
|
||||||
self.type_info.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gather_declared_names(
|
|
||||||
&mut self,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
let diagnostics = [&mut self.lhs, &mut self.rhs]
|
|
||||||
.iter_mut()
|
|
||||||
.map(|expression| expression.gather_declared_names(symbol_table))
|
|
||||||
.filter_map(|result| result.err())
|
|
||||||
.flatten()
|
|
||||||
.collect::<Vec<Diagnostic>>();
|
|
||||||
if diagnostics.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(diagnostics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
let diagnostics: Vec<Diagnostic> = [&mut self.lhs, &mut self.rhs]
|
|
||||||
.iter_mut()
|
|
||||||
.map(|expression| expression.check_name_usages(symbol_table))
|
|
||||||
.filter_map(Result::err)
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
if diagnostics.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(diagnostics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_op(
|
|
||||||
&mut self,
|
|
||||||
check: impl Fn(&TypeInfo, &TypeInfo) -> bool,
|
|
||||||
op_result: impl Fn(&TypeInfo, &TypeInfo) -> TypeInfo,
|
|
||||||
lazy_diagnostic_message: impl Fn(&TypeInfo, &TypeInfo) -> String,
|
|
||||||
) -> Result<(), Diagnostic> {
|
|
||||||
let lhs_type_info = self.lhs.type_info();
|
|
||||||
let rhs_type_info = self.rhs.type_info();
|
|
||||||
|
|
||||||
if check(lhs_type_info, rhs_type_info) {
|
|
||||||
self.type_info = Some(op_result(lhs_type_info, rhs_type_info));
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
let diagnostic = Diagnostic::new(
|
|
||||||
&lazy_diagnostic_message(lhs_type_info, rhs_type_info),
|
|
||||||
self.source_range.start(),
|
|
||||||
self.source_range.end(),
|
|
||||||
)
|
|
||||||
.with_primary_label_message("Incompatible types for addition.")
|
|
||||||
.with_reporter(file!(), line!())
|
|
||||||
.with_error_code(BINARY_INCOMPATIBLE_TYPES);
|
|
||||||
Err(diagnostic)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
|
||||||
|
|
||||||
handle_diagnostics!(self.lhs.type_check(symbol_table), diagnostics);
|
|
||||||
handle_diagnostics!(self.rhs.type_check(symbol_table), diagnostics);
|
|
||||||
|
|
||||||
maybe_return_diagnostics!(diagnostics);
|
|
||||||
|
|
||||||
match &self.op {
|
|
||||||
BinaryOperation::Multiply => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
BinaryOperation::Divide => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
BinaryOperation::Modulo => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
BinaryOperation::Add => {
|
|
||||||
handle_diagnostic!(
|
|
||||||
self.check_op(
|
|
||||||
|lhs, rhs| lhs.can_add(rhs),
|
|
||||||
|lhs, rhs| lhs.add_result(&rhs),
|
|
||||||
|lhs, rhs| format!("Incompatible types: cannot add {} to {}.", rhs, lhs)
|
|
||||||
),
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
}
|
|
||||||
BinaryOperation::Subtract => {
|
|
||||||
handle_diagnostic!(
|
|
||||||
self.check_op(
|
|
||||||
|lhs, rhs| lhs.can_subtract(rhs),
|
|
||||||
|lhs, rhs| lhs.subtract_result(rhs),
|
|
||||||
|lhs, rhs| format!(
|
|
||||||
"Incompatible types: cannot subtract {} from {}.",
|
|
||||||
rhs, lhs
|
|
||||||
)
|
|
||||||
),
|
|
||||||
diagnostics
|
|
||||||
)
|
|
||||||
}
|
|
||||||
BinaryOperation::LeftShift => todo!(),
|
|
||||||
BinaryOperation::RightShift => todo!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnostics_result!(diagnostics)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_ir_operation(
|
|
||||||
&self,
|
|
||||||
builder: &mut IrBuilder,
|
|
||||||
symbol_table: &SymbolTable,
|
|
||||||
) -> IrOperation {
|
|
||||||
let lhs = self
|
|
||||||
.lhs
|
|
||||||
.to_ir_expression(builder, symbol_table)
|
|
||||||
.expect("Attempt to use a non-value expression in binary expression.");
|
|
||||||
let rhs = self
|
|
||||||
.rhs
|
|
||||||
.to_ir_expression(builder, symbol_table)
|
|
||||||
.expect("Attempt to use a non-value expression in binary expression.");
|
|
||||||
let ir_binary_operation = match self.op {
|
|
||||||
BinaryOperation::Multiply => {
|
|
||||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Multiply)
|
|
||||||
}
|
|
||||||
BinaryOperation::Divide => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Divide),
|
|
||||||
BinaryOperation::Modulo => todo!(),
|
|
||||||
BinaryOperation::Add => IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Add),
|
|
||||||
BinaryOperation::Subtract => {
|
|
||||||
IrBinaryOperation::new(lhs, rhs, IrBinaryOperator::Subtract)
|
|
||||||
}
|
|
||||||
BinaryOperation::LeftShift => todo!(),
|
|
||||||
BinaryOperation::RightShift => todo!(),
|
|
||||||
};
|
|
||||||
IrOperation::Binary(ir_binary_operation)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_ir_expression(
|
|
||||||
&self,
|
|
||||||
builder: &mut IrBuilder,
|
|
||||||
symbol_table: &SymbolTable,
|
|
||||||
) -> IrExpression {
|
|
||||||
let ir_operation = self.to_ir_operation(builder, symbol_table);
|
|
||||||
let t_var = IrVariable::new_vr(
|
|
||||||
builder.new_t_var().into(),
|
|
||||||
builder.current_block().id(),
|
|
||||||
self.type_info(),
|
|
||||||
);
|
|
||||||
let as_rc = Rc::new(RefCell::new(t_var));
|
|
||||||
let ir_assign = IrAssign::new(as_rc.clone(), ir_operation);
|
|
||||||
builder
|
|
||||||
.current_block_mut()
|
|
||||||
.add_statement(IrStatement::Assign(ir_assign));
|
|
||||||
IrExpression::Variable(as_rc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -5,6 +5,7 @@ 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;
|
||||||
@ -175,7 +176,7 @@ impl Call {
|
|||||||
let arguments: Vec<IrExpression> = self
|
let arguments: Vec<IrExpression> = self
|
||||||
.arguments
|
.arguments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|argument| argument.to_ir_expression(builder, symbol_table))
|
.map(|argument| argument.to_ir(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,19 +200,13 @@ impl Constructor {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, parameter)| {
|
.map(|(i, parameter)| {
|
||||||
let mut parameter_symbol = parameter.parameter_symbol().borrow_mut();
|
let parameter_symbol = parameter.parameter_symbol().borrow();
|
||||||
let offset = (parameters_count as isize).neg() + i as isize;
|
let offset = (parameters_count as isize).neg() + i as isize;
|
||||||
let ir_parameter = Rc::new(IrParameter::new(
|
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<_>>();
|
||||||
|
|
||||||
@ -225,11 +219,6 @@ 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())),
|
||||||
@ -263,18 +252,16 @@ 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.declared_name_owned(), field_mut_ref_variable); // n.b. field name, not t var name
|
.insert(field_mut_ref_variable_name.clone(), field_mut_ref_variable);
|
||||||
|
|
||||||
// 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.declared_name())
|
.get(&field_mut_ref_variable_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let ir_expression = initializer
|
let ir_expression = initializer.to_ir(&mut ir_builder, symbol_table).unwrap();
|
||||||
.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,
|
||||||
@ -285,11 +272,6 @@ 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(),
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::ast::binary_expression::BinaryExpression;
|
use crate::ast::add_expression::AddExpression;
|
||||||
use crate::ast::call::Call;
|
use crate::ast::call::Call;
|
||||||
use crate::ast::double_literal::DoubleLiteral;
|
use crate::ast::double_literal::DoubleLiteral;
|
||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
@ -6,6 +6,7 @@ use crate::ast::integer_literal::IntegerLiteral;
|
|||||||
use crate::ast::ir_builder::IrBuilder;
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::string_literal::StringLiteral;
|
use crate::ast::string_literal::StringLiteral;
|
||||||
|
use crate::ast::subtract_expression::SubtractExpression;
|
||||||
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_expression::IrExpression;
|
||||||
@ -19,7 +20,8 @@ use std::cell::RefCell;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Binary(BinaryExpression),
|
Add(AddExpression),
|
||||||
|
Subtract(SubtractExpression),
|
||||||
Negative(NegativeExpression),
|
Negative(NegativeExpression),
|
||||||
Call(Call),
|
Call(Call),
|
||||||
Identifier(Identifier),
|
Identifier(Identifier),
|
||||||
@ -34,8 +36,9 @@ impl Expression {
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => {
|
Expression::Add(add_expression) => add_expression.gather_declared_names(symbol_table),
|
||||||
binary_expression.gather_declared_names(symbol_table)
|
Expression::Subtract(subtract_expression) => {
|
||||||
|
subtract_expression.gather_declared_names(symbol_table)
|
||||||
}
|
}
|
||||||
Expression::Negative(negative_expression) => {
|
Expression::Negative(negative_expression) => {
|
||||||
negative_expression.gather_declared_names(symbol_table)
|
negative_expression.gather_declared_names(symbol_table)
|
||||||
@ -50,8 +53,9 @@ impl Expression {
|
|||||||
|
|
||||||
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>> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => {
|
Expression::Add(add_expression) => add_expression.check_name_usages(symbol_table),
|
||||||
binary_expression.check_name_usages(symbol_table)
|
Expression::Subtract(subtract_expression) => {
|
||||||
|
subtract_expression.check_name_usages(symbol_table)
|
||||||
}
|
}
|
||||||
Expression::Negative(negative_expression) => {
|
Expression::Negative(negative_expression) => {
|
||||||
negative_expression.check_name_usages(symbol_table)
|
negative_expression.check_name_usages(symbol_table)
|
||||||
@ -66,7 +70,10 @@ impl Expression {
|
|||||||
|
|
||||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => binary_expression.type_check(symbol_table),
|
Expression::Add(add_expression) => add_expression.type_check(symbol_table),
|
||||||
|
Expression::Subtract(subtract_expression) => {
|
||||||
|
subtract_expression.type_check(symbol_table)
|
||||||
|
}
|
||||||
Expression::Negative(negative_expression) => {
|
Expression::Negative(negative_expression) => {
|
||||||
negative_expression.type_check(symbol_table)
|
negative_expression.type_check(symbol_table)
|
||||||
}
|
}
|
||||||
@ -80,7 +87,8 @@ impl Expression {
|
|||||||
|
|
||||||
pub fn type_info(&self) -> &TypeInfo {
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => binary_expression.type_info(),
|
Expression::Add(add_expression) => add_expression.type_info(),
|
||||||
|
Expression::Subtract(subtract_expression) => subtract_expression.type_info(),
|
||||||
Expression::Negative(negative_expression) => negative_expression.type_info(),
|
Expression::Negative(negative_expression) => negative_expression.type_info(),
|
||||||
Expression::Call(call) => call.return_type_info(),
|
Expression::Call(call) => call.return_type_info(),
|
||||||
Expression::Identifier(identifier) => identifier.type_info(),
|
Expression::Identifier(identifier) => identifier.type_info(),
|
||||||
@ -92,7 +100,8 @@ impl Expression {
|
|||||||
|
|
||||||
pub fn source_range(&self) -> &SourceRange {
|
pub fn source_range(&self) -> &SourceRange {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => binary_expression.source_range(),
|
Expression::Add(additive_expression) => additive_expression.source_range(),
|
||||||
|
Expression::Subtract(subtract_expression) => subtract_expression.source_range(),
|
||||||
Expression::Negative(negative_expression) => negative_expression.source_range(),
|
Expression::Negative(negative_expression) => negative_expression.source_range(),
|
||||||
Expression::Call(call) => call.source_range(),
|
Expression::Call(call) => call.source_range(),
|
||||||
Expression::Identifier(identifier) => identifier.source_range(),
|
Expression::Identifier(identifier) => identifier.source_range(),
|
||||||
@ -102,43 +111,12 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir_operation(
|
pub fn to_ir(
|
||||||
&self,
|
|
||||||
builder: &mut IrBuilder,
|
|
||||||
symbol_table: &SymbolTable,
|
|
||||||
) -> IrOperation {
|
|
||||||
match self {
|
|
||||||
Expression::Binary(binary_expression) => {
|
|
||||||
binary_expression.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::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,
|
||||||
) -> Option<IrExpression> {
|
) -> Option<IrExpression> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Binary(binary_expression) => {
|
|
||||||
Some(binary_expression.to_ir_expression(builder, symbol_table))
|
|
||||||
}
|
|
||||||
Expression::Call(call) => {
|
Expression::Call(call) => {
|
||||||
let ir_call = call.to_ir(builder, symbol_table);
|
let ir_call = call.to_ir(builder, symbol_table);
|
||||||
if matches!(call.return_type_info(), TypeInfo::Void) {
|
if matches!(call.return_type_info(), TypeInfo::Void) {
|
||||||
@ -173,6 +151,23 @@ impl Expression {
|
|||||||
let expressible_symbol = identifier.expressible_symbol();
|
let expressible_symbol = identifier.expressible_symbol();
|
||||||
Some(expressible_symbol.ir_expression(builder))
|
Some(expressible_symbol.ir_expression(builder))
|
||||||
}
|
}
|
||||||
|
Expression::Add(additive_expression) => {
|
||||||
|
let ir_add = additive_expression.to_ir(builder, symbol_table);
|
||||||
|
let t_var = IrVariable::new_vr(
|
||||||
|
builder.new_t_var().into(),
|
||||||
|
builder.current_block().id(),
|
||||||
|
additive_expression.type_info(),
|
||||||
|
);
|
||||||
|
let as_rc = Rc::new(RefCell::new(t_var));
|
||||||
|
let assign = IrAssign::new(as_rc.clone(), IrOperation::Add(ir_add));
|
||||||
|
builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Assign(assign));
|
||||||
|
Some(IrExpression::Variable(as_rc))
|
||||||
|
}
|
||||||
|
Expression::Subtract(subtract_expression) => {
|
||||||
|
Some(subtract_expression.to_ir_expression(builder, symbol_table))
|
||||||
|
}
|
||||||
Expression::Negative(negative_expression) => {
|
Expression::Negative(negative_expression) => {
|
||||||
Some(negative_expression.to_ir(builder, symbol_table))
|
Some(negative_expression.to_ir(builder, symbol_table))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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_expression(builder, symbol_table);
|
let ir_expression = self.expression.to_ir(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,10 +42,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,83 +0,0 @@
|
|||||||
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,6 +2,8 @@ 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;
|
||||||
@ -104,7 +106,28 @@ 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 = self.initializer.to_ir_operation(builder, symbol_table);
|
let init_operation = match self.initializer() {
|
||||||
|
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);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
pub mod add_expression;
|
||||||
pub mod assign_statement;
|
pub mod assign_statement;
|
||||||
pub mod binary_expression;
|
|
||||||
pub mod call;
|
pub mod call;
|
||||||
pub mod class;
|
pub mod class;
|
||||||
pub mod compilation_unit;
|
pub mod compilation_unit;
|
||||||
@ -16,11 +16,10 @@ 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;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
pub mod string_literal;
|
pub mod string_literal;
|
||||||
|
pub mod subtract_expression;
|
||||||
pub mod type_use;
|
pub mod type_use;
|
||||||
mod util;
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@ 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_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_multiply::IrMultiply;
|
||||||
use crate::ir::ir_operation::IrOperation;
|
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;
|
||||||
@ -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_expression(builder, symbol_table)
|
.to_ir(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 {
|
||||||
@ -87,11 +87,8 @@ impl NegativeExpression {
|
|||||||
_ => panic!("Trying to multiply with a non-integer/double"),
|
_ => panic!("Trying to multiply with a non-integer/double"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let operation = IrOperation::Binary(IrBinaryOperation::new(
|
let operation =
|
||||||
IrExpression::Parameter(parameter),
|
IrOperation::Multiply(IrMultiply::new(IrExpression::Parameter(parameter), rhs));
|
||||||
rhs,
|
|
||||||
IrBinaryOperator::Multiply,
|
|
||||||
));
|
|
||||||
|
|
||||||
let assign = IrAssign::new(destination.clone(), operation);
|
let assign = IrAssign::new(destination.clone(), operation);
|
||||||
builder
|
builder
|
||||||
@ -113,11 +110,8 @@ impl NegativeExpression {
|
|||||||
_ => panic!("Trying to multiply with a non-integer/double"),
|
_ => panic!("Trying to multiply with a non-integer/double"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let operation = IrOperation::Binary(IrBinaryOperation::new(
|
let operation =
|
||||||
IrExpression::Variable(variable),
|
IrOperation::Multiply(IrMultiply::new(IrExpression::Variable(variable), rhs));
|
||||||
rhs,
|
|
||||||
IrBinaryOperator::Multiply,
|
|
||||||
));
|
|
||||||
|
|
||||||
let assign = IrAssign::new(destination.clone(), operation);
|
let assign = IrAssign::new(destination.clone(), operation);
|
||||||
builder
|
builder
|
||||||
|
|||||||
@ -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) => {
|
||||||
assign_statement.to_ir(builder, symbol_table);
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
135
dmc-lib/src/ast/subtract_expression.rs
Normal file
135
dmc-lib/src/ast/subtract_expression.rs
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
use crate::ast::expression::Expression;
|
||||||
|
use crate::ast::ir_builder::IrBuilder;
|
||||||
|
use crate::diagnostic::Diagnostic;
|
||||||
|
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_subtract::IrSubtract;
|
||||||
|
use crate::ir::ir_variable::IrVariable;
|
||||||
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol_table::SymbolTable;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub struct SubtractExpression {
|
||||||
|
lhs: Box<Expression>,
|
||||||
|
rhs: Box<Expression>,
|
||||||
|
source_range: SourceRange,
|
||||||
|
type_info: Option<TypeInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubtractExpression {
|
||||||
|
pub fn new(lhs: Expression, rhs: Expression, source_range: SourceRange) -> Self {
|
||||||
|
Self {
|
||||||
|
lhs: lhs.into(),
|
||||||
|
rhs: rhs.into(),
|
||||||
|
source_range,
|
||||||
|
type_info: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lhs(&self) -> &Expression {
|
||||||
|
&self.lhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rhs(&self) -> &Expression {
|
||||||
|
&self.rhs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gather_declared_names(
|
||||||
|
&mut self,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
let diagnostics = [&mut self.lhs, &mut self.rhs]
|
||||||
|
.iter_mut()
|
||||||
|
.map(|expression| expression.gather_declared_names(symbol_table))
|
||||||
|
.filter_map(|result| result.err())
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<Diagnostic>>();
|
||||||
|
if diagnostics.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(diagnostics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
let diagnostics: Vec<Diagnostic> = [&mut self.lhs, &mut self.rhs]
|
||||||
|
.iter_mut()
|
||||||
|
.map(|expression| expression.check_name_usages(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
if diagnostics.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(diagnostics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
self.lhs.type_check(symbol_table)?;
|
||||||
|
self.rhs.type_check(symbol_table)?;
|
||||||
|
|
||||||
|
let lhs_type_info = self.lhs.type_info();
|
||||||
|
let rhs_type_info = self.rhs.type_info();
|
||||||
|
if lhs_type_info.can_subtract(rhs_type_info) {
|
||||||
|
self.type_info = Some(lhs_type_info.add_result(rhs_type_info));
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(vec![Diagnostic::new(
|
||||||
|
&format!(
|
||||||
|
"Incompatible types: cannot subtract {} from {}",
|
||||||
|
rhs_type_info, lhs_type_info
|
||||||
|
), // n.b. order
|
||||||
|
self.lhs.source_range().start(),
|
||||||
|
self.lhs.source_range().end(),
|
||||||
|
)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_info(&self) -> &TypeInfo {
|
||||||
|
self.type_info.as_ref().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn source_range(&self) -> &SourceRange {
|
||||||
|
&self.source_range
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ir_subtract(
|
||||||
|
&self,
|
||||||
|
builder: &mut IrBuilder,
|
||||||
|
symbol_table: &SymbolTable,
|
||||||
|
) -> IrSubtract {
|
||||||
|
let lhs = self
|
||||||
|
.lhs
|
||||||
|
.to_ir(builder, symbol_table)
|
||||||
|
.expect("Attempt to subtract non-expression");
|
||||||
|
let rhs = self
|
||||||
|
.rhs
|
||||||
|
.to_ir(builder, symbol_table)
|
||||||
|
.expect("Attempt to subtract non-expression");
|
||||||
|
IrSubtract::new(lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ir_expression(
|
||||||
|
&self,
|
||||||
|
builder: &mut IrBuilder,
|
||||||
|
symbol_table: &SymbolTable,
|
||||||
|
) -> IrExpression {
|
||||||
|
let ir_subtract = self.to_ir_subtract(builder, symbol_table);
|
||||||
|
let t_var = IrVariable::new_vr(
|
||||||
|
builder.new_t_var().into(),
|
||||||
|
builder.current_block().id(),
|
||||||
|
self.type_info(),
|
||||||
|
);
|
||||||
|
let as_rc = Rc::new(RefCell::new(t_var));
|
||||||
|
let assign = IrAssign::new(as_rc.clone(), IrOperation::Subtract(ir_subtract));
|
||||||
|
builder
|
||||||
|
.current_block_mut()
|
||||||
|
.add_statement(IrStatement::Assign(assign));
|
||||||
|
IrExpression::Variable(as_rc)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,43 +0,0 @@
|
|||||||
#[macro_export]
|
|
||||||
macro_rules! handle_diagnostic {
|
|
||||||
( $result: expr, $diagnostics: expr ) => {
|
|
||||||
match $result {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(diagnostic) => {
|
|
||||||
$diagnostics.push(diagnostic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! handle_diagnostics {
|
|
||||||
( $result: expr, $diagnostics: expr ) => {
|
|
||||||
match $result {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(mut result_diagnostics) => {
|
|
||||||
$diagnostics.append(&mut result_diagnostics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! maybe_return_diagnostics {
|
|
||||||
( $diagnostics: expr ) => {
|
|
||||||
if !$diagnostics.is_empty() {
|
|
||||||
return Err($diagnostics);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! diagnostics_result {
|
|
||||||
( $diagnostics: expr ) => {
|
|
||||||
if $diagnostics.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err($diagnostics)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
pub type ErrorCode = usize;
|
pub type ErrorCode = usize;
|
||||||
|
|
||||||
pub const BINARY_INCOMPATIBLE_TYPES: ErrorCode = 15;
|
|
||||||
pub const ASSIGN_MISMATCHED_TYPES: ErrorCode = 16;
|
pub const ASSIGN_MISMATCHED_TYPES: ErrorCode = 16;
|
||||||
pub const ASSIGN_NO_L_VALUE: ErrorCode = 17;
|
pub const ASSIGN_NO_L_VALUE: ErrorCode = 17;
|
||||||
pub const ASSIGN_LHS_IMMUTABLE: ErrorCode = 18;
|
pub const ASSIGN_LHS_IMMUTABLE: ErrorCode = 18;
|
||||||
|
|||||||
75
dmc-lib/src/ir/ir_add.rs
Normal file
75
dmc-lib/src/ir/ir_add.rs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
use crate::constants_table::ConstantsTable;
|
||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
|
use dvm_lib::instruction::AddOperand;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn left(&self) -> &IrExpression {
|
||||||
|
&self.left
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn right(&self) -> &IrExpression {
|
||||||
|
&self.right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn operand_pair(&self, constants_table: &mut ConstantsTable) -> (AddOperand, AddOperand) {
|
||||||
|
(
|
||||||
|
self.left.add_operand(constants_table),
|
||||||
|
self.right.add_operand(constants_table),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrAdd {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} + {}", self.left, self.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrAdd {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[self.left.as_ref(), self.right.as_ref()]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|e| e.vr_definitions())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[self.left.as_ref(), self.right.as_ref()]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|e| e.vr_uses())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
self.left.propagate_spills(spills);
|
||||||
|
self.right.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
self.left.propagate_register_assignments(assignments);
|
||||||
|
self.right.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op, no definitions here
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,7 +3,6 @@ use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
|||||||
use crate::ir::ir_operation::IrOperation;
|
use crate::ir::ir_operation::IrOperation;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
||||||
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::ir::util::propagate_spills;
|
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
@ -26,10 +25,12 @@ impl IrAssign {
|
|||||||
|
|
||||||
impl VrUser for IrAssign {
|
impl VrUser for IrAssign {
|
||||||
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
self.destination
|
match self.destination.borrow().descriptor() {
|
||||||
.borrow()
|
IrVariableDescriptor::VirtualRegister(vr_descriptor) => {
|
||||||
.descriptor()
|
HashSet::from([vr_descriptor.clone()])
|
||||||
.vr_variable_descriptors()
|
}
|
||||||
|
IrVariableDescriptor::Stack(_) => HashSet::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
@ -37,7 +38,20 @@ impl VrUser for IrAssign {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
propagate_spills(&mut self.destination, spills);
|
let borrowed_destination = self.destination.borrow();
|
||||||
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
|
borrowed_destination.descriptor()
|
||||||
|
{
|
||||||
|
if spills.contains(vr_variable) {
|
||||||
|
let replacement = IrVariable::new_stack(
|
||||||
|
vr_variable.name().into(),
|
||||||
|
vr_variable.block_id(),
|
||||||
|
borrowed_destination.type_info().clone(),
|
||||||
|
);
|
||||||
|
drop(borrowed_destination);
|
||||||
|
self.destination.replace(replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_register_assignments(
|
fn propagate_register_assignments(
|
||||||
@ -52,6 +66,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
||||||
@ -97,8 +112,17 @@ impl Assemble for IrAssign {
|
|||||||
let move_operand = ir_expression.move_operand(constants_table);
|
let move_operand = ir_expression.move_operand(constants_table);
|
||||||
builder.push(Instruction::Move(move_operand, destination));
|
builder.push(Instruction::Move(move_operand, destination));
|
||||||
}
|
}
|
||||||
IrOperation::Binary(ir_binary_operation) => {
|
IrOperation::Add(ir_add) => {
|
||||||
ir_binary_operation.assemble_assign(builder, constants_table, destination);
|
let (left, right) = ir_add.operand_pair(constants_table);
|
||||||
|
builder.push(Instruction::Add(left, right, destination));
|
||||||
|
}
|
||||||
|
IrOperation::Subtract(ir_subtract) => {
|
||||||
|
let (left, right) = ir_subtract.operand_pair();
|
||||||
|
builder.push(Instruction::Subtract(left, right, destination));
|
||||||
|
}
|
||||||
|
IrOperation::Multiply(ir_multiply) => {
|
||||||
|
let (left, right) = ir_multiply.operand_pair();
|
||||||
|
builder.push(Instruction::Multiply(left, right, destination));
|
||||||
}
|
}
|
||||||
IrOperation::Call(ir_call) => {
|
IrOperation::Call(ir_call) => {
|
||||||
ir_call.assemble(builder, constants_table);
|
ir_call.assemble(builder, constants_table);
|
||||||
|
|||||||
@ -1,88 +0,0 @@
|
|||||||
use crate::constants_table::ConstantsTable;
|
|
||||||
use crate::ir::assemble::InstructionsBuilder;
|
|
||||||
use crate::ir::ir_expression::IrExpression;
|
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
|
||||||
use crate::ir::register_allocation::VrUser;
|
|
||||||
use dvm_lib::instruction::{Instruction, Location};
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
|
|
||||||
pub enum IrBinaryOperator {
|
|
||||||
Multiply,
|
|
||||||
Divide,
|
|
||||||
Add,
|
|
||||||
Subtract,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IrBinaryOperation {
|
|
||||||
left: Box<IrExpression>,
|
|
||||||
right: Box<IrExpression>,
|
|
||||||
op: IrBinaryOperator,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IrBinaryOperation {
|
|
||||||
pub fn new(left: IrExpression, right: IrExpression, op: IrBinaryOperator) -> Self {
|
|
||||||
Self {
|
|
||||||
left: left.into(),
|
|
||||||
right: right.into(),
|
|
||||||
op,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn assemble_assign(
|
|
||||||
&self,
|
|
||||||
builder: &mut InstructionsBuilder,
|
|
||||||
constants_table: &mut ConstantsTable,
|
|
||||||
destination: Location,
|
|
||||||
) {
|
|
||||||
let instruction = match &self.op {
|
|
||||||
IrBinaryOperator::Multiply => Instruction::Multiply(
|
|
||||||
self.left.multiply_operand(),
|
|
||||||
self.right.multiply_operand(),
|
|
||||||
destination,
|
|
||||||
),
|
|
||||||
IrBinaryOperator::Divide => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Add => Instruction::Add(
|
|
||||||
self.left.add_operand(constants_table),
|
|
||||||
self.right.add_operand(constants_table),
|
|
||||||
destination,
|
|
||||||
),
|
|
||||||
IrBinaryOperator::Subtract => Instruction::Subtract(
|
|
||||||
self.left.subtract_operand(),
|
|
||||||
self.right.subtract_operand(),
|
|
||||||
destination,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
builder.push(instruction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for IrBinaryOperation {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match &self.op {
|
|
||||||
IrBinaryOperator::Multiply => {
|
|
||||||
write!(f, "{} * {}", self.left, self.right)
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Divide => {
|
|
||||||
write!(f, "{} / {}", self.left, self.right)
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Add => {
|
|
||||||
write!(f, "{} + {}", self.left, self.right)
|
|
||||||
}
|
|
||||||
IrBinaryOperator::Subtract => {
|
|
||||||
write!(f, "{} - {}", self.left, self.right)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VrUser for IrBinaryOperation {
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
||||||
[self.left.as_ref(), self.right.as_ref()]
|
|
||||||
.iter()
|
|
||||||
.flat_map(|e| e.vr_uses())
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,9 +2,9 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -25,9 +25,32 @@ impl IrCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrCall {
|
impl VrUser for IrCall {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
self.arguments.iter().flat_map(|a| a.vr_uses()).collect()
|
self.arguments.iter().flat_map(|a| a.vr_uses()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
for argument in &mut self.arguments {
|
||||||
|
argument.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
for argument in &mut self.arguments {
|
||||||
|
argument.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op, because no definitions here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrCall {
|
impl Assemble for IrCall {
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::{
|
||||||
use crate::ir::register_allocation::VrUser;
|
IrStackVariableDescriptor, IrVariable, IrVariableDescriptor, IrVrVariableDescriptor,
|
||||||
|
};
|
||||||
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::instruction::{
|
use dvm_lib::instruction::{
|
||||||
AddOperand, Location, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand,
|
AddOperand, Location, MoveOperand, MultiplyOperand, PushOperand, ReturnOperand,
|
||||||
SetFieldOperand, SubtractOperand,
|
SetFieldOperand, SubtractOperand,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -229,6 +231,11 @@ impl Display for IrExpression {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrExpression {
|
impl VrUser for IrExpression {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
// no defs for an expression
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
match self {
|
match self {
|
||||||
IrExpression::Parameter(_) => HashSet::new(),
|
IrExpression::Parameter(_) => HashSet::new(),
|
||||||
@ -246,4 +253,71 @@ impl VrUser for IrExpression {
|
|||||||
IrExpression::String(_) => HashSet::new(),
|
IrExpression::String(_) => HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
match self {
|
||||||
|
IrExpression::Parameter(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::Variable(ir_variable) => {
|
||||||
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
|
ir_variable.borrow().descriptor()
|
||||||
|
{
|
||||||
|
if spills.contains(&vr_variable) {
|
||||||
|
ir_variable
|
||||||
|
.borrow_mut()
|
||||||
|
.set_descriptor(IrVariableDescriptor::Stack(
|
||||||
|
IrStackVariableDescriptor::new(
|
||||||
|
vr_variable.name().into(),
|
||||||
|
vr_variable.block_id(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IrExpression::Int(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::Double(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::String(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
match self {
|
||||||
|
IrExpression::Parameter(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::Variable(ir_variable) => {
|
||||||
|
let mut borrowed = ir_variable.borrow_mut();
|
||||||
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
|
borrowed.descriptor_mut()
|
||||||
|
{
|
||||||
|
if assignments.contains_key(vr_variable) {
|
||||||
|
vr_variable.set_assigned_register(assignments[vr_variable]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IrExpression::Int(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::Double(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
IrExpression::String(_) => {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub struct IrGetFieldRef {
|
pub struct IrGetFieldRef {
|
||||||
@ -37,7 +37,21 @@ impl Display for IrGetFieldRef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrGetFieldRef {
|
impl VrUser for IrGetFieldRef {
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
self.self_parameter_or_variable().vr_uses()
|
HashSet::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub struct IrGetFieldRefMut {
|
pub struct IrGetFieldRefMut {
|
||||||
@ -38,7 +38,21 @@ impl Display for IrGetFieldRefMut {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrGetFieldRefMut {
|
impl VrUser for IrGetFieldRefMut {
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
self.self_parameter_or_variable.vr_uses()
|
HashSet::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {}
|
||||||
}
|
}
|
||||||
|
|||||||
67
dmc-lib/src/ir/ir_multiply.rs
Normal file
67
dmc-lib/src/ir/ir_multiply.rs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
|
use dvm_lib::instruction::MultiplyOperand;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
pub struct IrMultiply {
|
||||||
|
left: Box<IrExpression>,
|
||||||
|
right: Box<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrMultiply {
|
||||||
|
pub fn new(left: IrExpression, right: IrExpression) -> Self {
|
||||||
|
Self {
|
||||||
|
left: left.into(),
|
||||||
|
right: right.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn operand_pair(&self) -> (MultiplyOperand, MultiplyOperand) {
|
||||||
|
(self.left.multiply_operand(), self.right.multiply_operand())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrMultiply {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} * {}", self.left, self.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrMultiply {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[&self.left, &self.right]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|ir_expression| ir_expression.vr_definitions())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[&self.left, &self.right]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|ir_expression| ir_expression.vr_uses())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
[&mut self.left, &mut self.right]
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|ir_expression| ir_expression.propagate_spills(spills));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
[&mut self.left, &mut self.right]
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|ir_expression| ir_expression.propagate_register_assignments(assignments));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {
|
||||||
|
[&mut self.left, &mut self.right]
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|ir_expression| ir_expression.propagate_stack_offsets(counter));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,15 @@
|
|||||||
|
use crate::ir::ir_add::IrAdd;
|
||||||
use crate::ir::ir_allocate::IrAllocate;
|
use crate::ir::ir_allocate::IrAllocate;
|
||||||
use crate::ir::ir_binary_operation::IrBinaryOperation;
|
|
||||||
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::ir::ir_get_field_ref::IrGetFieldRef;
|
use crate::ir::ir_get_field_ref::IrGetFieldRef;
|
||||||
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
|
use crate::ir::ir_get_field_ref_mut::IrGetFieldRefMut;
|
||||||
|
use crate::ir::ir_multiply::IrMultiply;
|
||||||
use crate::ir::ir_read_field::IrReadField;
|
use crate::ir::ir_read_field::IrReadField;
|
||||||
|
use crate::ir::ir_subtract::IrSubtract;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub enum IrOperation {
|
pub enum IrOperation {
|
||||||
@ -15,7 +17,9 @@ pub enum IrOperation {
|
|||||||
GetFieldRefMut(IrGetFieldRefMut),
|
GetFieldRefMut(IrGetFieldRefMut),
|
||||||
ReadField(IrReadField),
|
ReadField(IrReadField),
|
||||||
Load(IrExpression),
|
Load(IrExpression),
|
||||||
Binary(IrBinaryOperation),
|
Add(IrAdd),
|
||||||
|
Subtract(IrSubtract),
|
||||||
|
Multiply(IrMultiply),
|
||||||
Call(IrCall),
|
Call(IrCall),
|
||||||
Allocate(IrAllocate),
|
Allocate(IrAllocate),
|
||||||
}
|
}
|
||||||
@ -35,8 +39,14 @@ impl Display for IrOperation {
|
|||||||
IrOperation::Load(ir_expression) => {
|
IrOperation::Load(ir_expression) => {
|
||||||
write!(f, "{}", ir_expression)
|
write!(f, "{}", ir_expression)
|
||||||
}
|
}
|
||||||
IrOperation::Binary(ir_binary_operation) => {
|
IrOperation::Add(ir_add) => {
|
||||||
write!(f, "{}", ir_binary_operation)
|
write!(f, "{}", ir_add)
|
||||||
|
}
|
||||||
|
IrOperation::Subtract(ir_subtract) => {
|
||||||
|
write!(f, "{}", ir_subtract)
|
||||||
|
}
|
||||||
|
IrOperation::Multiply(ir_multiply) => {
|
||||||
|
write!(f, "{}", ir_multiply)
|
||||||
}
|
}
|
||||||
IrOperation::Call(ir_call) => {
|
IrOperation::Call(ir_call) => {
|
||||||
write!(f, "{}", ir_call)
|
write!(f, "{}", ir_call)
|
||||||
@ -49,15 +59,86 @@ impl Display for IrOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrOperation {
|
impl VrUser for IrOperation {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
match self {
|
||||||
|
IrOperation::GetFieldRef(_) => HashSet::new(),
|
||||||
|
IrOperation::GetFieldRefMut(_) => HashSet::new(),
|
||||||
|
IrOperation::ReadField(_) => HashSet::new(),
|
||||||
|
IrOperation::Load(ir_expression) => ir_expression.vr_definitions(),
|
||||||
|
IrOperation::Add(ir_add) => ir_add.vr_definitions(),
|
||||||
|
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_definitions(),
|
||||||
|
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_definitions(),
|
||||||
|
IrOperation::Call(ir_call) => ir_call.vr_definitions(),
|
||||||
|
IrOperation::Allocate(_) => HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
match self {
|
match self {
|
||||||
IrOperation::GetFieldRef(ir_get_field_ref) => ir_get_field_ref.vr_uses(),
|
IrOperation::GetFieldRef(ir_get_field_ref) => ir_get_field_ref.vr_uses(),
|
||||||
IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => ir_get_field_ref_mut.vr_uses(),
|
IrOperation::GetFieldRefMut(ir_get_field_ref_mut) => ir_get_field_ref_mut.vr_uses(),
|
||||||
IrOperation::ReadField(ir_read_field) => ir_read_field.vr_uses(),
|
IrOperation::ReadField(ir_read_field) => ir_read_field.vr_uses(),
|
||||||
IrOperation::Load(ir_expression) => ir_expression.vr_uses(),
|
IrOperation::Load(ir_expression) => ir_expression.vr_uses(),
|
||||||
IrOperation::Binary(ir_binary) => ir_binary.vr_uses(),
|
IrOperation::Add(ir_add) => ir_add.vr_uses(),
|
||||||
|
IrOperation::Subtract(ir_subtract) => ir_subtract.vr_uses(),
|
||||||
|
IrOperation::Multiply(ir_multiply) => ir_multiply.vr_uses(),
|
||||||
IrOperation::Call(ir_call) => ir_call.vr_uses(),
|
IrOperation::Call(ir_call) => ir_call.vr_uses(),
|
||||||
IrOperation::Allocate(_) => HashSet::new(),
|
IrOperation::Allocate(_) => HashSet::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
match self {
|
||||||
|
IrOperation::GetFieldRef(_) => {}
|
||||||
|
IrOperation::GetFieldRefMut(_) => {}
|
||||||
|
IrOperation::ReadField(_) => {}
|
||||||
|
IrOperation::Load(ir_expression) => {
|
||||||
|
ir_expression.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
IrOperation::Add(ir_add) => {
|
||||||
|
ir_add.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
IrOperation::Subtract(ir_subtract) => {
|
||||||
|
ir_subtract.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
IrOperation::Multiply(ir_multiply) => {
|
||||||
|
ir_multiply.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
IrOperation::Call(ir_call) => {
|
||||||
|
ir_call.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
IrOperation::Allocate(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
match self {
|
||||||
|
IrOperation::GetFieldRef(_) => {}
|
||||||
|
IrOperation::GetFieldRefMut(_) => {}
|
||||||
|
IrOperation::ReadField(_) => {}
|
||||||
|
IrOperation::Load(ir_expression) => {
|
||||||
|
ir_expression.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
IrOperation::Add(ir_add) => {
|
||||||
|
ir_add.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
IrOperation::Subtract(ir_subtract) => {
|
||||||
|
ir_subtract.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
IrOperation::Multiply(ir_multiply) => {
|
||||||
|
ir_multiply.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
IrOperation::Call(ir_call) => {
|
||||||
|
ir_call.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
IrOperation::Allocate(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use crate::ir::ir_parameter::IrParameter;
|
use crate::ir::ir_parameter::IrParameter;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::IrVariable;
|
||||||
use dvm_lib::instruction::Location;
|
use dvm_lib::instruction::Location;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -23,17 +22,6 @@ impl IrParameterOrVariable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
||||||
if let IrParameterOrVariable::Variable(ir_variable) = &self {
|
|
||||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
|
||||||
ir_variable.borrow().descriptor()
|
|
||||||
{
|
|
||||||
return HashSet::from([vr_variable.clone()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HashSet::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for IrParameterOrVariable {
|
impl Display for IrParameterOrVariable {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -26,6 +26,10 @@ impl Display for IrReadField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrReadField {
|
impl VrUser for IrReadField {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
if let IrVariableDescriptor::VirtualRegister(vr_variable) =
|
||||||
@ -35,4 +39,14 @@ impl VrUser for IrReadField {
|
|||||||
}
|
}
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
pub struct IrReturn {
|
pub struct IrReturn {
|
||||||
@ -18,6 +18,10 @@ impl IrReturn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrReturn {
|
impl VrUser for IrReturn {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
HashSet::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
if let Some(ir_expression) = self.value.as_ref() {
|
if let Some(ir_expression) = self.value.as_ref() {
|
||||||
ir_expression.vr_uses()
|
ir_expression.vr_uses()
|
||||||
@ -25,6 +29,25 @@ impl VrUser for IrReturn {
|
|||||||
HashSet::new()
|
HashSet::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
if let Some(ir_expression) = self.value.as_mut() {
|
||||||
|
ir_expression.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
if let Some(ir_expression) = self.value.as_mut() {
|
||||||
|
ir_expression.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrReturn {
|
impl Assemble for IrReturn {
|
||||||
|
|||||||
@ -2,10 +2,11 @@ use crate::constants_table::ConstantsTable;
|
|||||||
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
use crate::ir::assemble::{Assemble, InstructionsBuilder};
|
||||||
use crate::ir::ir_expression::IrExpression;
|
use crate::ir::ir_expression::IrExpression;
|
||||||
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
use crate::ir::ir_variable::{IrVariable, IrVariableDescriptor, IrVrVariableDescriptor};
|
||||||
use crate::ir::register_allocation::VrUser;
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
|
use crate::ir::util::propagate_spills;
|
||||||
use dvm_lib::instruction::Instruction;
|
use dvm_lib::instruction::Instruction;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashSet;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -24,6 +25,11 @@ impl IrSetField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VrUser for IrSetField {
|
impl VrUser for IrSetField {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
// only this, because the target_object is technically not a definition
|
||||||
|
self.initializer.vr_definitions()
|
||||||
|
}
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
let mut set = HashSet::new();
|
let mut set = HashSet::new();
|
||||||
match self.field_ref_variable.borrow().descriptor() {
|
match self.field_ref_variable.borrow().descriptor() {
|
||||||
@ -35,6 +41,22 @@ impl VrUser for IrSetField {
|
|||||||
set.extend(self.initializer.vr_uses());
|
set.extend(self.initializer.vr_uses());
|
||||||
set
|
set
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
propagate_spills(&mut self.field_ref_variable, spills);
|
||||||
|
self.initializer.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
_assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
// no definitions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no definitions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Assemble for IrSetField {
|
impl Assemble for IrSetField {
|
||||||
|
|||||||
63
dmc-lib/src/ir/ir_subtract.rs
Normal file
63
dmc-lib/src/ir/ir_subtract.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
use crate::ir::ir_expression::IrExpression;
|
||||||
|
use crate::ir::ir_variable::IrVrVariableDescriptor;
|
||||||
|
use crate::ir::register_allocation::{OffsetCounter, VrUser};
|
||||||
|
use dvm_lib::instruction::SubtractOperand;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
|
pub struct IrSubtract {
|
||||||
|
left: Box<IrExpression>,
|
||||||
|
right: Box<IrExpression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrSubtract {
|
||||||
|
pub fn new(left: IrExpression, right: IrExpression) -> Self {
|
||||||
|
Self {
|
||||||
|
left: left.into(),
|
||||||
|
right: right.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn operand_pair(&self) -> (SubtractOperand, SubtractOperand) {
|
||||||
|
(self.left.subtract_operand(), self.right.subtract_operand())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VrUser for IrSubtract {
|
||||||
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[&self.left, &self.right]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|expression| expression.vr_definitions())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor> {
|
||||||
|
[&self.left, &self.right]
|
||||||
|
.iter()
|
||||||
|
.flat_map(|expression| expression.vr_uses())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>) {
|
||||||
|
self.left.propagate_spills(spills);
|
||||||
|
self.right.propagate_spills(spills);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_register_assignments(
|
||||||
|
&mut self,
|
||||||
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
|
) {
|
||||||
|
self.left.propagate_register_assignments(assignments);
|
||||||
|
self.right.propagate_register_assignments(assignments);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for IrSubtract {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} - {}", self.left, self.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
use dvm_lib::instruction::Location;
|
use dvm_lib::instruction::Location;
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::fmt::{Debug, Display, Formatter};
|
use std::fmt::{Debug, Display, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -91,14 +90,6 @@ impl IrVariableDescriptor {
|
|||||||
IrVariableDescriptor::Stack(stack_variable) => stack_variable.as_location(),
|
IrVariableDescriptor::Stack(stack_variable) => stack_variable.as_location(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vr_variable_descriptors(&self) -> HashSet<IrVrVariableDescriptor> {
|
|
||||||
if let IrVariableDescriptor::VirtualRegister(register_variable) = self {
|
|
||||||
HashSet::from([register_variable.clone()])
|
|
||||||
} else {
|
|
||||||
HashSet::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
mod assemble;
|
mod assemble;
|
||||||
|
pub mod ir_add;
|
||||||
pub mod ir_allocate;
|
pub mod ir_allocate;
|
||||||
pub mod ir_assign;
|
pub mod ir_assign;
|
||||||
pub mod ir_binary_operation;
|
|
||||||
pub mod ir_block;
|
pub mod ir_block;
|
||||||
pub mod ir_call;
|
pub mod ir_call;
|
||||||
pub mod ir_class;
|
pub mod ir_class;
|
||||||
@ -9,6 +9,7 @@ pub mod ir_expression;
|
|||||||
pub mod ir_function;
|
pub mod ir_function;
|
||||||
pub mod ir_get_field_ref;
|
pub mod ir_get_field_ref;
|
||||||
pub mod ir_get_field_ref_mut;
|
pub mod ir_get_field_ref_mut;
|
||||||
|
pub mod ir_multiply;
|
||||||
pub mod ir_operation;
|
pub mod ir_operation;
|
||||||
pub mod ir_parameter;
|
pub mod ir_parameter;
|
||||||
pub mod ir_parameter_or_variable;
|
pub mod ir_parameter_or_variable;
|
||||||
@ -16,6 +17,7 @@ pub mod ir_read_field;
|
|||||||
pub mod ir_return;
|
pub mod ir_return;
|
||||||
pub mod ir_set_field;
|
pub mod ir_set_field;
|
||||||
pub mod ir_statement;
|
pub mod ir_statement;
|
||||||
|
pub mod ir_subtract;
|
||||||
pub mod ir_variable;
|
pub mod ir_variable;
|
||||||
mod register_allocation;
|
mod register_allocation;
|
||||||
mod util;
|
mod util;
|
||||||
|
|||||||
@ -135,26 +135,14 @@ pub trait HasVrUsers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait VrUser {
|
pub trait VrUser {
|
||||||
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor> {
|
fn vr_definitions(&self) -> HashSet<IrVrVariableDescriptor>;
|
||||||
HashSet::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor>;
|
fn vr_uses(&self) -> HashSet<IrVrVariableDescriptor>;
|
||||||
|
fn propagate_spills(&mut self, spills: &HashSet<IrVrVariableDescriptor>);
|
||||||
fn propagate_spills(&mut self, _spills: &HashSet<IrVrVariableDescriptor>) {
|
|
||||||
// default no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
fn propagate_register_assignments(
|
fn propagate_register_assignments(
|
||||||
&mut self,
|
&mut self,
|
||||||
_assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
assignments: &HashMap<IrVrVariableDescriptor, usize>,
|
||||||
) {
|
);
|
||||||
// default no-op
|
fn propagate_stack_offsets(&mut self, counter: &mut OffsetCounter);
|
||||||
}
|
|
||||||
|
|
||||||
fn propagate_stack_offsets(&mut self, _counter: &mut OffsetCounter) {
|
|
||||||
// default no-op
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OffsetCounter {
|
pub struct OffsetCounter {
|
||||||
|
|||||||
@ -46,18 +46,8 @@ impl<'a> Lexer<'a> {
|
|||||||
self.position + 1,
|
self.position + 1,
|
||||||
TokenKind::RightParentheses,
|
TokenKind::RightParentheses,
|
||||||
)
|
)
|
||||||
} else if chunk.starts_with("*") {
|
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Star)
|
|
||||||
} else if chunk.starts_with("/") {
|
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Slash)
|
|
||||||
} else if chunk.starts_with("%") {
|
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Modulo)
|
|
||||||
} else if chunk.starts_with("+") {
|
} else if chunk.starts_with("+") {
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Plus)
|
Token::new(self.position, self.position + 1, TokenKind::Plus)
|
||||||
} else if chunk.starts_with("<<") {
|
|
||||||
Token::new(self.position, self.position + 2, TokenKind::LeftShift)
|
|
||||||
} else if chunk.starts_with(">>") {
|
|
||||||
Token::new(self.position, self.position + 2, TokenKind::RightShift)
|
|
||||||
} else if chunk.starts_with("=") {
|
} else if chunk.starts_with("=") {
|
||||||
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
Token::new(self.position, self.position + 1, TokenKind::Equals)
|
||||||
} else if chunk.starts_with(",") {
|
} else if chunk.starts_with(",") {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
use crate::ast::add_expression::AddExpression;
|
||||||
use crate::ast::assign_statement::AssignStatement;
|
use crate::ast::assign_statement::AssignStatement;
|
||||||
use crate::ast::binary_expression::{BinaryExpression, BinaryOperation};
|
|
||||||
use crate::ast::call::Call;
|
use crate::ast::call::Call;
|
||||||
use crate::ast::class::Class;
|
use crate::ast::class::Class;
|
||||||
use crate::ast::compilation_unit::CompilationUnit;
|
use crate::ast::compilation_unit::CompilationUnit;
|
||||||
@ -17,6 +17,7 @@ use crate::ast::negative_expression::NegativeExpression;
|
|||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::ast::string_literal::StringLiteral;
|
use crate::ast::string_literal::StringLiteral;
|
||||||
|
use crate::ast::subtract_expression::SubtractExpression;
|
||||||
use crate::ast::type_use::TypeUse;
|
use crate::ast::type_use::TypeUse;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::lexer::Lexer;
|
use crate::lexer::Lexer;
|
||||||
@ -662,119 +663,28 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
fn expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||||
self.shift_expression()
|
self.additive_expression()
|
||||||
}
|
|
||||||
|
|
||||||
fn shift_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
|
||||||
let mut result = self.additive_expression()?;
|
|
||||||
while self.current.is_some() {
|
|
||||||
let current = self.get_current();
|
|
||||||
match current.kind() {
|
|
||||||
TokenKind::LeftShift => {
|
|
||||||
self.advance(); // left shift
|
|
||||||
let rhs = self.additive_expression()?;
|
|
||||||
let source_range =
|
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::LeftShift,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
TokenKind::RightShift => {
|
|
||||||
self.advance(); // right shift
|
|
||||||
let rhs = self.additive_expression()?;
|
|
||||||
let source_range =
|
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::RightShift,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn additive_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
fn additive_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
||||||
let mut result = self.multiplicative_expression()?;
|
let mut result = self.prefix_expression()?;
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.get_current();
|
let current = self.get_current();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Plus => {
|
TokenKind::Plus => {
|
||||||
self.advance(); // plus
|
self.advance(); // plus
|
||||||
let rhs = self.multiplicative_expression()?;
|
let rhs = self.prefix_expression()?;
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
result = Expression::Add(AddExpression::new(result, rhs, source_range));
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::Add,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
TokenKind::Minus => {
|
TokenKind::Minus => {
|
||||||
self.advance(); // minus
|
self.advance(); // minus
|
||||||
let rhs = self.multiplicative_expression()?;
|
|
||||||
let source_range =
|
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::Subtract,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiplicative_expression(&mut self) -> Result<Expression, Vec<Diagnostic>> {
|
|
||||||
let mut result = self.prefix_expression()?;
|
|
||||||
while self.current.is_some() {
|
|
||||||
let current = self.get_current();
|
|
||||||
match current.kind() {
|
|
||||||
TokenKind::Star => {
|
|
||||||
self.advance(); // multiply
|
|
||||||
let rhs = self.prefix_expression()?;
|
let rhs = self.prefix_expression()?;
|
||||||
let source_range =
|
let source_range =
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
result =
|
||||||
result,
|
Expression::Subtract(SubtractExpression::new(result, rhs, source_range));
|
||||||
rhs,
|
|
||||||
BinaryOperation::Multiply,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
TokenKind::Slash => {
|
|
||||||
self.advance(); // slash
|
|
||||||
let rhs = self.prefix_expression()?;
|
|
||||||
let source_range =
|
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::Divide,
|
|
||||||
source_range,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
TokenKind::Modulo => {
|
|
||||||
self.advance(); // modulo
|
|
||||||
let rhs = self.prefix_expression()?;
|
|
||||||
let source_range =
|
|
||||||
SourceRange::new(result.source_range().start(), rhs.source_range().end());
|
|
||||||
result = Expression::Binary(BinaryExpression::new(
|
|
||||||
result,
|
|
||||||
rhs,
|
|
||||||
BinaryOperation::Modulo,
|
|
||||||
source_range,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
@ -1042,31 +952,6 @@ mod smoke_tests {
|
|||||||
",
|
",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_multiply() {
|
|
||||||
smoke_test("fn main() 1 * 2 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_divide() {
|
|
||||||
smoke_test("fn main() 1 / 2 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_modulo() {
|
|
||||||
smoke_test("fn main() 1 % 2 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_left_shift() {
|
|
||||||
smoke_test("fn main() 2 << 1 end");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn simple_right_shift() {
|
|
||||||
smoke_test("fn main() 4 >> 1 end");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -1170,15 +1055,14 @@ mod concrete_tests {
|
|||||||
fn add_negative() {
|
fn add_negative() {
|
||||||
let expression = assert_expression("1 + -1");
|
let expression = assert_expression("1 + -1");
|
||||||
match expression {
|
match expression {
|
||||||
Expression::Binary(binary_expression) => {
|
Expression::Add(add_expression) => {
|
||||||
assert!(matches!(binary_expression.op(), BinaryOperation::Add));
|
match add_expression.lhs() {
|
||||||
match binary_expression.lhs() {
|
|
||||||
Expression::Integer(integer_literal) => {
|
Expression::Integer(integer_literal) => {
|
||||||
assert_eq!(integer_literal.value(), 1);
|
assert_eq!(integer_literal.value(), 1);
|
||||||
}
|
}
|
||||||
_ => panic!("Expected integer literal"),
|
_ => panic!("Expected integer literal"),
|
||||||
}
|
}
|
||||||
match binary_expression.rhs() {
|
match add_expression.rhs() {
|
||||||
Expression::Negative(negative_expression) => {
|
Expression::Negative(negative_expression) => {
|
||||||
match negative_expression.operand() {
|
match negative_expression.operand() {
|
||||||
Expression::Integer(integer_literal) => {
|
Expression::Integer(integer_literal) => {
|
||||||
@ -1198,15 +1082,14 @@ mod concrete_tests {
|
|||||||
fn simple_subtract() {
|
fn simple_subtract() {
|
||||||
let expression = assert_expression("1 - 1");
|
let expression = assert_expression("1 - 1");
|
||||||
match expression {
|
match expression {
|
||||||
Expression::Binary(binary_expression) => {
|
Expression::Subtract(subtract_expression) => {
|
||||||
assert!(matches!(binary_expression.op(), BinaryOperation::Subtract));
|
match subtract_expression.lhs() {
|
||||||
match binary_expression.lhs() {
|
|
||||||
Expression::Integer(integer_literal) => {
|
Expression::Integer(integer_literal) => {
|
||||||
assert_eq!(integer_literal.value(), 1);
|
assert_eq!(integer_literal.value(), 1);
|
||||||
}
|
}
|
||||||
_ => panic!("Expected integer literal"),
|
_ => panic!("Expected integer literal"),
|
||||||
}
|
}
|
||||||
match binary_expression.rhs() {
|
match subtract_expression.rhs() {
|
||||||
Expression::Integer(integer_literal) => {
|
Expression::Integer(integer_literal) => {
|
||||||
assert_eq!(integer_literal.value(), 1);
|
assert_eq!(integer_literal.value(), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,6 +79,34 @@ 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(
|
||||||
@ -88,7 +116,11 @@ 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(
|
||||||
get_or_init_field_pointer_variable(builder, field_symbol).clone(),
|
builder
|
||||||
|
.field_pointer_variables()
|
||||||
|
.get(field_symbol.borrow().declared_name())
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
);
|
);
|
||||||
builder
|
builder
|
||||||
.current_block_mut()
|
.current_block_mut()
|
||||||
|
|||||||
@ -42,11 +42,6 @@ pub enum TokenKind {
|
|||||||
RightArrow,
|
RightArrow,
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
Star,
|
|
||||||
Slash,
|
|
||||||
Modulo,
|
|
||||||
LeftShift,
|
|
||||||
RightShift,
|
|
||||||
Class,
|
Class,
|
||||||
Dot,
|
Dot,
|
||||||
SelfKw,
|
SelfKw,
|
||||||
|
|||||||
@ -248,48 +248,6 @@ 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)]
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
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