321 lines
12 KiB
Rust
321 lines
12 KiB
Rust
use crate::ast::binary_expression::BinaryExpression;
|
|
use crate::ast::call::Call;
|
|
use crate::ast::double_literal::DoubleLiteral;
|
|
use crate::ast::identifier::Identifier;
|
|
use crate::ast::integer_literal::IntegerLiteral;
|
|
use crate::ast::ir_builder::IrBuilder;
|
|
use crate::ast::negative_expression::NegativeExpression;
|
|
use crate::ast::string_literal::StringLiteral;
|
|
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_variable::IrVariable;
|
|
use crate::source_range::SourceRange;
|
|
use crate::symbol::class_symbol::ClassSymbol;
|
|
use crate::symbol_table::SymbolTable;
|
|
use crate::type_info::TypeInfo;
|
|
use crate::types_table::TypesTable;
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
|
|
pub enum Expression {
|
|
Binary(BinaryExpression),
|
|
Negative(NegativeExpression),
|
|
Call(Call),
|
|
Identifier(Identifier),
|
|
Integer(IntegerLiteral),
|
|
Double(DoubleLiteral),
|
|
String(StringLiteral),
|
|
}
|
|
|
|
impl Expression {
|
|
pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.init_scopes(symbol_table, container_scope);
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.init_scopes(symbol_table, container_scope);
|
|
}
|
|
Expression::Call(call) => {
|
|
call.init_scopes(symbol_table, container_scope);
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
identifier.init_scope_id(container_scope);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
pub fn check_field_initializer_names(
|
|
&self,
|
|
symbol_table: &SymbolTable,
|
|
class_symbol: &ClassSymbol,
|
|
) -> Vec<Diagnostic> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.check_field_initializer_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.check_field_initializer_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Call(call) => {
|
|
call.check_field_initializer_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
if let Some(diagnostic) =
|
|
identifier.check_name_as_field_initializer(symbol_table, class_symbol)
|
|
{
|
|
vec![diagnostic]
|
|
} else {
|
|
vec![]
|
|
}
|
|
}
|
|
_ => vec![],
|
|
}
|
|
}
|
|
|
|
pub fn check_constructor_destination_names(
|
|
&self,
|
|
symbol_table: &SymbolTable,
|
|
class_symbol: &ClassSymbol,
|
|
) -> Vec<Diagnostic> {
|
|
match self {
|
|
Expression::Binary(_) => {
|
|
panic!()
|
|
}
|
|
Expression::Negative(_) => {
|
|
panic!()
|
|
}
|
|
Expression::Call(_) => {
|
|
panic!()
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
if let Some(diagnostic) =
|
|
identifier.check_constructor_destination_name(symbol_table, class_symbol)
|
|
{
|
|
vec![diagnostic]
|
|
} else {
|
|
vec![]
|
|
}
|
|
}
|
|
_ => vec![],
|
|
}
|
|
}
|
|
|
|
pub fn check_constructor_local_names(
|
|
&self,
|
|
symbol_table: &SymbolTable,
|
|
class_symbol: &ClassSymbol,
|
|
) -> Vec<Diagnostic> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.check_constructor_local_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.check_constructor_local_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Call(call) => {
|
|
call.check_constructor_local_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
if let Some(diagnostic) =
|
|
identifier.check_constructor_local_name(symbol_table, class_symbol)
|
|
{
|
|
vec![diagnostic]
|
|
} else {
|
|
vec![]
|
|
}
|
|
}
|
|
_ => vec![],
|
|
}
|
|
}
|
|
|
|
pub fn check_method_local_names(
|
|
&self,
|
|
symbol_table: &SymbolTable,
|
|
class_symbol: &ClassSymbol,
|
|
) -> Vec<Diagnostic> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.check_method_local_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.check_method_local_names(symbol_table, class_symbol)
|
|
}
|
|
Expression::Call(call) => call.check_method_local_names(symbol_table, class_symbol),
|
|
Expression::Identifier(identifier) => {
|
|
if let Some(diagnostic) =
|
|
identifier.check_method_local_name(symbol_table, class_symbol)
|
|
{
|
|
vec![diagnostic]
|
|
} else {
|
|
vec![]
|
|
}
|
|
}
|
|
_ => vec![],
|
|
}
|
|
}
|
|
|
|
pub fn check_static_fn_local_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.check_static_fn_local_names(symbol_table)
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.check_static_fn_local_names(symbol_table)
|
|
}
|
|
Expression::Call(call) => call.check_static_fn_local_names(symbol_table),
|
|
Expression::Identifier(identifier) => {
|
|
if let Some(diagnostic) = identifier.check_static_fn_local_name(symbol_table) {
|
|
vec![diagnostic]
|
|
} else {
|
|
vec![]
|
|
}
|
|
}
|
|
Expression::Integer(_) => {
|
|
vec![]
|
|
}
|
|
Expression::Double(_) => {
|
|
vec![]
|
|
}
|
|
Expression::String(_) => {
|
|
vec![]
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn type_check(
|
|
&mut self,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
) -> Result<(), Vec<Diagnostic>> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.type_check(symbol_table, types_table)
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
negative_expression.type_check(symbol_table, types_table)
|
|
}
|
|
Expression::Call(call) => call.type_check(symbol_table, types_table),
|
|
Expression::Identifier(_) => Ok(()),
|
|
Expression::Integer(_) => Ok(()),
|
|
Expression::Double(_) => Ok(()),
|
|
Expression::String(_) => Ok(()),
|
|
}
|
|
}
|
|
|
|
pub fn type_info<'a>(
|
|
&'a self,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &'a TypesTable,
|
|
) -> &'a TypeInfo {
|
|
match self {
|
|
Expression::Binary(binary_expression) => binary_expression.type_info(),
|
|
Expression::Negative(negative_expression) => negative_expression.type_info(),
|
|
Expression::Call(call) => call.return_type_info(symbol_table, types_table),
|
|
Expression::Identifier(identifier) => identifier.type_info(symbol_table, types_table),
|
|
Expression::Integer(integer_literal) => integer_literal.type_info(),
|
|
Expression::Double(double_literal) => double_literal.type_info(),
|
|
Expression::String(string_literal) => string_literal.type_info(),
|
|
}
|
|
}
|
|
|
|
pub fn source_range(&self) -> &SourceRange {
|
|
match self {
|
|
Expression::Binary(binary_expression) => binary_expression.source_range(),
|
|
Expression::Negative(negative_expression) => negative_expression.source_range(),
|
|
Expression::Call(call) => call.source_range(),
|
|
Expression::Identifier(identifier) => identifier.source_range(),
|
|
Expression::Integer(integer_literal) => integer_literal.source_range(),
|
|
Expression::Double(double_literal) => double_literal.source_range(),
|
|
Expression::String(string_literal) => string_literal.source_range(),
|
|
}
|
|
}
|
|
|
|
pub fn to_ir_operation(
|
|
&self,
|
|
builder: &mut IrBuilder,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
) -> IrOperation {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
binary_expression.to_ir_operation(builder, symbol_table, types_table)
|
|
}
|
|
Expression::Call(call) => {
|
|
IrOperation::Call(call.to_ir(builder, symbol_table, types_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.ir_expression(builder, symbol_table, types_table))
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
IrOperation::Load(negative_expression.to_ir(builder, symbol_table, types_table))
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn to_ir_expression(
|
|
&self,
|
|
builder: &mut IrBuilder,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
) -> Option<IrExpression> {
|
|
match self {
|
|
Expression::Binary(binary_expression) => {
|
|
Some(binary_expression.to_ir_expression(builder, symbol_table, types_table))
|
|
}
|
|
Expression::Negative(negative_expression) => {
|
|
Some(negative_expression.to_ir(builder, symbol_table, types_table))
|
|
}
|
|
Expression::Call(call) => {
|
|
let ir_call = call.to_ir(builder, symbol_table, types_table);
|
|
if matches!(
|
|
call.return_type_info(symbol_table, types_table),
|
|
TypeInfo::Void
|
|
) {
|
|
builder
|
|
.current_block_mut()
|
|
.add_statement(IrStatement::Call(ir_call));
|
|
None
|
|
} else {
|
|
let t_var = IrVariable::new_vr(
|
|
builder.new_t_var().into(),
|
|
builder.current_block().id(),
|
|
call.return_type_info(symbol_table, types_table),
|
|
);
|
|
let as_rc = Rc::new(RefCell::new(t_var));
|
|
let assign = IrAssign::new(as_rc.clone(), IrOperation::Call(ir_call));
|
|
builder
|
|
.current_block_mut()
|
|
.add_statement(IrStatement::Assign(assign));
|
|
Some(IrExpression::Variable(as_rc))
|
|
}
|
|
}
|
|
Expression::Identifier(identifier) => {
|
|
Some(identifier.ir_expression(builder, symbol_table, types_table))
|
|
}
|
|
Expression::Integer(integer_literal) => {
|
|
Some(IrExpression::Int(integer_literal.value()))
|
|
}
|
|
Expression::Double(double_literal) => {
|
|
Some(IrExpression::Double(double_literal.value()))
|
|
}
|
|
Expression::String(string_literal) => {
|
|
Some(IrExpression::String(string_literal.content().into()))
|
|
}
|
|
}
|
|
}
|
|
}
|