Work on new name resolve methods WIP.
This commit is contained in:
parent
fe8ab3601c
commit
3a75a0c8e8
@ -1,7 +1,9 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
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, Diagnostics, SecondaryLabel};
|
||||
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;
|
||||
@ -10,6 +12,8 @@ use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::types_table::TypesTable;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct AssignStatement {
|
||||
destination: Box<Expression>,
|
||||
@ -33,6 +37,53 @@ impl AssignStatement {
|
||||
self.value.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for expression in [self.destination.as_ref(), self.value.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_static(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.value
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
match self.destination.as_ref() {
|
||||
Expression::Identifier(identifier) => {
|
||||
let (ns, mut ds) =
|
||||
identifier.resolve_name_ctor_destination(symbol_table, initialized_fields);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
_ => {
|
||||
// no-op, because this is a non-L-Value and will be caught during type checking.
|
||||
}
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::error_codes::BINARY_INCOMPATIBLE_TYPES;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
||||
@ -79,6 +81,53 @@ impl BinaryExpression {
|
||||
self.rhs.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_static(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_field_init(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_field_init(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for expression in [self.lhs.as_ref(), self.rhs.as_ref()] {
|
||||
let (ns, mut ds) = expression.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::class_has_no_constructor;
|
||||
use crate::ir::ir_call::IrCall;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -43,6 +45,75 @@ impl Call {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self.callee.resolve_names_static(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for argument in &self.arguments {
|
||||
let (ns, mut ds) = argument.resolve_names_static(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_field_init(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.callee
|
||||
.resolve_names_field_init(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for argument in &self.arguments {
|
||||
let (ns, mut ds) = argument.resolve_names_field_init(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.callee
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for argument in &self.arguments {
|
||||
let (ns, mut ds) = argument.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -6,9 +6,13 @@ use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::function::Function;
|
||||
use crate::ast::generic_parameter::GenericParameter;
|
||||
use crate::ast::helpers::{collect_diagnostics_mut, collect_diagnostics_single, resolve_ctor_name};
|
||||
use crate::ast::helpers::{
|
||||
collect_diagnostics_mut, collect_diagnostics_single, insert_resolved_names_into,
|
||||
resolve_ctor_name,
|
||||
};
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::error_codes::{FIELD_MULTIPLE_INIT, FIELD_UNINIT};
|
||||
use crate::ir::ir_class::{IrClass, IrField};
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
@ -24,6 +28,7 @@ use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Class {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
generic_parameters: Vec<GenericParameter>,
|
||||
@ -37,6 +42,7 @@ pub struct Class {
|
||||
|
||||
impl Class {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
generic_parameters: Vec<GenericParameter>,
|
||||
@ -45,6 +51,7 @@ impl Class {
|
||||
functions: Vec<Function>,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
generic_parameters,
|
||||
@ -147,6 +154,39 @@ impl Class {
|
||||
all_symbols
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for generic_parameter in &self.generic_parameters {
|
||||
let (ns, mut ds) = generic_parameter.resolve_names(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
let self_class_symbol = self.get_class_symbol_owned(symbol_table);
|
||||
let mut initialized_fields = HashSet::new();
|
||||
|
||||
for field in &self.fields {
|
||||
let (ns, mut ds) = field.resolve_names(symbol_table, &self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
initialized_fields.insert(field.declared_name_owned());
|
||||
}
|
||||
|
||||
if let Some(constructor) = &self.constructor {
|
||||
let (ns, mut ds) = constructor.resolve_names(
|
||||
symbol_table,
|
||||
self_class_symbol.as_ref(),
|
||||
&mut initialized_fields,
|
||||
);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
|
||||
@ -169,6 +209,13 @@ impl Class {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
fn get_self_class_symbol<'a>(&self, symbol_table: &'a SymbolTable) -> &'a ClassSymbol {
|
||||
symbol_table
|
||||
.get_class_symbol(self.scope_id.unwrap(), &self.declared_name)
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
fn get_class_symbol_owned(&self, symbol_table: &SymbolTable) -> Rc<ClassSymbol> {
|
||||
symbol_table
|
||||
.get_class_symbol(self.scope_id.unwrap(), &self.declared_name)
|
||||
|
||||
@ -3,8 +3,9 @@ use crate::ast::extern_function::ExternFunction;
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::function::Function;
|
||||
use crate::ast::helpers::collect_diagnostics_into_mut;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::compile_pipeline::FileId;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_class::IrClass;
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
use crate::symbol::Symbol;
|
||||
@ -12,6 +13,7 @@ use crate::symbol_table::SymbolTable;
|
||||
use crate::symbol_table::util::try_insert_symbols_into;
|
||||
use crate::types_table::TypesTable;
|
||||
use crate::{diagnostics_result, handle_diagnostics};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct CompilationUnit {
|
||||
file_id: Option<FileId>,
|
||||
@ -106,6 +108,37 @@ impl CompilationUnit {
|
||||
diagnostics_result!(diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &mut SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for function in &self.functions {
|
||||
let (ns, mut ds) = function.resolve_names_static(symbol_table);
|
||||
for (node_id, symbol) in ns.into_iter() {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for extern_function in &self.extern_functions {
|
||||
let (ns, mut ds) = extern_function.resolve_names_static(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for class in &self.classes {
|
||||
let (ns, mut ds) = class.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &mut SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||
let mut diagnostics = vec![];
|
||||
for class in &self.classes {
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::field::Field;
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::helpers::{collect_parameter_symbols_into, resolve_ctor_name};
|
||||
use crate::ast::helpers::{
|
||||
collect_parameter_symbols_into, insert_resolved_names_into, resolve_ctor_name,
|
||||
};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_allocate::IrAllocate;
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -26,6 +29,7 @@ use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::ops::Neg;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -94,6 +98,31 @@ impl Constructor {
|
||||
(constructor_symbol, all_symbols)
|
||||
}
|
||||
|
||||
pub fn resolve_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for parameter in &self.parameters {
|
||||
let (ns, mut ds) = parameter.resolve_names(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
for statement in &self.statements {
|
||||
let (ns, mut ds) =
|
||||
statement.resolve_names_ctor(symbol_table, self_class_symbol, initialized_fields);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
for parameter in &self.parameters {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::binary_expression::BinaryExpression;
|
||||
use crate::ast::call::Call;
|
||||
use crate::ast::double_literal::DoubleLiteral;
|
||||
@ -6,7 +7,7 @@ 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::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
use crate::ir::ir_operation::IrOperation;
|
||||
@ -49,6 +50,62 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_static(symbol_table)
|
||||
}
|
||||
Expression::Negative(negative_expression) => {
|
||||
negative_expression.resolve_names_static(symbol_table)
|
||||
}
|
||||
Expression::Call(call) => call.resolve_names_static(symbol_table),
|
||||
Expression::Identifier(identifier) => identifier.resolve_name_static(symbol_table),
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_field_init(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Negative(negative_expression) => {
|
||||
negative_expression.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Call(call) => {
|
||||
call.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_name_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
match self {
|
||||
Expression::Binary(binary_expression) => {
|
||||
binary_expression.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Negative(negative_expression) => {
|
||||
negative_expression.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
Expression::Call(call) => call.resolve_names_ctor(symbol_table, self_class_symbol),
|
||||
Expression::Identifier(identifier) => {
|
||||
identifier.resolve_name_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
_ => (NamesTable::new(), Diagnostics::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_return::IrReturn;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
@ -27,6 +28,19 @@ impl ExpressionStatement {
|
||||
self.expression.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
self.expression.resolve_names_static(symbol_table)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
self.expression
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
pub fn check_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::helpers::{collect_diagnostics_into_mut, collect_parameter_symbols_into};
|
||||
use crate::ast::helpers::{
|
||||
collect_diagnostics_into_mut, collect_parameter_symbols_into, resolve_parameter_names_into,
|
||||
};
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
@ -13,6 +16,7 @@ use crate::{diagnostics_result, handle_diagnostics};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct ExternFunction {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
parameters: Vec<Parameter>,
|
||||
@ -22,12 +26,14 @@ pub struct ExternFunction {
|
||||
|
||||
impl ExternFunction {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
parameters: Vec<Parameter>,
|
||||
return_type: TypeUse,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: name.into(),
|
||||
declared_name_source_range,
|
||||
parameters,
|
||||
@ -74,6 +80,28 @@ impl ExternFunction {
|
||||
(function_symbol, all_symbols)
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
resolve_parameter_names_into(
|
||||
&self.parameters,
|
||||
symbol_table,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self.return_type.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
for parameter in &self.parameters {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::field_has_no_type_or_init;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
@ -79,6 +81,30 @@ impl Field {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
if let Some(type_use) = &self.declared_type {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
if let Some(initializer) = &self.initializer {
|
||||
let (ns, mut ds) = initializer.resolve_names_field_init(symbol_table, class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
if let Some(type_use) = &self.declared_type {
|
||||
@ -87,6 +113,7 @@ impl Field {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -2,13 +2,14 @@ use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::fqn_util::fqn_parts_to_string;
|
||||
use crate::ast::helpers::{
|
||||
collect_diagnostics_into_enumerated_mut, collect_diagnostics_into_mut,
|
||||
collect_parameter_symbols_into,
|
||||
collect_parameter_symbols_into, resolve_parameter_names_into,
|
||||
};
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_function::IrFunction;
|
||||
use crate::ir::ir_parameter::IrParameter;
|
||||
use crate::ir::ir_parameter_or_variable::IrParameterOrVariable;
|
||||
@ -24,6 +25,7 @@ use std::ops::Neg;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Function {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
is_public: bool,
|
||||
@ -35,6 +37,7 @@ pub struct Function {
|
||||
|
||||
impl Function {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
is_public: bool,
|
||||
@ -43,6 +46,7 @@ impl Function {
|
||||
statements: Vec<Statement>,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
is_public,
|
||||
@ -108,6 +112,51 @@ impl Function {
|
||||
(function_symbol, all_symbols)
|
||||
}
|
||||
|
||||
fn resolve_names_common(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
resolve_parameter_names_into(
|
||||
&self.parameters,
|
||||
symbol_table,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
|
||||
if let Some(type_use) = &self.return_type {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let (mut names_table, mut diagnostics) = self.resolve_names_common(symbol_table);
|
||||
|
||||
for statement in &self.statements {
|
||||
let (ns, mut ds) = statement.resolve_names_static(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_method(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let (names_table, diagnostics) = self.resolve_names_common(symbol_table);
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = Vec::new();
|
||||
for parameter in &self.parameters {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
@ -47,6 +49,19 @@ impl GenericParameter {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
for type_use in &self.extends {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.extends
|
||||
.iter()
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::fqn_context::FqnContext;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostics_result;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// Iterates through all `ts`, running the `f` function, and pushing returned `Diagnostic`s
|
||||
@ -104,3 +106,24 @@ pub fn collect_parameter_symbols_into(
|
||||
parameter_symbols.push(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_parameter_names_into(
|
||||
parameters: &[Parameter],
|
||||
symbol_table: &SymbolTable,
|
||||
names_table: &mut NamesTable,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
for parameter in parameters {
|
||||
let (ns, mut ds) = parameter.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
names_table.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_resolved_names_into(source: NamesTable, destination: &mut NamesTable) {
|
||||
for (node_id, symbol) in source {
|
||||
destination.insert(node_id, symbol);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::ir_util::get_or_init_field_pointer_variable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::{
|
||||
outer_class_field_usage, outer_class_method_usage, self_constructor_used_in_init,
|
||||
self_field_used_in_init, self_method_used_in_init, symbol_not_found,
|
||||
cannot_reassign_immutable_field, not_assignable, outer_class_field_usage,
|
||||
outer_class_method_usage, self_constructor_used_in_init, self_field_used_in_init,
|
||||
self_method_used_in_init, symbol_not_found,
|
||||
};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -12,6 +14,7 @@ use crate::ir::ir_read_field::IrReadField;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_variable::IrVariable;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::expressible_symbol::ExpressibleSymbol;
|
||||
use crate::symbol::field_symbol::FieldSymbol;
|
||||
@ -20,17 +23,20 @@ use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Identifier {
|
||||
name: String,
|
||||
node_id: NodeId,
|
||||
name: Rc<str>,
|
||||
source_range: SourceRange,
|
||||
scope_id: Option<usize>,
|
||||
}
|
||||
|
||||
impl Identifier {
|
||||
pub fn new(name: &str, source_range: SourceRange) -> Self {
|
||||
pub fn new(node_id: NodeId, name: &str, source_range: SourceRange) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
name: name.into(),
|
||||
source_range,
|
||||
scope_id: None,
|
||||
@ -49,7 +55,222 @@ impl Identifier {
|
||||
self.scope_id.unwrap()
|
||||
}
|
||||
|
||||
pub fn resolve_name_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
match symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name) {
|
||||
None => {
|
||||
diagnostics.push(symbol_not_found(&self.name, &self.source_range));
|
||||
}
|
||||
Some(expressible_symbol) => {
|
||||
names_table.insert(self.node_id, expressible_symbol.into_symbol());
|
||||
}
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_name_field_init(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
match symbol {
|
||||
ExpressibleSymbol::Class(class_symbol) => {
|
||||
self.init_referring_to_class(
|
||||
self_class_symbol,
|
||||
&class_symbol,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Field(field_symbol) => {
|
||||
self.init_referring_to_field(
|
||||
self_class_symbol,
|
||||
&field_symbol,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
self.init_referring_to_function(
|
||||
self_class_symbol,
|
||||
&function_symbol,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Parameter(_) => {
|
||||
// Cannot get here, because classes cannot currently be declared in functions
|
||||
unreachable!()
|
||||
}
|
||||
ExpressibleSymbol::Variable(_) => {
|
||||
// Cannot get here, as classes cannot currently be declared in functions
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diagnostics.push(symbol_not_found(&self.name, &self.source_range));
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_name_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
match symbol {
|
||||
ExpressibleSymbol::Class(class_symbol) => {
|
||||
self.init_referring_to_class(
|
||||
self_class_symbol,
|
||||
&class_symbol,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Field(field_symbol) => {
|
||||
self.init_referring_to_field(
|
||||
self_class_symbol,
|
||||
&field_symbol,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Function(function_symbol) => {
|
||||
self.init_referring_to_function(
|
||||
self_class_symbol,
|
||||
&function_symbol,
|
||||
&mut names_table,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => {
|
||||
names_table.insert(self.node_id, Symbol::Parameter(parameter_symbol));
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
names_table.insert(self.node_id, Symbol::Variable(variable_symbol));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diagnostics.push(symbol_not_found(&self.name, &self.source_range));
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_name_ctor_destination(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
let mut names_table = NamesTable::new();
|
||||
|
||||
let symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name);
|
||||
if let Some(symbol) = symbol {
|
||||
match symbol {
|
||||
ExpressibleSymbol::Class(_) => {
|
||||
// error
|
||||
diagnostics.push(not_assignable(&self.name, &self.source_range));
|
||||
}
|
||||
ExpressibleSymbol::Field(field_symbol) => {
|
||||
// ok if field has not been initialized yet OR field is mutable
|
||||
if !initialized_fields.contains(&self.name) {
|
||||
initialized_fields.insert(self.name.clone());
|
||||
names_table.insert(self.node_id, Symbol::Field(field_symbol));
|
||||
} else if !field_symbol.is_mut() {
|
||||
// error since we are trying to reassign an immutable field
|
||||
diagnostics.push(cannot_reassign_immutable_field(&self.source_range));
|
||||
} else {
|
||||
// mut is ok
|
||||
names_table.insert(self.node_id, Symbol::Field(field_symbol));
|
||||
}
|
||||
}
|
||||
ExpressibleSymbol::Function(_) => {
|
||||
diagnostics.push(not_assignable(&self.name, &self.source_range));
|
||||
}
|
||||
ExpressibleSymbol::Parameter(_) => {
|
||||
// assigning to parameter is an error
|
||||
// we may in the future allow mut on parameters, but it's probably pointless
|
||||
diagnostics.push(not_assignable(&self.name, &self.source_range));
|
||||
}
|
||||
ExpressibleSymbol::Variable(variable_symbol) => {
|
||||
// ok
|
||||
names_table.insert(self.node_id, Symbol::Variable(variable_symbol));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
diagnostics.push(symbol_not_found(&self.name, &self.source_range));
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
fn init_referring_to_class(
|
||||
&self,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
class_symbol: &Rc<ClassSymbol>,
|
||||
names_table: &mut NamesTable,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
// Check against recursively constructing this class.
|
||||
// This is not future-proof, as we will eventually allow reference to the self class, which
|
||||
// would (theoretically) be assigned to an instance field.
|
||||
if self_class_symbol == class_symbol.as_ref() {
|
||||
diagnostics.push(self_constructor_used_in_init(&self.source_range));
|
||||
} else {
|
||||
names_table.insert(self.node_id, Symbol::Class(class_symbol.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn init_referring_to_field(
|
||||
&self,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
field_symbol: &FieldSymbol,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
if self_class_symbol
|
||||
.fields()
|
||||
.contains_key(field_symbol.declared_name())
|
||||
{
|
||||
diagnostics.push(self_field_used_in_init(&self.source_range));
|
||||
} else {
|
||||
diagnostics.push(outer_class_field_usage(&self.source_range));
|
||||
}
|
||||
}
|
||||
|
||||
fn init_referring_to_function(
|
||||
&self,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
function_symbol: &Rc<FunctionSymbol>,
|
||||
names_table: &mut NamesTable,
|
||||
diagnostics: &mut Diagnostics,
|
||||
) {
|
||||
if self_class_symbol
|
||||
.functions()
|
||||
.contains_key(function_symbol.declared_name())
|
||||
{
|
||||
diagnostics.push(self_method_used_in_init(&self.source_range));
|
||||
} else if function_symbol.is_method() {
|
||||
diagnostics.push(outer_class_method_usage(&self.source_range));
|
||||
} else {
|
||||
names_table.insert(self.node_id, Symbol::Function(function_symbol.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
/// Check against recursively constructing this class.
|
||||
#[deprecated]
|
||||
fn check_self_constructor_use(
|
||||
&self,
|
||||
context_class_symbol: &ClassSymbol,
|
||||
@ -65,6 +286,7 @@ impl Identifier {
|
||||
}
|
||||
|
||||
/// Check against using this or outer class' bare fields.
|
||||
#[deprecated]
|
||||
fn check_self_or_outer_field_use(
|
||||
&self,
|
||||
context_class_symbol: &ClassSymbol,
|
||||
@ -82,6 +304,7 @@ impl Identifier {
|
||||
}
|
||||
|
||||
/// Check against using self or outer class methods.
|
||||
#[deprecated]
|
||||
fn check_self_or_outer_method_use(
|
||||
&self,
|
||||
context_class_symbol: &ClassSymbol,
|
||||
@ -101,6 +324,7 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated]
|
||||
pub fn check_name_as_field_initializer(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::helpers::insert_resolved_names_into;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_statement::IrStatement;
|
||||
use crate::ir::ir_variable::IrVariable;
|
||||
@ -73,6 +75,49 @@ impl LetStatement {
|
||||
try_insert_symbol_into(Symbol::Variable(variable_symbol), symbol_table).err()
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self.initializer.resolve_names_static(symbol_table);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
let mut names_table = NamesTable::new();
|
||||
let mut diagnostics = Diagnostics::new();
|
||||
|
||||
{
|
||||
let (ns, mut ds) = self
|
||||
.initializer
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol);
|
||||
insert_resolved_names_into(ns, &mut names_table);
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
if let Some(diagnostic) = self.make_and_insert_variable_symbol(symbol_table) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
(names_table, diagnostics)
|
||||
}
|
||||
|
||||
pub fn analyze_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
use crate::symbol::Symbol;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub mod assign_statement;
|
||||
pub mod binary_expression;
|
||||
pub mod call;
|
||||
@ -25,3 +28,6 @@ pub mod parameter;
|
||||
pub mod statement;
|
||||
pub mod string_literal;
|
||||
pub mod type_use;
|
||||
|
||||
pub type NodeId = usize;
|
||||
pub type NamesTable = HashMap<NodeId, Symbol>;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::expression::Expression;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::ir::ir_assign::IrAssign;
|
||||
use crate::ir::ir_binary_operation::{IrBinaryOperation, IrBinaryOperator};
|
||||
use crate::ir::ir_expression::IrExpression;
|
||||
@ -46,6 +47,28 @@ impl NegativeExpression {
|
||||
self.operand.init_scopes(symbol_table, container_scope);
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
self.operand.resolve_names_static(symbol_table)
|
||||
}
|
||||
|
||||
pub fn resolve_names_field_init(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
self.operand
|
||||
.resolve_names_field_init(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
self.operand
|
||||
.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
|
||||
pub fn check_field_initializer_names(
|
||||
&self,
|
||||
symbol_table: &SymbolTable,
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::type_use::TypeUse;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
@ -48,6 +49,10 @@ impl Parameter {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
self.type_use.resolve_names(symbol_table)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.type_use.check_names(symbol_table)
|
||||
}
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
use crate::ast::NamesTable;
|
||||
use crate::ast::assign_statement::AssignStatement;
|
||||
use crate::ast::expression_statement::ExpressionStatement;
|
||||
use crate::ast::ir_builder::IrBuilder;
|
||||
use crate::ast::let_statement::LetStatement;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub enum Statement {
|
||||
Let(LetStatement),
|
||||
@ -29,6 +32,42 @@ impl Statement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_static(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => let_statement.resolve_names_static(symbol_table),
|
||||
Statement::Expression(expression_statement) => {
|
||||
expression_statement.resolve_names_static(symbol_table)
|
||||
}
|
||||
Statement::Assign(assign_statement) => {
|
||||
assign_statement.resolve_names_static(symbol_table)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names_ctor(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
self_class_symbol: &ClassSymbol,
|
||||
initialized_fields: &mut HashSet<Rc<str>>,
|
||||
) -> (NamesTable, Diagnostics) {
|
||||
match self {
|
||||
Statement::Let(let_statement) => {
|
||||
let_statement.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
Statement::Expression(expression_statement) => {
|
||||
expression_statement.resolve_names_ctor(symbol_table, self_class_symbol)
|
||||
}
|
||||
Statement::Assign(assign_statement) => assign_statement.resolve_names_ctor(
|
||||
symbol_table,
|
||||
self_class_symbol,
|
||||
initialized_fields,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn analyze_constructor_local_names(
|
||||
&self,
|
||||
symbol_table: &mut SymbolTable,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::diagnostic::Diagnostic;
|
||||
use crate::ast::{NamesTable, NodeId};
|
||||
use crate::diagnostic::{Diagnostic, Diagnostics};
|
||||
use crate::diagnostic_factories::symbol_not_found;
|
||||
use crate::error_codes::INCORRECT_GENERIC_ARGUMENTS;
|
||||
use crate::source_range::SourceRange;
|
||||
@ -7,9 +8,11 @@ use crate::symbol_table::SymbolTable;
|
||||
use crate::type_info::TypeInfo;
|
||||
use crate::types_table::TypesTable;
|
||||
use crate::{diagnostics_result, handle_diagnostics, maybe_return_diagnostics};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct TypeUse {
|
||||
node_id: NodeId,
|
||||
declared_name: Rc<str>,
|
||||
declared_name_source_range: SourceRange,
|
||||
generic_arguments: Vec<TypeUse>,
|
||||
@ -18,11 +21,13 @@ pub struct TypeUse {
|
||||
|
||||
impl TypeUse {
|
||||
pub fn new(
|
||||
node_id: NodeId,
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
generic_arguments: Vec<TypeUse>,
|
||||
) -> Self {
|
||||
Self {
|
||||
node_id,
|
||||
declared_name: declared_name.into(),
|
||||
declared_name_source_range,
|
||||
generic_arguments,
|
||||
@ -41,6 +46,35 @@ impl TypeUse {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NamesTable, Diagnostics) {
|
||||
let mut diagnostics = Vec::new();
|
||||
let mut resolved_names = HashMap::new();
|
||||
|
||||
// resolve this name
|
||||
match symbol_table.find_type_symbol(self.scope_id.unwrap(), &self.declared_name) {
|
||||
None => {
|
||||
diagnostics.push(symbol_not_found(
|
||||
&self.declared_name,
|
||||
&self.declared_name_source_range,
|
||||
));
|
||||
}
|
||||
Some(type_symbol) => {
|
||||
resolved_names.insert(self.node_id, type_symbol.into_symbol());
|
||||
}
|
||||
}
|
||||
|
||||
// check generic args
|
||||
for type_use in &self.generic_arguments {
|
||||
let (ns, mut ds) = type_use.resolve_names(symbol_table);
|
||||
for (node_id, symbol) in ns {
|
||||
resolved_names.insert(node_id, symbol);
|
||||
}
|
||||
diagnostics.append(&mut ds);
|
||||
}
|
||||
|
||||
(resolved_names, diagnostics)
|
||||
}
|
||||
|
||||
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
|
||||
|
||||
@ -43,5 +43,15 @@ pub fn compile_compilation_units(inputs: &HashMap<FileId, &str>) -> Result<(), D
|
||||
.collect::<Vec<_>>();
|
||||
try_insert_symbols_into(all_symbols, &mut symbol_table)?;
|
||||
|
||||
// now we can just finish each compilation unit, since we have the symbols
|
||||
let mut diagnostics = Vec::new();
|
||||
for compilation_unit in compilation_units.values() {
|
||||
let (resolved_names, mut ds) = compilation_unit.resolve_names(&mut symbol_table);
|
||||
if !ds.is_empty() {
|
||||
diagnostics.append(&mut ds);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use crate::diagnostic::{Diagnostic, SecondaryLabel};
|
||||
use crate::error_codes::{
|
||||
CLASS_NO_CONSTRUCTOR, FIELD_NO_TYPE_OR_INIT, OUTER_CLASS_FIELD_USED_IN_INIT,
|
||||
OUTER_CLASS_METHOD_USED_IN_INIT, SELF_CONSTRUCTOR_USED_IN_INIT, SELF_FIELD_USED_IN_INIT,
|
||||
SELF_METHOD_USED_IN_INIT, SYMBOL_ALREADY_DECLARED, SYMBOL_NOT_FOUND,
|
||||
ASSIGN_LHS_IMMUTABLE, CLASS_NO_CONSTRUCTOR, FIELD_NO_TYPE_OR_INIT, NOT_ASSIGNABLE,
|
||||
OUTER_CLASS_FIELD_USED_IN_INIT, OUTER_CLASS_METHOD_USED_IN_INIT, SELF_CONSTRUCTOR_USED_IN_INIT,
|
||||
SELF_FIELD_USED_IN_INIT, SELF_METHOD_USED_IN_INIT, SYMBOL_ALREADY_DECLARED, SYMBOL_NOT_FOUND,
|
||||
};
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
@ -117,3 +117,21 @@ pub fn class_has_no_constructor(name: &str, source_range: &SourceRange) -> Diagn
|
||||
)
|
||||
.with_error_code(CLASS_NO_CONSTRUCTOR)
|
||||
}
|
||||
|
||||
pub fn not_assignable(name: &str, source_range: &SourceRange) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
&format!("Symbol {} is not assignable.", name),
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(NOT_ASSIGNABLE)
|
||||
}
|
||||
|
||||
pub fn cannot_reassign_immutable_field(source_range: &SourceRange) -> Diagnostic {
|
||||
Diagnostic::new(
|
||||
"Cannot reassign an immutable field.",
|
||||
source_range.start(),
|
||||
source_range.end(),
|
||||
)
|
||||
.with_error_code(ASSIGN_LHS_IMMUTABLE)
|
||||
}
|
||||
|
||||
@ -19,3 +19,4 @@ pub const OUTER_CLASS_FIELD_USED_IN_INIT: ErrorCode = 26;
|
||||
pub const OUTER_CLASS_METHOD_USED_IN_INIT: ErrorCode = 27;
|
||||
pub const FIELD_NO_TYPE_OR_INIT: ErrorCode = 28;
|
||||
pub const CLASS_NO_CONSTRUCTOR: ErrorCode = 29;
|
||||
pub const NOT_ASSIGNABLE: ErrorCode = 30;
|
||||
|
||||
@ -425,6 +425,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if let Some(identifier) = maybe_identifier {
|
||||
let function = Function::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
is_public,
|
||||
@ -466,6 +467,7 @@ impl<'a> Parser<'a> {
|
||||
&& let Some(type_use) = return_type
|
||||
{
|
||||
let extern_function = ExternFunction::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
parameters,
|
||||
@ -539,6 +541,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if let Some(identifier) = maybe_identifier {
|
||||
let class = Class::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
generic_parameters,
|
||||
@ -641,6 +644,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
if let Some(identifier) = maybe_identifier {
|
||||
let type_use = TypeUse::new(
|
||||
self.next_node_id(),
|
||||
self.token_text(&identifier),
|
||||
SourceRange::new(identifier.start(), identifier.end()),
|
||||
generic_arguments,
|
||||
@ -1312,7 +1316,11 @@ impl<'a> Parser<'a> {
|
||||
let source_range = SourceRange::new(current.start(), current.end());
|
||||
diagnostics.append(&mut self.advance());
|
||||
(
|
||||
Expression::Identifier(Identifier::new(declared_name, source_range)),
|
||||
Expression::Identifier(Identifier::new(
|
||||
self.next_node_id(),
|
||||
declared_name,
|
||||
source_range,
|
||||
)),
|
||||
diagnostics,
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::field_symbol::FieldSymbol;
|
||||
use crate::symbol::function_symbol::FunctionSymbol;
|
||||
@ -15,6 +16,16 @@ pub enum ExpressibleSymbol {
|
||||
}
|
||||
|
||||
impl ExpressibleSymbol {
|
||||
pub fn into_symbol(self) -> Symbol {
|
||||
match self {
|
||||
ExpressibleSymbol::Class(class_symbol) => Symbol::Class(class_symbol),
|
||||
ExpressibleSymbol::Field(field_symbol) => Symbol::Field(field_symbol),
|
||||
ExpressibleSymbol::Function(function_symbol) => Symbol::Function(function_symbol),
|
||||
ExpressibleSymbol::Parameter(parameter_symbol) => Symbol::Parameter(parameter_symbol),
|
||||
ExpressibleSymbol::Variable(variable_symbol) => Symbol::Variable(variable_symbol),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source_range(&self) -> Option<&SourceRange> {
|
||||
match self {
|
||||
ExpressibleSymbol::Class(class_symbol) => class_symbol.declared_name_source_range(),
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::symbol::Symbol;
|
||||
use crate::symbol::class_symbol::ClassSymbol;
|
||||
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
|
||||
use std::rc::Rc;
|
||||
@ -6,3 +7,14 @@ pub enum TypeSymbol {
|
||||
Class(Rc<ClassSymbol>),
|
||||
GenericParameter(Rc<GenericParameterSymbol>),
|
||||
}
|
||||
|
||||
impl TypeSymbol {
|
||||
pub fn into_symbol(self) -> Symbol {
|
||||
match self {
|
||||
TypeSymbol::Class(class_symbol) => Symbol::Class(class_symbol),
|
||||
TypeSymbol::GenericParameter(generic_parameter_symbol) => {
|
||||
Symbol::GenericParameter(generic_parameter_symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user