Flesh out gather and resolve, add todos, refactor a bit.

This commit is contained in:
Jesse Brault 2025-05-20 10:56:47 -05:00
parent 88270e0cdd
commit 4c68d0dc28
8 changed files with 927 additions and 317 deletions

View File

@ -1,3 +1 @@
use std::core::println;
use std::core::*;
use std::core::{print, println}; use std::core::{print, println};

View File

@ -10,7 +10,8 @@ pub mod build;
pub mod named; pub mod named;
pub mod pretty_print; pub mod pretty_print;
pub mod unparse; pub mod unparse;
// Operators
/* Operators */
#[derive(Debug)] #[derive(Debug)]
pub enum Operator { pub enum Operator {
@ -56,19 +57,13 @@ pub enum SuffixUnaryOperator {
/* Names */ /* Names */
#[derive(Debug, Clone)]
pub enum SavedSymbol {
Declaration(Symbol),
Linking(Symbol),
}
#[derive(Debug)] #[derive(Debug)]
pub struct Identifier { pub struct Identifier {
pub name: String, name: String,
pub file_id: usize, file_id: usize,
pub range: Range<usize>, range: Range<usize>,
scope_id: Option<usize>, scope_id: Option<usize>,
saved_symbol: Option<SavedSymbol>, saved_symbol: Option<Symbol>,
} }
impl Identifier { impl Identifier {
@ -81,31 +76,15 @@ impl Identifier {
saved_symbol: None, saved_symbol: None,
} }
} }
pub fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
pub fn scope_id(&self) -> Option<usize> {
self.scope_id
}
pub fn set_saved_symbol(&mut self, saved_symbol: SavedSymbol) {
self.saved_symbol = Some(saved_symbol);
}
pub fn saved_symbol(&self) -> Option<SavedSymbol> {
self.saved_symbol.clone()
}
} }
#[derive(Debug)] #[derive(Debug)]
pub struct FullyQualifiedName { pub struct FullyQualifiedName {
pub identifiers: Vec<Identifier>, identifiers: Vec<Identifier>,
pub file_id: usize, file_id: usize,
pub range: Range<usize>, range: Range<usize>,
scope_id: Option<usize>, scope_id: Option<usize>,
symbol: Option<Symbol>, saved_symbol: Option<Symbol>,
} }
impl FullyQualifiedName { impl FullyQualifiedName {
@ -115,24 +94,25 @@ impl FullyQualifiedName {
range, range,
file_id, file_id,
scope_id: None, scope_id: None,
symbol: None, saved_symbol: None,
} }
} }
pub fn set_scope_id(&mut self, scope_id: usize) { pub fn last(&self) -> &Identifier {
self.scope_id = Some(scope_id); &self.identifiers[self.identifiers.len() - 1]
} }
pub fn scope_id(&self) -> Option<usize> { pub fn last_mut(&mut self) -> &mut Identifier {
self.scope_id let last_index = self.identifiers.len() - 1;
&mut self.identifiers[last_index]
} }
pub fn set_symbol(&mut self, symbol: Symbol) { pub fn len(&self) -> usize {
self.symbol = Some(symbol); self.identifiers.len()
} }
pub fn symbol(&self) -> &Option<Symbol> { pub fn is_single_identifier(&self) -> bool {
&self.symbol self.identifiers.len() == 1
} }
} }
@ -185,7 +165,7 @@ pub struct FunctionTypeUse {
pub return_type: ReturnType, pub return_type: ReturnType,
} }
// Generic arguments /* Generic arguments */
#[derive(Debug)] #[derive(Debug)]
pub struct GenericArguments(pub Vec<TypeUse>); pub struct GenericArguments(pub Vec<TypeUse>);
@ -319,7 +299,68 @@ pub struct CompilationUnit {
pub declarations: Vec<ModuleLevelDeclaration>, pub declarations: Vec<ModuleLevelDeclaration>,
} }
// Declarations allowed in each level /* Use Statement */
#[derive(Debug)]
pub struct UseStatement {
pub identifiers: Vec<Identifier>,
pub last: UseStatementLast,
pub file_id: usize,
pub range: Range<usize>,
}
impl UseStatement {
pub fn new(
identifiers: Vec<Identifier>,
last: UseStatementLast,
file_id: usize,
range: Range<usize>,
) -> Self {
UseStatement {
identifiers,
last,
file_id,
range,
}
}
pub fn base_name(&self) -> Cow<'_, str> {
use UseStatementLast::*;
if self.identifiers.is_empty() {
match &self.last {
Identifier(_) => Cow::from(""),
Star | Identifiers(_) => panic!(), // should never get here because of grammar
}
} else if self.identifiers.len() == 1 {
self.identifiers[0].name()
} else {
let mut acc = String::new();
for (i, identifier) in self.identifiers.iter().enumerate() {
acc.push_str(&identifier.name());
if i != self.identifiers.len() - 1 {
acc.push_str("::");
}
}
Cow::from(acc)
}
}
pub fn is_star(&self) -> bool {
match &self.last {
UseStatementLast::Star => true,
_ => false,
}
}
}
#[derive(Debug)]
pub enum UseStatementLast {
Identifier(Rc<RefCell<Identifier>>),
Identifiers(Vec<Rc<RefCell<Identifier>>>),
Star,
}
/* Declarations allowed in each level */
#[derive(Debug)] #[derive(Debug)]
pub enum ModuleLevelDeclaration { pub enum ModuleLevelDeclaration {
@ -351,7 +392,7 @@ pub enum ClassLevelDeclaration {
Field(FieldDeclaration), Field(FieldDeclaration),
} }
// Declarations /* Main Declarations */
#[derive(Debug)] #[derive(Debug)]
pub struct ModuleDeclaration { pub struct ModuleDeclaration {
@ -379,7 +420,7 @@ pub struct ClassDeclaration {
pub declarations: Vec<ClassLevelDeclaration>, pub declarations: Vec<ClassLevelDeclaration>,
} }
// Function declarations and components /* Function declarations and components */
#[derive(Debug)] #[derive(Debug)]
pub struct FunctionDefinition { pub struct FunctionDefinition {
@ -449,7 +490,7 @@ pub enum FunctionBody {
Alias(Identifier), Alias(Identifier),
} }
// Class components /* Class components */
#[derive(Debug)] #[derive(Debug)]
pub struct ClassConstructor(pub Vec<ClassConstructorParameter>); pub struct ClassConstructor(pub Vec<ClassConstructorParameter>);
@ -474,72 +515,7 @@ pub struct FieldDeclaration {
pub declared_type: TypeUse, pub declared_type: TypeUse,
} }
// Statements /* Statements */
#[derive(Debug)]
pub struct UseStatement {
pub identifiers: Vec<Identifier>,
pub last: UseStatementLast,
pub file_id: usize,
pub range: Range<usize>,
}
pub struct UseStatementImport<'a> {
pub declared_name: String,
pub fqn: String,
pub identifier: &'a mut Identifier,
}
impl UseStatement {
pub fn new(
identifiers: Vec<Identifier>,
last: UseStatementLast,
file_id: usize,
range: Range<usize>,
) -> Self {
UseStatement {
identifiers,
last,
file_id,
range,
}
}
pub fn base_name(&self) -> Cow<'_, str> {
use UseStatementLast::*;
if self.identifiers.is_empty() {
match &self.last {
Identifier(_) => Cow::from(""),
Star | Identifiers(_) => panic!(), // should never get here because of grammar
}
} else if self.identifiers.len() == 1 {
self.identifiers[0].name()
} else {
let mut acc = String::new();
for (i, identifier) in self.identifiers.iter().enumerate() {
acc.push_str(&identifier.name());
if i != self.identifiers.len() - 1 {
acc.push_str("::");
}
}
Cow::from(acc)
}
}
pub fn is_star(&self) -> bool {
match &self.last {
UseStatementLast::Star => true,
_ => false,
}
}
}
#[derive(Debug)]
pub enum UseStatementLast {
Identifier(Rc<RefCell<Identifier>>),
Identifiers(Vec<Rc<RefCell<Identifier>>>),
Star,
}
#[derive(Debug)] #[derive(Debug)]
pub struct BlockStatement { pub struct BlockStatement {
@ -612,7 +588,7 @@ pub struct ForStatement {
pub body: BlockStatement, pub body: BlockStatement,
} }
// Expressions /* Expressions */
#[derive(Debug)] #[derive(Debug)]
pub enum Expression { pub enum Expression {

View File

@ -1,14 +1,49 @@
use crate::ast::{FullyQualifiedName, Identifier}; use crate::ast::{FullyQualifiedName, Identifier};
use crate::name_analysis::symbol::Symbol;
use std::borrow::Cow; use std::borrow::Cow;
use std::range::Range;
pub trait Named { pub trait Named {
fn name(&self) -> Cow<'_, str>; fn name(&self) -> Cow<'_, str>;
fn file_id(&self) -> usize;
fn range(&self) -> Range<usize>;
fn set_scope_id(&mut self, scope_id: usize);
fn scope_id(&self) -> Option<usize>;
fn set_saved_symbol(&mut self, symbol: Symbol);
fn saved_symbol(&self) -> Option<Symbol>;
} }
impl Named for Identifier { impl Named for Identifier {
fn name(&self) -> Cow<'_, str> { fn name(&self) -> Cow<'_, str> {
Cow::Borrowed(&self.name) Cow::Borrowed(&self.name)
} }
fn file_id(&self) -> usize {
self.file_id
}
fn range(&self) -> Range<usize> {
self.range
}
fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
fn scope_id(&self) -> Option<usize> {
self.scope_id
}
fn set_saved_symbol(&mut self, saved_symbol: Symbol) {
self.saved_symbol = Some(saved_symbol);
}
fn saved_symbol(&self) -> Option<Symbol> {
self.saved_symbol.clone()
}
} }
impl Named for FullyQualifiedName { impl Named for FullyQualifiedName {
@ -26,4 +61,28 @@ impl Named for FullyQualifiedName {
Cow::Owned(acc) Cow::Owned(acc)
} }
} }
fn file_id(&self) -> usize {
self.file_id
}
fn range(&self) -> Range<usize> {
self.range
}
fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
fn scope_id(&self) -> Option<usize> {
self.scope_id
}
fn set_saved_symbol(&mut self, symbol: Symbol) {
self.saved_symbol = Some(symbol);
}
fn saved_symbol(&self) -> Option<Symbol> {
self.saved_symbol.clone()
}
} }

View File

@ -42,6 +42,8 @@ fn handle_insert_error(
} }
} }
/* Names */
fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) { fn gather_identifier(identifier: &mut Identifier, symbol_table: &mut SymbolTable) {
identifier.set_scope_id(symbol_table.current_scope_id()); identifier.set_scope_id(symbol_table.current_scope_id());
} }
@ -50,9 +52,11 @@ fn gather_fully_qualified_name(
fully_qualified_name: &mut FullyQualifiedName, fully_qualified_name: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
) { ) {
fully_qualified_name.set_scope_id(symbol_table.current_scope_id()); gather_identifier(fully_qualified_name.last_mut(), symbol_table);
} }
/* Type Use */
fn gather_type_use( fn gather_type_use(
type_use: &mut TypeUse, type_use: &mut TypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -61,19 +65,7 @@ fn gather_type_use(
) { ) {
match type_use { match type_use {
TypeUse::Primitive(primitive_type_use) => { TypeUse::Primitive(primitive_type_use) => {
match primitive_type_use { gather_primitive_type_use(primitive_type_use, symbol_table, fqn_context, diagnostics)
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
gather_generic_arguments(
generic_arguments,
symbol_table,
fqn_context,
diagnostics,
);
}
}
_ => {}
}
} }
TypeUse::InterfaceOrClass(interface_or_class_type_use) => { TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
gather_interface_or_class_type_use( gather_interface_or_class_type_use(
@ -92,6 +84,22 @@ fn gather_type_use(
} }
} }
fn gather_primitive_type_use(
primitive_type_use: &mut PrimitiveTypeUse,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match primitive_type_use {
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
gather_generic_arguments(generic_arguments, symbol_table, fqn_context, diagnostics);
}
}
_ => {}
}
}
fn gather_interface_or_class_type_use( fn gather_interface_or_class_type_use(
interface_or_class_type_use: &mut InterfaceOrClassTypeUse, interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -124,9 +132,28 @@ fn gather_function_type_use(
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
todo!() gather_generic_parameters(
&mut function_type_use.generics,
symbol_table,
fqn_context,
diagnostics,
);
gather_parameters(
&mut function_type_use.parameters,
symbol_table,
fqn_context,
diagnostics,
);
gather_return_type(
&mut function_type_use.return_type,
symbol_table,
fqn_context,
diagnostics,
);
} }
/* Generic Arguments */
fn gather_generic_arguments( fn gather_generic_arguments(
generic_arguments: &mut GenericArguments, generic_arguments: &mut GenericArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -138,6 +165,123 @@ fn gather_generic_arguments(
} }
} }
/* Generic Parameters */
fn gather_generic_parameters(
generic_parameters: &mut GenericParameters,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!("Add each Identifier as a type to the current scope; make sure caller's push/pop before/after")
}
/* Implements List */
fn gather_implements_list(
implements_list: &mut ImplementsList,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for type_use in &mut implements_list.0 {
gather_type_use(type_use, symbol_table, fqn_context, diagnostics);
}
}
/* Function Parameters */
fn gather_parameters(
parameters: &mut Parameters,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Vec<Rc<ParameterSymbol>>> {
parameters
.0
.iter_mut()
.map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics))
.collect()
}
fn gather_parameter(
parameter: &mut Parameter,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Rc<ParameterSymbol>> {
let parameter_name = parameter.identifier.name();
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
&parameter_name,
Some(&parameter.identifier),
));
match insert_result {
Ok(parameter_symbol) => {
parameter
.identifier
.set_scope_id(symbol_table.current_scope_id());
gather_type_use(
&mut parameter.type_use,
symbol_table,
fqn_context,
diagnostics,
);
Some(parameter_symbol)
}
Err(err) => {
handle_insert_error(
err,
&parameter_name,
parameter.identifier.file_id(),
parameter.identifier.range(),
"function/variable",
diagnostics,
);
None
}
}
}
/* Return Type */
fn gather_return_type(
return_type: &mut ReturnType,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
gather_type_use(
&mut return_type.declared_type,
symbol_table,
fqn_context,
diagnostics,
);
gather_references(
&mut return_type.references,
symbol_table,
fqn_context,
diagnostics,
);
}
/* References */
fn gather_references(
references: &mut References,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for identifier in &mut references.0 {
gather_identifier(identifier, symbol_table);
}
}
/* Compilation Unit/Top-level construct */
pub(super) fn gather_compilation_unit( pub(super) fn gather_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -159,6 +303,8 @@ pub(super) fn gather_compilation_unit(
assert_eq!(symbol_table.current_scope_id(), 0); assert_eq!(symbol_table.current_scope_id(), 0);
} }
/* Use Statement */
fn handle_use_statement_import( fn handle_use_statement_import(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
base_name: &str, base_name: &str,
@ -181,16 +327,15 @@ fn handle_use_statement_import(
gather_identifier(mutable_borrowed_identifier.deref_mut(), symbol_table); gather_identifier(mutable_borrowed_identifier.deref_mut(), symbol_table);
mutable_borrowed_identifier.set_saved_symbol(SavedSymbol::Linking( mutable_borrowed_identifier
Symbol::UseStatement(use_statement_symbol), .set_saved_symbol(Symbol::UseStatement(use_statement_symbol));
));
} }
Err(err) => { Err(err) => {
handle_insert_error( handle_insert_error(
err, err,
&declared_name, &declared_name,
borrowed_identifier.file_id, borrowed_identifier.file_id(),
borrowed_identifier.range, borrowed_identifier.range(),
"Use statement", "Use statement",
diagnostics, diagnostics,
); );
@ -226,6 +371,8 @@ fn gather_use_statement(
} }
} }
/* Declarations allowed in each level */
fn gather_module_level_declaration( fn gather_module_level_declaration(
declaration: &mut ModuleLevelDeclaration, declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -255,6 +402,26 @@ fn gather_module_level_declaration(
} }
} }
fn gather_interface_level_declaration(
declaration: &mut InterfaceLevelDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_class_level_declaration(
declaration: &mut ClassLevelDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Main Declarations */
fn gather_module_declaration( fn gather_module_declaration(
declaration: &mut ModuleDeclaration, declaration: &mut ModuleDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -280,8 +447,8 @@ fn gather_module_declaration(
handle_insert_error( handle_insert_error(
err, err,
&module_name, &module_name,
declaration.identifier.file_id, declaration.identifier.file_id(),
declaration.identifier.range, declaration.identifier.range(),
"module/type", "module/type",
diagnostics, diagnostics,
) )
@ -315,8 +482,8 @@ fn gather_class_declaration(
handle_insert_error( handle_insert_error(
err, err,
&declared_name, &declared_name,
class_declaration.identifier.file_id, class_declaration.identifier.file_id(),
class_declaration.identifier.range, class_declaration.identifier.range(),
"interface/class", "interface/class",
diagnostics, diagnostics,
); );
@ -325,6 +492,8 @@ fn gather_class_declaration(
// todo: scopes, generics, etc. // todo: scopes, generics, etc.
} }
/* Function declarations and components */
fn gather_function_definition( fn gather_function_definition(
function: &mut FunctionDefinition, function: &mut FunctionDefinition,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -384,8 +553,8 @@ fn gather_function_definition(
handle_insert_error( handle_insert_error(
err, err,
&declared_name, &declared_name,
function.identifier.file_id, function.identifier.file_id(),
function.identifier.range, function.identifier.range(),
"function/variable", "function/variable",
diagnostics, diagnostics,
); );
@ -393,6 +562,15 @@ fn gather_function_definition(
} }
} }
fn gather_operator_function_definition(
operator_function_definition: &mut OperatorFunctionDefinition,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_platform_function_definition( fn gather_platform_function_definition(
platform_function_declaration: &mut PlatformFunctionDeclaration, platform_function_declaration: &mut PlatformFunctionDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -453,8 +631,8 @@ fn gather_platform_function_definition(
handle_insert_error( handle_insert_error(
err, err,
&declared_name, &declared_name,
platform_function_declaration.identifier.file_id, platform_function_declaration.identifier.file_id(),
platform_function_declaration.identifier.range, platform_function_declaration.identifier.range(),
"(Platform-) Function", "(Platform-) Function",
diagnostics, diagnostics,
); );
@ -462,89 +640,22 @@ fn gather_platform_function_definition(
} }
} }
fn gather_parameters( fn gather_interface_function_declaration(
parameters: &mut Parameters, declaration: &mut InterfaceFunctionDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Vec<Rc<ParameterSymbol>>> {
parameters
.0
.iter_mut()
.map(|parameter| gather_parameter(parameter, symbol_table, fqn_context, diagnostics))
.collect()
}
fn gather_parameter(
parameter: &mut Parameter,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Rc<ParameterSymbol>> {
let parameter_name = parameter.identifier.name();
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
&parameter_name,
Some(&parameter.identifier),
));
match insert_result {
Ok(parameter_symbol) => {
parameter
.identifier
.set_scope_id(symbol_table.current_scope_id());
gather_type_use(
&mut parameter.type_use,
symbol_table,
fqn_context,
diagnostics,
);
Some(parameter_symbol)
}
Err(err) => {
handle_insert_error(
err,
&parameter_name,
parameter.identifier.file_id,
parameter.identifier.range,
"function/variable",
diagnostics,
);
None
}
}
}
fn gather_return_type(
return_type: &mut ReturnType,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
gather_type_use( todo!()
&mut return_type.declared_type,
symbol_table,
fqn_context,
diagnostics,
);
gather_references(
&mut return_type.references,
symbol_table,
fqn_context,
diagnostics,
);
} }
fn gather_references( fn gather_interface_operator_function_declaration(
references: &mut References, declaration: &mut InterfaceOperatorFunctionDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext, fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
for identifier in &mut references.0 { todo!()
gather_identifier(identifier, symbol_table);
}
} }
fn gather_function_body( fn gather_function_body(
@ -560,6 +671,37 @@ fn gather_function_body(
} }
} }
/* Class Components */
fn gather_class_constructor(
class_constructor: &mut ClassConstructor,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_property_declaration(
property_declaration: &mut PropertyDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_field_declaration(
field_declaration: &mut FieldDeclaration,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Statements */
fn gather_block_statement( fn gather_block_statement(
block: &mut BlockStatement, block: &mut BlockStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -626,8 +768,8 @@ fn gather_variable_declaration(
handle_insert_error( handle_insert_error(
err, err,
&variable_name, &variable_name,
variable_declaration.identifier.file_id, variable_declaration.identifier.file_id(),
variable_declaration.identifier.range, variable_declaration.identifier.range(),
"function/variable", "function/variable",
diagnostics, diagnostics,
) )
@ -660,6 +802,55 @@ fn gather_call_statement(
gather_expression(&mut call_statement.0, symbol_table, diagnostics); gather_expression(&mut call_statement.0, symbol_table, diagnostics);
} }
fn gather_return_statement(
return_statement: &mut ReturnStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(expression) = &mut return_statement.0 {
gather_expression(expression, symbol_table, diagnostics);
}
}
fn gather_if_statement(
if_statement: &mut IfStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_if_else_statement(
if_else_statement: &mut IfElseStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_while_statement(
while_statement: &mut WhileStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn gather_for_statement(
for_statement: &mut ForStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Expressions */
fn gather_expression( fn gather_expression(
expression: &mut Expression, expression: &mut Expression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -782,6 +973,7 @@ fn gather_object_access(
gather_expression(index_expression, symbol_table, diagnostics); gather_expression(index_expression, symbol_table, diagnostics);
} }
ObjectNavigation::Identifier(identifier) => { ObjectNavigation::Identifier(identifier) => {
// TODO: use a special gather for names belonging to a struct
gather_identifier(identifier, symbol_table); gather_identifier(identifier, symbol_table);
} }
} }
@ -794,8 +986,18 @@ fn gather_literal(
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match literal { match literal {
Literal::DString(d_string) => todo!(), Literal::DString(d_string) => gather_d_string(d_string, symbol_table, diagnostics),
Literal::BacktickString(backtick_string) => todo!(), Literal::BacktickString(backtick_string) => {
gather_d_string(backtick_string, symbol_table, diagnostics)
}
_ => {} _ => {}
} }
} }
fn gather_d_string(
d_string: &mut DString,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}

View File

@ -88,8 +88,6 @@ mod tests {
let diagnostics = analyze_names(&mut compilation_units, symbol_table); let diagnostics = analyze_names(&mut compilation_units, symbol_table);
assert_eq!(n_diagnostics, diagnostics.len());
if !diagnostics.is_empty() { if !diagnostics.is_empty() {
let writer = StandardStream::stderr(ColorChoice::Always); let writer = StandardStream::stderr(ColorChoice::Always);
let config = term::Config::default(); let config = term::Config::default();
@ -101,6 +99,8 @@ mod tests {
eprintln!("{}", symbol_table); eprintln!("{}", symbol_table);
} }
assert_eq!(n_diagnostics, diagnostics.len());
for compilation_unit in &compilation_units { for compilation_unit in &compilation_units {
dbg!(compilation_unit); dbg!(compilation_unit);
} }
@ -174,13 +174,25 @@ mod tests {
} }
#[test] #[test]
fn symbol_shadows_import() { fn use_class_from_other_file() {
let sources: HashMap<&str, &str> = HashMap::from([( let sources: HashMap<&str, &str> = HashMap::from([
"main.dm", (
indoc! {" "main.dm",
platform fn println(msg: Any) -> Void; indoc! {"
"}, use greeter::Greeter;
)]);
fn test(greeter: Greeter) {}
"},
),
(
"greeter.dm",
indoc! {"
ns greeter;
class Greeter {}
"},
),
]);
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
assert_no_diagnostics(sources, &mut symbol_table); assert_no_diagnostics(sources, &mut symbol_table);

View File

@ -1,41 +1,14 @@
use crate::ast::named::Named; use crate::ast::named::Named;
use crate::ast::*; use crate::ast::*;
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol_table::SymbolTable; use crate::name_analysis::symbol::Symbol;
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::cell::RefCell; use std::cell::RefCell;
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
fn resolve_fully_qualified_name( /* Type Use */
fully_qualified_name: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result = symbol_table.lookup(
fully_qualified_name.name().as_ref(),
fully_qualified_name.scope_id().expect(&format!(
"FullyQualifiedName has no scope_id set: {:?}",
fully_qualified_name
)),
);
match lookup_result {
Ok(symbol) => {
fully_qualified_name.set_symbol(symbol.clone());
}
Err(e) => diagnostics.push(
Diagnostic::error()
.with_message(format!(
"No symbol with name '{}' found in current scope.",
fully_qualified_name.name()
))
.with_label(Label::primary(
fully_qualified_name.file_id,
fully_qualified_name.range,
)),
),
}
}
fn resolve_type_use( fn resolve_type_use(
type_use: &mut TypeUse, type_use: &mut TypeUse,
@ -44,18 +17,7 @@ fn resolve_type_use(
) { ) {
match type_use { match type_use {
TypeUse::Primitive(primitive_type_use) => { TypeUse::Primitive(primitive_type_use) => {
match primitive_type_use { resolve_primitive_type_use(primitive_type_use, symbol_table, diagnostics)
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
resolve_generic_arguments(
generic_arguments,
symbol_table,
diagnostics,
);
}
}
_ => {}
}
} }
TypeUse::InterfaceOrClass(interface_or_class_type_use) => { TypeUse::InterfaceOrClass(interface_or_class_type_use) => {
resolve_interface_or_class_type_use( resolve_interface_or_class_type_use(
@ -73,16 +35,56 @@ fn resolve_type_use(
} }
} }
fn resolve_primitive_type_use(
primitive_type_use: &mut PrimitiveTypeUse,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match primitive_type_use {
PrimitiveTypeUse::Array(generic_arguments_opt) => {
if let Some(generic_arguments) = generic_arguments_opt {
resolve_generic_arguments(generic_arguments, symbol_table, diagnostics);
}
}
_ => {}
}
}
fn resolve_interface_or_class_type_use( fn resolve_interface_or_class_type_use(
interface_or_class_type_use: &mut InterfaceOrClassTypeUse, interface_or_class_type_use: &mut InterfaceOrClassTypeUse,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
resolve_fully_qualified_name( // 1. handle main name
&mut interface_or_class_type_use.fqn, let fqn = &mut interface_or_class_type_use.fqn;
symbol_table, let lookup_result = if fqn.is_single_identifier() {
diagnostics, let identifier = fqn.last();
); symbol_table.lookup_type_by_declared_name(
&identifier.name(),
identifier
.scope_id()
.expect("Identifier's scope id not set."),
)
} else {
todo!("Fully-qualified-name type uses sensitive to imports and so on")
};
match lookup_result {
Ok(type_symbol) => {
fqn.last_mut().set_saved_symbol(Symbol::Type(type_symbol));
}
Err(_) => {
diagnostics.push(
Diagnostic::error()
.with_message(&format!(
"No type symbol '{}' found in current scope.",
fqn.name()
))
.with_label(Label::primary(fqn.file_id(), fqn.range())),
);
}
}
// 2. generics
resolve_generic_arguments( resolve_generic_arguments(
&mut interface_or_class_type_use.generics, &mut interface_or_class_type_use.generics,
symbol_table, symbol_table,
@ -111,6 +113,8 @@ fn resolve_function_type_use(
); );
} }
/* Generic arguments */
fn resolve_generic_arguments( fn resolve_generic_arguments(
generic_arguments: &mut GenericArguments, generic_arguments: &mut GenericArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -121,6 +125,10 @@ fn resolve_generic_arguments(
} }
} }
/* Generic parameters: todo: no resolution needed? */
/* Tuple arguments */
fn resolve_tuple_arguments( fn resolve_tuple_arguments(
tuple_type_use: &mut TupleArguments, tuple_type_use: &mut TupleArguments,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -131,6 +139,8 @@ fn resolve_tuple_arguments(
} }
} }
/* Implements list */
fn resolve_implements_list( fn resolve_implements_list(
implements_list: &mut ImplementsList, implements_list: &mut ImplementsList,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -139,6 +149,8 @@ fn resolve_implements_list(
todo!() todo!()
} }
/* Function parameters */
fn resolve_parameters( fn resolve_parameters(
parameters: &mut Parameters, parameters: &mut Parameters,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -149,6 +161,8 @@ fn resolve_parameters(
} }
} }
/* Return Type */
fn resolve_return_type( fn resolve_return_type(
return_type: &mut ReturnType, return_type: &mut ReturnType,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -158,6 +172,8 @@ fn resolve_return_type(
resolve_references(&mut return_type.references, symbol_table, diagnostics); resolve_references(&mut return_type.references, symbol_table, diagnostics);
} }
/* References */
fn resolve_references( fn resolve_references(
references: &mut References, references: &mut References,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -168,8 +184,25 @@ fn resolve_references(
} }
} }
/* Compilation Unit/Top-level construct */
pub(super) fn resolve_compilation_unit(
compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for use_statement in &mut compilation_unit.use_statements {
resolve_use_statement(use_statement, symbol_table, diagnostics);
}
for declaration in &mut compilation_unit.declarations {
resolve_module_level_declaration(declaration, symbol_table, diagnostics);
}
}
/* Use Statement */
fn handle_use_statement_identifier( fn handle_use_statement_identifier(
identifier: &Rc<RefCell<Identifier>>, identifier: Rc<RefCell<Identifier>>,
base_name: &str, base_name: &str,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -183,18 +216,15 @@ fn handle_use_statement_identifier(
symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap()); symbol_table.lookup_usable_by_fqn(&fqn, borrowed_identifier.scope_id().unwrap());
match lookup_result { match lookup_result {
Ok(referenced_symbol) => match borrowed_identifier.saved_symbol() { Ok(referenced_symbol) => {
Some(saved_symbol) => match saved_symbol { let saved_symbol = borrowed_identifier
SavedSymbol::Linking(symbol) => { .saved_symbol()
let use_statement_symbol = symbol.unwrap_use_statement_symbol(); .expect("Identifier's saved_symbol is not set.");
use_statement_symbol let use_statement_symbol = saved_symbol.unwrap_use_statement_symbol();
.borrow_mut() use_statement_symbol
.set_referenced_symbol(referenced_symbol); .borrow_mut()
} .set_referenced_symbol(referenced_symbol);
_ => panic!("Expected to find SavedSymbol::Linking."), }
},
None => panic!("Expected to find saved_symbol"),
},
Err(_) => { Err(_) => {
diagnostics.push( diagnostics.push(
Diagnostic::error() Diagnostic::error()
@ -215,7 +245,7 @@ fn resolve_use_statement(
match &use_statement.last { match &use_statement.last {
UseStatementLast::Identifier(identifier) => { UseStatementLast::Identifier(identifier) => {
handle_use_statement_identifier( handle_use_statement_identifier(
identifier, identifier.clone(),
&base_name, &base_name,
symbol_table, symbol_table,
diagnostics, diagnostics,
@ -226,33 +256,22 @@ fn resolve_use_statement(
UseStatementLast::Identifiers(identifiers) => { UseStatementLast::Identifiers(identifiers) => {
for identifier in identifiers { for identifier in identifiers {
handle_use_statement_identifier( handle_use_statement_identifier(
identifier, identifier.clone(),
&base_name, &base_name,
symbol_table, symbol_table,
diagnostics, diagnostics,
use_statement.file_id, use_statement.file_id,
identifier.borrow().range, identifier.borrow().range(),
) )
} }
} }
UseStatementLast::Star => todo!(), UseStatementLast::Star => todo!("star imports"),
} }
} }
pub(super) fn resolve_compilation_unit( /* Declarations allowed in each level */
compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for use_statement in &mut compilation_unit.use_statements {
resolve_use_statement(use_statement, symbol_table, diagnostics);
}
for declaration in &mut compilation_unit.declarations {
resolve_module_level_declaration(declaration, symbol_table, diagnostics);
}
}
pub(super) fn resolve_module_level_declaration( fn resolve_module_level_declaration(
declaration: &mut ModuleLevelDeclaration, declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -274,6 +293,65 @@ pub(super) fn resolve_module_level_declaration(
} }
} }
fn resolve_interface_level_declaration(
declaration: &mut InterfaceLevelDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_class_level_declaration(
declaration: &mut ClassLevelDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Main Declarations */
fn resolve_module_declaration(
module_declaration: &mut ModuleDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
for declaration in &mut module_declaration.declarations {
resolve_module_level_declaration(declaration, symbol_table, diagnostics);
}
}
fn resolve_interface_declaration(
interface_declaration: &mut InterfaceDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
resolve_implements_list(
&mut interface_declaration.implements,
symbol_table,
diagnostics,
);
for declaration in &mut interface_declaration.declarations {
resolve_interface_level_declaration(declaration, symbol_table, diagnostics);
}
}
fn resolve_class_declaration(
class_declaration: &mut ClassDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(class_constructor) = &mut class_declaration.class_constructor {
resolve_class_constructor(class_constructor, symbol_table, diagnostics);
}
resolve_implements_list(&mut class_declaration.implements, symbol_table, diagnostics);
for declaration in &mut class_declaration.declarations {
resolve_class_level_declaration(declaration, symbol_table, diagnostics);
}
}
/* Function declarations and components */
fn resolve_function_definition( fn resolve_function_definition(
function_definition: &mut FunctionDefinition, function_definition: &mut FunctionDefinition,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -292,6 +370,14 @@ fn resolve_function_definition(
resolve_function_body(&mut function_definition.body, symbol_table, diagnostics); resolve_function_body(&mut function_definition.body, symbol_table, diagnostics);
} }
fn resolve_operator_function_definition(
operator_function_definition: &mut OperatorFunctionDefinition,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_platform_function_declaration( fn resolve_platform_function_declaration(
platform_function_declaration: &mut PlatformFunctionDeclaration, platform_function_declaration: &mut PlatformFunctionDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -309,6 +395,22 @@ fn resolve_platform_function_declaration(
); );
} }
fn resolve_interface_function_declaration(
interface_function_declaration: &mut InterfaceFunctionDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_interface_operator_function_declaration(
interface_operator_function_declaration: &mut InterfaceOperatorFunctionDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_function_body( fn resolve_function_body(
function_body: &mut FunctionBody, function_body: &mut FunctionBody,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -316,12 +418,49 @@ fn resolve_function_body(
) { ) {
use crate::ast::FunctionBody::*; use crate::ast::FunctionBody::*;
match function_body { match function_body {
Block(block) => resolve_block(block, symbol_table, diagnostics), Equals(expression) => resolve_expression(expression, symbol_table, diagnostics),
_ => todo!(), Block(block) => resolve_block_statement(block, symbol_table, diagnostics),
Alias(identifier) => resolve_function_alias(identifier, symbol_table, diagnostics),
} }
} }
fn resolve_block( fn resolve_function_alias(
identifier: &mut Identifier,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Class components */
fn resolve_class_constructor(
class_constructor: &mut ClassConstructor,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_property_declaration(
property_declaration: &mut PropertyDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_field_declaration(
field_declaration: &mut FieldDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Statements */
fn resolve_block_statement(
block_statement: &mut BlockStatement, block_statement: &mut BlockStatement,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -341,7 +480,7 @@ fn resolve_statement(
) { ) {
use crate::ast::Statement::*; use crate::ast::Statement::*;
match statement { match statement {
BlockStatement(block) => resolve_block(block, symbol_table, diagnostics), BlockStatement(block) => resolve_block_statement(block, symbol_table, diagnostics),
VariableDeclarationStatement(variable_declaration) => { VariableDeclarationStatement(variable_declaration) => {
resolve_variable_declaration(variable_declaration, symbol_table, diagnostics) resolve_variable_declaration(variable_declaration, symbol_table, diagnostics)
} }
@ -382,6 +521,42 @@ fn resolve_call_statement(
resolve_expression(&mut call_statement.0, symbol_table, diagnostics) resolve_expression(&mut call_statement.0, symbol_table, diagnostics)
} }
fn resolve_return_statement(
return_statement: &mut ReturnStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
if let Some(expression) = &mut return_statement.0 {
resolve_expression(expression, symbol_table, diagnostics);
}
}
fn resolve_if_statement(
if_statement: &mut IfStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_while_statement(
while_statement: &mut WhileStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
fn resolve_for_statement(
for_statement: &mut ForStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
todo!()
}
/* Expressions */
fn resolve_expression( fn resolve_expression(
expression: &mut Expression, expression: &mut Expression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -407,7 +582,13 @@ fn resolve_expression(
ObjectAccess(object_access) => { ObjectAccess(object_access) => {
resolve_object_access(object_access, symbol_table, diagnostics); resolve_object_access(object_access, symbol_table, diagnostics);
} }
FullyQualifiedName(fqn) => resolve_fully_qualified_name(fqn, symbol_table, diagnostics), FullyQualifiedName(fqn) => {
if fqn.is_single_identifier() {
resolve_identifier_expression(fqn.last_mut(), symbol_table, diagnostics);
} else {
resolve_fqn_expression(fqn, symbol_table, diagnostics);
}
}
Literal(literal) => { Literal(literal) => {
resolve_literal(literal, symbol_table, diagnostics); resolve_literal(literal, symbol_table, diagnostics);
} }
@ -417,6 +598,48 @@ fn resolve_expression(
} }
} }
fn handle_named_lookup_result(
lookup_result: Result<Symbol, SymbolLookupError>,
named: &mut impl Named,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match lookup_result {
Ok(referenced_symbol) => {
named.set_saved_symbol(referenced_symbol);
}
Err(_) => {
diagnostics.push(
DmDiagnostic::error()
.with_message(&format!(
"Unable to find expressible symbol {} in current scope.",
named.name()
))
.with_label(Label::primary(named.file_id(), named.range())),
);
}
}
}
fn resolve_identifier_expression(
identifier: &mut Identifier,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result = symbol_table
.lookup_expressible_by_declared_name(&identifier.name(), identifier.scope_id().unwrap());
handle_named_lookup_result(lookup_result, identifier, diagnostics);
}
fn resolve_fqn_expression(
fqn: &mut FullyQualifiedName,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let lookup_result =
symbol_table.lookup_expressible_by_fqn(&fqn.name(), fqn.last().scope_id().unwrap());
handle_named_lookup_result(lookup_result, fqn, diagnostics);
}
fn resolve_ternary_expression( fn resolve_ternary_expression(
ternary_expression: &mut TernaryExpression, ternary_expression: &mut TernaryExpression,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -477,7 +700,7 @@ fn resolve_turbo_fish(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
todo!() resolve_generic_arguments(&mut turbo_fish.0, symbol_table, diagnostics);
} }
fn resolve_call_arguments( fn resolve_call_arguments(

View File

@ -3,6 +3,7 @@ use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::named::Named;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SourceDefinition { pub struct SourceDefinition {
@ -13,16 +14,16 @@ pub struct SourceDefinition {
impl SourceDefinition { impl SourceDefinition {
pub fn from_identifier(identifier: &Identifier) -> Self { pub fn from_identifier(identifier: &Identifier) -> Self {
SourceDefinition { SourceDefinition {
file_id: identifier.file_id, file_id: identifier.file_id(),
range: identifier.range, range: identifier.range(),
} }
} }
pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self { pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self {
let borrowed = identifier.borrow(); let borrowed = identifier.borrow();
SourceDefinition { SourceDefinition {
file_id: borrowed.file_id, file_id: borrowed.file_id(),
range: borrowed.range, range: borrowed.range(),
} }
} }

View File

@ -76,6 +76,29 @@ impl Scope {
None None
} }
fn get_type_symbol_by_declared_name(&self, declared_name: &str) -> Option<Rc<TypeSymbol>> {
if let Some(type_symbol) = self.type_symbols.get(declared_name) {
Some(type_symbol.clone())
} else {
for use_statement_symbol in self.use_statement_symbols.values() {
let borrowed = use_statement_symbol.borrow();
if borrowed.declared_name() == declared_name {
if let Some(referenced_symbol) = borrowed.referenced_symbol() {
match *referenced_symbol {
Symbol::Type(type_symbol) => return Some(type_symbol.clone()),
_ => continue,
}
}
}
}
None
}
}
fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<TypeSymbol>> {
self.type_symbols.values().find(|s| s.fqn() == fqn).cloned()
}
fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> { fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> {
for function_symbol in self.function_symbols.values() { for function_symbol in self.function_symbols.values() {
if function_symbol.borrow().fqn() == fqn { if function_symbol.borrow().fqn() == fqn {
@ -117,6 +140,45 @@ impl Scope {
} }
None None
} }
fn get_expressible_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
self.variable_symbols
.get(declared_name)
.map(|s| Symbol::Variable(s.clone()))
.or_else(|| {
self.parameter_symbols
.get(declared_name)
.map(|p| Symbol::Parameter(p.clone()))
})
.or_else(|| {
self.function_symbols
.get(declared_name)
.map(|f| Symbol::Function(f.clone()))
})
.or_else(|| {
self.type_symbols
.get(declared_name)
.map(|t| Symbol::Type(t.clone()))
})
.or_else(|| {
self.use_statement_symbols
.get(declared_name)
.map(|us| Symbol::UseStatement(us.clone()))
})
}
fn get_expressible_by_fqn(&self, fqn: &str) -> Option<Symbol> {
self.function_symbols
.values()
.find(|fs| fs.borrow().fqn() == fqn)
.map(|f| Symbol::Function(f.clone()))
.or_else(|| {
self.type_symbols
.values()
.find(|ts| ts.fqn() == fqn)
.map(|ts| Symbol::Type(ts.clone()))
})
}
} }
/* Symbol table */ /* Symbol table */
@ -280,6 +342,7 @@ impl SymbolTable {
} }
} }
#[deprecated(note = "Use more specific lookup methods.")]
pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> { pub fn lookup(&self, name: &str, scope_id: usize) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]); let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt { while let Some(scope) = scope_opt {
@ -295,6 +358,44 @@ impl SymbolTable {
Err(NoDefinition) Err(NoDefinition)
} }
pub fn lookup_type_by_declared_name(
&self,
declared_name: &str,
scope_id: usize,
) -> Result<Rc<TypeSymbol>, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_type_symbol_by_declared_name(declared_name) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_type_by_fqn(
&self,
fqn: &str,
scope_id: usize,
) -> Result<Rc<TypeSymbol>, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_type_symbol_by_fqn(fqn) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_usable_by_fqn( pub fn lookup_usable_by_fqn(
&self, &self,
fully_qualified_name: &str, fully_qualified_name: &str,
@ -307,6 +408,44 @@ impl SymbolTable {
} }
Err(NoDefinition) Err(NoDefinition)
} }
pub fn lookup_expressible_by_declared_name(
&self,
declared_name: &str,
scope_id: usize,
) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_expressible_by_declared_name(declared_name) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
pub fn lookup_expressible_by_fqn(
&self,
fqn: &str,
scope_id: usize,
) -> Result<Symbol, SymbolLookupError> {
let mut scope_opt = Some(&self.scopes[scope_id]);
while let Some(scope) = scope_opt {
if let Some(symbol) = scope.get_expressible_by_fqn(fqn) {
return Ok(symbol);
}
scope_opt = if let Some(parent_id) = scope.parent {
Some(&self.scopes[parent_id])
} else {
None
}
}
Err(NoDefinition)
}
} }
impl Display for SymbolTable { impl Display for SymbolTable {