Work on new name resolve methods WIP.

This commit is contained in:
Jesse Brault 2026-04-06 20:43:30 -05:00
parent fe8ab3601c
commit 3a75a0c8e8
26 changed files with 960 additions and 31 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -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,

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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 {

View File

@ -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()

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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>;

View File

@ -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,

View File

@ -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)
}

View File

@ -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,

View File

@ -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();

View File

@ -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(())
}

View File

@ -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)
}

View File

@ -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;

View File

@ -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,
)
}

View File

@ -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(),

View File

@ -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)
}
}
}
}