WIP more name analysis.

This commit is contained in:
Jesse Brault 2025-10-21 18:36:03 -05:00
parent bdbc2543b8
commit 664aebfd61
11 changed files with 267 additions and 233 deletions

View File

@ -9,16 +9,15 @@ fn deserialize_field(field_yaml: &Yaml) -> StructField {
let (name, props) = unwrap_single_member_hash(field_yaml); let (name, props) = unwrap_single_member_hash(field_yaml);
let kind = props["kind"].as_str().unwrap(); let kind = props["kind"].as_str().unwrap();
let wrap = if let Some(wrap) = props["wrap"].as_str() { let wrap = if let Some(wrap) = props["wrap"].as_str() {
match wrap { match wrap {
"rc_ref_cell" => { "rc_ref_cell" => Some(StructFieldWrap::RcRefCell),
Some(StructFieldWrap::RcRefCell) _ => panic!(),
}
_ => panic!()
} }
} else { } else {
None None
}; };
StructField::new(&name, kind, wrap) let vec = get_as_bool(&props["vec"]);
StructField::new(&name, kind, wrap, vec)
} }
fn deserialize_skip_child(props: &Yaml) -> StructChild { fn deserialize_skip_child(props: &Yaml) -> StructChild {
@ -112,8 +111,12 @@ fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild {
match props["kind"].as_str().unwrap() { match props["kind"].as_str().unwrap() {
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)), "file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
"range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)), "range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)),
_ => panic!("Invalid special child kind {} in {}", props["kind"].as_str().unwrap(), name), _ => panic!(
} "Invalid special child kind {} in {}",
props["kind"].as_str().unwrap(),
name
),
}
} }
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild { fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
@ -124,7 +127,7 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
} else if props["member"].is_hash() { } else if props["member"].is_hash() {
deserialize_member_child(name, &props["member"]) deserialize_member_child(name, &props["member"])
} else if props["special"].is_hash() { } else if props["special"].is_hash() {
deserialize_special_child(name, &props["special"]) deserialize_special_child(name, &props["special"])
} else { } else {
panic!("Expected 'skip' or 'vec' in 'member' in {}", name); panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
} }
@ -167,9 +170,10 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
} else { } else {
deserialize_error!("array", "children", name); deserialize_error!("array", "children", name);
}; };
let fields = if struct_yaml["fields"].is_array() { let fields = if struct_yaml["fields"].is_array() {
struct_yaml["fields"].as_vec() struct_yaml["fields"]
.as_vec()
.unwrap() .unwrap()
.iter() .iter()
.map(|field| deserialize_field(field)) .map(|field| deserialize_field(field))
@ -178,9 +182,10 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
} else { } else {
vec![] vec![]
}; };
let derive = if struct_yaml["derive"].is_array() { let derive = if struct_yaml["derive"].is_array() {
struct_yaml["derive"].as_vec() struct_yaml["derive"]
.as_vec()
.unwrap() .unwrap()
.iter() .iter()
.map(|derive| derive.as_str().unwrap().to_string()) .map(|derive| derive.as_str().unwrap().to_string())
@ -188,6 +193,6 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
} else { } else {
vec![] vec![]
}; };
StructSpec::new(name, children, fields, derive) StructSpec::new(name, children, fields, derive)
} }

View File

@ -6,7 +6,12 @@ pub struct StructSpec {
} }
impl StructSpec { impl StructSpec {
pub fn new(build: &str, children: Vec<Box<StructChild>>, fields: Vec<Box<StructField>>, derive: Vec<String>) -> Self { pub fn new(
build: &str,
children: Vec<Box<StructChild>>,
fields: Vec<Box<StructField>>,
derive: Vec<String>,
) -> Self {
Self { Self {
build: build.to_string(), build: build.to_string(),
children, children,
@ -24,11 +29,11 @@ impl StructSpec {
pub fn children(&self) -> impl Iterator<Item = &StructChild> { pub fn children(&self) -> impl Iterator<Item = &StructChild> {
self.children.iter().map(Box::as_ref) self.children.iter().map(Box::as_ref)
} }
pub fn fields(&self) -> impl Iterator<Item = &StructField> { pub fn fields(&self) -> impl Iterator<Item = &StructField> {
self.fields.iter().map(Box::as_ref) self.fields.iter().map(Box::as_ref)
} }
pub fn derive(&self) -> &[String] { pub fn derive(&self) -> &[String] {
&self.derive &self.derive
} }
@ -48,13 +53,11 @@ impl StructChild {
_ => false, _ => false,
} }
} }
pub fn unwrap_special(&self) -> Option<&SpecialChild> { pub fn unwrap_special(&self) -> Option<&SpecialChild> {
match self { match self {
StructChild::Special(special_child) => { StructChild::Special(special_child) => Some(special_child),
Some(special_child) _ => None,
},
_ => None
} }
} }
} }
@ -254,14 +257,14 @@ impl SpecialChild {
pub fn new(name: &str, kind: SpecialChildKind) -> Self { pub fn new(name: &str, kind: SpecialChildKind) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
kind kind,
} }
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn kind(&self) -> &SpecialChildKind { pub fn kind(&self) -> &SpecialChildKind {
&self.kind &self.kind
} }
@ -278,31 +281,37 @@ pub struct StructField {
name: String, name: String,
kind: String, kind: String,
wrap: Option<StructFieldWrap>, wrap: Option<StructFieldWrap>,
vec: bool,
} }
impl StructField { impl StructField {
pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>) -> Self { pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>, vec: bool) -> Self {
Self { Self {
name: name.to_string(), name: name.to_string(),
kind: kind.to_string(), kind: kind.to_string(),
wrap, wrap,
vec,
} }
} }
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
&self.name &self.name
} }
pub fn kind(&self) -> &str { pub fn kind(&self) -> &str {
&self.kind &self.kind
} }
pub fn wrap(&self) -> Option<&StructFieldWrap> { pub fn wrap(&self) -> Option<&StructFieldWrap> {
self.wrap.as_ref() self.wrap.as_ref()
} }
pub fn vec(&self) -> bool {
self.vec
}
} }
#[derive(Debug)] #[derive(Debug)]
pub enum StructFieldWrap { pub enum StructFieldWrap {
RcRefCell RcRefCell,
} }

View File

@ -19,35 +19,51 @@ fn make_field_accessors(field: &StructField) -> TokenStream {
quote! { #inner } quote! { #inner }
} }
}; };
let set_field_ident = format_ident!("set_{}", field.name());
let field_ident_mut = format_ident!("{}_mut", field.name()); let field_ident_mut = format_ident!("{}_mut", field.name());
quote! { if field.vec() {
pub fn #field_ident(&self) -> Option<&#field_type> { quote! {
self.#field_ident.as_ref() pub fn #field_ident(&self) -> &[#field_type] {
} self.#field_ident.as_slice()
}
pub fn #field_ident_mut(&mut self) -> Option<&mut #field_type> {
self.#field_ident.as_mut()
}
pub fn #set_field_ident(&mut self, #field_ident: #field_type) { pub fn #field_ident_mut(&mut self) -> &mut Vec<#field_type> {
self.#field_ident = Some(#field_ident); &mut self.#field_ident
}
}
} else {
let set_field_ident = format_ident!("set_{}", field.name());
quote! {
pub fn #field_ident(&self) -> Option<&#field_type> {
self.#field_ident.as_ref()
}
pub fn #field_ident_mut(&mut self) -> Option<&mut #field_type> {
self.#field_ident.as_mut()
}
pub fn #set_field_ident(&mut self, #field_ident: #field_type) {
self.#field_ident = Some(#field_ident);
}
} }
} }
} }
fn make_field_initializer(field: &StructField) -> TokenStream { fn make_field_initializer(field: &StructField) -> TokenStream {
let field_ident = format_ident!("{}", field.name()); let field_ident = format_ident!("{}", field.name());
quote! { #field_ident: None } if field.vec() {
quote! { #field_ident: vec![] }
} else {
quote! { #field_ident: None }
}
} }
fn make_annotated_field(field: &StructField) -> TokenStream { fn make_annotated_field(field: &StructField) -> TokenStream {
let field_ident = format_ident!("{}", field.name()); let field_ident = format_ident!("{}", field.name());
let field_type = if let Some(wrap) = field.wrap() { let field_type = if let Some(wrap) = field.wrap() {
let inner = format_ident!("{}", field.kind());
match wrap { match wrap {
StructFieldWrap::RcRefCell => { StructFieldWrap::RcRefCell => {
let inner = format_ident!("{}", field.kind());
quote! { Rc<RefCell<#inner>> } quote! { Rc<RefCell<#inner>> }
} }
} }
@ -56,8 +72,14 @@ fn make_annotated_field(field: &StructField) -> TokenStream {
quote! { #inner } quote! { #inner }
}; };
quote! { if field.vec() {
#field_ident: Option<#field_type> quote! {
#field_ident: Vec<#field_type>
}
} else {
quote! {
#field_ident: Option<#field_type>
}
} }
} }

View File

@ -3,50 +3,17 @@ use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::fqn_context::FqnContext; use crate::name_analysis::fqn_context::FqnContext;
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol};
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; use crate::name_analysis::symbol_table::SymbolTable;
use crate::name_analysis::symbol_tree::SymbolTree; use crate::name_analysis::symbol_tree::SymbolTree;
use crate::name_analysis::util::use_statement_base_fqn; use crate::name_analysis::util;
use codespan_reporting::diagnostic::{Diagnostic, Label}; use crate::name_analysis::util::{handle_insert_error, use_statement_base_fqn};
use std::cell::RefCell; use std::cell::RefCell;
use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
fn handle_insert_error(
err: SymbolInsertError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolInsertError::SymbolAlreadyDefined(s) => {
let mut diagnostic = Diagnostic::error()
.with_message(format!(
"{} symbol '{}' already defined in the current scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range)
.with_message("Symbol duplicated here."),
);
if let Some(source_definition) = s.definition() {
diagnostic = diagnostic.with_label(
Label::secondary(source_definition.file_id(), source_definition.range())
.with_message("Symbol defined here."),
);
}
diagnostics.push(diagnostic);
}
}
}
macro_rules! insert_symbol { macro_rules! insert_symbol {
($insert_method:ident, $symbol:expr, $symbol_table:ident, $name:expr, $node:ident, $symbol_kinds:literal, $diagnostics:ident) => { ($insert_method:ident, $symbol:expr, $symbol_table:ident, $name:expr, $node:ident, $symbol_kinds:literal, $diagnostics:ident) => {
if let Err(insert_error) = $symbol_table.$insert_method($symbol) { if let Err(insert_error) = $symbol_table.$insert_method($symbol) {
handle_insert_error( util::handle_insert_error(
insert_error, insert_error,
$name, $name,
$node.file_id(), $node.file_id(),
@ -58,20 +25,6 @@ macro_rules! insert_symbol {
}; };
} }
macro_rules! insert_concrete_use_symbol {
($symbol:expr, $symbol_table:ident, $symbol_name:expr, $source_node:ident, $symbol_kinds:literal, $diagnostics:ident) => {
insert_symbol!(
insert_concrete_use_symbol,
$symbol,
$symbol_table,
$symbol_name,
$source_node,
$symbol_kinds,
$diagnostics
)
};
}
pub fn nap1_compilation_unit( pub fn nap1_compilation_unit(
file_name: &str, file_name: &str,
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
@ -95,12 +48,12 @@ pub fn nap1_compilation_unit(
symbol_table.pop_scope(); symbol_table.pop_scope();
} }
fn handle_concrete_use_statement( fn maybe_insert_concrete_use_symbol(
use_statement: &mut UseStatement, use_statement: &UseStatement,
identifier: &Identifier, identifier: &Identifier,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
let base_fqn = use_statement_base_fqn(use_statement); let base_fqn = use_statement_base_fqn(use_statement);
let to_insert = ConcreteUseSymbol::new( let to_insert = ConcreteUseSymbol::new(
&base_fqn, &base_fqn,
@ -108,9 +61,7 @@ fn handle_concrete_use_statement(
Some(SourceDefinition::from_identifier(identifier)), Some(SourceDefinition::from_identifier(identifier)),
); );
match symbol_table.insert_concrete_use_symbol(to_insert) { match symbol_table.insert_concrete_use_symbol(to_insert) {
Ok(inserted) => { Ok(inserted) => Some(inserted),
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(inserted))));
}
Err(insert_error) => { Err(insert_error) => {
handle_insert_error( handle_insert_error(
insert_error, insert_error,
@ -120,6 +71,7 @@ fn handle_concrete_use_statement(
"Use Symbol", "Use Symbol",
diagnostics, diagnostics,
); );
None
} }
} }
} }
@ -133,54 +85,51 @@ fn nap1_use_statement(
match use_statement.suffix() { match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => { UseStatementSuffix::Identifier(identifier) => {
insert_concrete_use_symbol!( let maybe_symbol = maybe_insert_concrete_use_symbol(
ConcreteUseSymbol::new( use_statement,
&base_fqn, &identifier,
identifier.name(),
Some(SourceDefinition::from_identifier(identifier))
),
symbol_table, symbol_table,
&base_fqn, diagnostics,
identifier,
"Use Statement",
diagnostics
); );
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(Rc::new( if let Some(concrete_use_symbol) = maybe_symbol {
RefCell::new(ConcreteUseSymbol::new( use_statement.use_symbols_mut().push(UseSymbol::Concrete(concrete_use_symbol));
&base_fqn, }
identifier.name(),
Some(SourceDefinition::from_use_statement(use_statement)),
)),
)))));
} }
UseStatementSuffix::Star => { UseStatementSuffix::Star => {
insert_symbol!( let maybe_symbol = match symbol_table.insert_star_use_symbol(
insert_star_use_symbol, StarUseSymbol::new(&base_fqn, Some(SourceDefinition::from_use_statement(use_statement)))
StarUseSymbol::new( ) {
&base_fqn, Ok(inserted) => {
Some(SourceDefinition::from_use_statement(use_statement)) Some(todo!())
), },
symbol_table, Err(insert_error) => {
&base_fqn, handle_insert_error(
use_statement, insert_error,
"Use Statement", &base_fqn,
diagnostics use_statement.file_id(),
); use_statement.range(),
"Star Use Symbol",
diagnostics,
);
None
}
};
} }
UseStatementSuffix::UseList(use_list) => { UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() { let maybe_symbols = use_list.identifiers()
insert_concrete_use_symbol!( .map(|identifier| {
ConcreteUseSymbol::new( maybe_insert_concrete_use_symbol(
&base_fqn, use_statement,
identifier.name(), identifier,
Some(SourceDefinition::from_identifier(identifier)) symbol_table,
), diagnostics,
symbol_table, )
&base_fqn, })
identifier, .collect::<Vec<_>>();
"Use Statement", for maybe_symbol in maybe_symbols {
diagnostics if let Some(symbol) = maybe_symbol {
); use_statement.use_symbols_mut().push(UseSymbol::Concrete(symbol));
}
} }
} }
} }

View File

@ -1,34 +1,12 @@
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol; use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
use crate::name_analysis::symbol::use_symbol::UseSymbol; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, UseSymbol};
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
use crate::name_analysis::symbol_tree::SymbolTree; use crate::name_analysis::symbol_tree::SymbolTree;
use codespan_reporting::diagnostic::{Diagnostic, Label}; use crate::name_analysis::util::{handle_lookup_error, use_statement_base_fqn};
use std::range::Range; use std::cell::RefCell;
use std::rc::Rc;
fn handle_lookup_error(
err: SymbolLookupError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolLookupError::NoDefinition => {
let diagnostic = Diagnostic::error()
.with_message(format!(
"No such {} symbol '{}' in scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
);
diagnostics.push(diagnostic);
}
}
}
pub fn nap2_compilation_unit( pub fn nap2_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
@ -44,13 +22,12 @@ pub fn nap2_compilation_unit(
// TODO: declarations // TODO: declarations
} }
fn handle_concrete_use_symbol( fn find_usable_symbol(
use_statement: &UseStatement, use_statement: &UseStatement,
identifier: &Identifier, identifier: &Identifier,
symbol_tree: &SymbolTree, symbol_tree: &SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>, ) -> Option<UsableSymbol> {
) { let fqn_parts: Vec<&str> = {
let mut fqn_parts: Vec<&str> = {
let mut base: Vec<&str> = use_statement let mut base: Vec<&str> = use_statement
.prefixes() .prefixes()
.map(|prefix| prefix.identifier().name()) .map(|prefix| prefix.identifier().name())
@ -58,36 +35,67 @@ fn handle_concrete_use_symbol(
base.push(identifier.name()); base.push(identifier.name());
base base
}; };
let found = symbol_tree symbol_tree
.find_interface(&fqn_parts) .find_interface(&fqn_parts)
.map(|interface_symbol| ConcreteUsableSymbol::Interface(interface_symbol)) .map(|interface_symbol| UsableSymbol::Interface(interface_symbol))
.or_else(|| { .or_else(|| {
symbol_tree symbol_tree
.find_class(&fqn_parts) .find_class(&fqn_parts)
.map(|class_symbol| ConcreteUsableSymbol::Class(class_symbol)) .map(|class_symbol| UsableSymbol::Class(class_symbol))
}) })
.or_else(|| { .or_else(|| {
symbol_tree symbol_tree
.find_function(&fqn_parts) .find_function(&fqn_parts)
.map(|function_symbol| ConcreteUsableSymbol::Function(function_symbol)) .map(|function_symbol| UsableSymbol::Function(function_symbol))
}); })
if let Some(concrete_usable_symbol) = found { }
let use_symbol_ref = use_statement.use_symbol().unwrap().borrow();
match *use_symbol_ref { fn find_matching_concrete_use_symbol(
UseSymbol::Concrete(ref concrete_use_symbol) => { use_statement: &UseStatement,
concrete_use_symbol identifier: &Identifier,
.borrow_mut() ) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
.set_resolved_symbol(concrete_usable_symbol); let base_fqn = use_statement_base_fqn(use_statement);
use_statement
.use_symbols()
.iter()
.find(|use_symbol| match use_symbol {
UseSymbol::Concrete(concrete_use_symbol) => {
let borrowed = concrete_use_symbol.borrow();
borrowed.base_fqn() == base_fqn && borrowed.declared_name() == identifier.name()
} }
_ => panic!( _ => false,
"Unexpected UseSymbol type (expected Concrete, found: {:?}", })
*use_symbol_ref .map(|use_symbol| match use_symbol {
), UseSymbol::Concrete(concrete) => concrete.clone(),
_ => panic!(),
})
}
fn handle_concrete_use(
use_statement: &UseStatement,
identifier: &Identifier,
symbol_tree: &SymbolTree,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let maybe_usable_symbol = find_usable_symbol(use_statement, identifier, symbol_tree);
if let Some(usable_symbol) = maybe_usable_symbol {
let maybe_concrete_use_symbol =
find_matching_concrete_use_symbol(use_statement, identifier);
if let Some(concrete_use_symbol) = maybe_concrete_use_symbol {
concrete_use_symbol
.borrow_mut()
.set_resolved_symbol(usable_symbol);
} else {
panic!("Can't find matching ConcreteUseSymbol");
} }
} else { } else {
handle_lookup_error( handle_lookup_error(
SymbolLookupError::NoDefinition, SymbolLookupError::NoDefinition,
&fqn_parts.join("::"), &format!(
"{}::{}",
use_statement_base_fqn(use_statement),
identifier.name()
),
use_statement.file_id(), use_statement.file_id(),
use_statement.range(), use_statement.range(),
"Usable Symbol", "Usable Symbol",
@ -103,14 +111,14 @@ fn nap2_use_statement(
) { ) {
match use_statement.suffix() { match use_statement.suffix() {
UseStatementSuffix::Identifier(identifier) => { UseStatementSuffix::Identifier(identifier) => {
handle_concrete_use_symbol(use_statement, identifier, symbol_tree, diagnostics); handle_concrete_use(use_statement, identifier, symbol_tree, diagnostics);
} }
UseStatementSuffix::Star => { UseStatementSuffix::Star => {
todo!("Resolve star symbols") todo!("Resolve star symbols")
} }
UseStatementSuffix::UseList(use_list) => { UseStatementSuffix::UseList(use_list) => {
for identifier in use_list.identifiers() { for identifier in use_list.identifiers() {
handle_concrete_use_symbol(use_statement, identifier, symbol_tree, diagnostics); handle_concrete_use(use_statement, identifier, symbol_tree, diagnostics);
} }
} }
} }

View File

@ -5,7 +5,7 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ConcreteUsableSymbol { pub enum UsableSymbol {
Interface(Rc<RefCell<InterfaceSymbol>>), Interface(Rc<RefCell<InterfaceSymbol>>),
Class(Rc<RefCell<ClassSymbol>>), Class(Rc<RefCell<ClassSymbol>>),
Function(Rc<RefCell<FunctionSymbol>>), Function(Rc<RefCell<FunctionSymbol>>),

View File

@ -1,5 +1,5 @@
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol; use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
use std::cell::RefCell; use std::cell::RefCell;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc; use std::rc::Rc;
@ -24,7 +24,7 @@ pub struct ConcreteUseSymbol {
base_fqn: String, base_fqn: String,
declared_name: String, declared_name: String,
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
resolved_symbol: Option<ConcreteUsableSymbol>, resolved_symbol: Option<UsableSymbol>,
} }
impl ConcreteUseSymbol { impl ConcreteUseSymbol {
@ -53,11 +53,11 @@ impl ConcreteUseSymbol {
self.source_definition.as_ref() self.source_definition.as_ref()
} }
pub fn resolved_symbol(&self) -> Option<&ConcreteUsableSymbol> { pub fn resolved_symbol(&self) -> Option<&UsableSymbol> {
self.resolved_symbol.as_ref() self.resolved_symbol.as_ref()
} }
pub fn set_resolved_symbol(&mut self, symbol: ConcreteUsableSymbol) { pub fn set_resolved_symbol(&mut self, symbol: UsableSymbol) {
self.resolved_symbol = Some(symbol); self.resolved_symbol = Some(symbol);
} }
} }

View File

@ -2,7 +2,6 @@ use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol; use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol};
use crate::name_analysis::symbol::variable_symbol::VariableSymbol; use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
use crate::name_analysis::symbol::*; use crate::name_analysis::symbol::*;
@ -10,7 +9,6 @@ use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
use scope::Scope; use scope::Scope;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::VecDeque;
use std::fmt::Display; use std::fmt::Display;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
@ -81,10 +79,6 @@ impl SymbolTable {
.cloned() .cloned()
} }
fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> {
self.current_scope().star_use_symbols().get(base_fqn)
}
fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> { fn find_current_scope_module_symbol(&self, declared_name: &str) -> Option<&ModuleSymbol> {
self.current_scope().module_symbols().get(declared_name) self.current_scope().module_symbols().get(declared_name)
} }
@ -158,19 +152,11 @@ impl SymbolTable {
pub fn insert_star_use_symbol( pub fn insert_star_use_symbol(
&mut self, &mut self,
star_use_symbol: StarUseSymbol, star_use_symbol: StarUseSymbol,
) -> Result<(), SymbolInsertError> { ) -> Result<Rc<RefCell<StarUseSymbol>>, SymbolInsertError> {
if let Some(defined_symbol) = let inserted = self
self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn()) .current_scope_mut()
{ .insert_star_use_symbol(star_use_symbol);
Err(SymbolAlreadyDefined(Symbol::Use(UseSymbol::Star( Ok(inserted)
defined_symbol.clone(),
))))
} else {
self.current_scope_mut()
.star_use_symbols_mut()
.insert(star_use_symbol.base_fqn().to_string(), star_use_symbol);
Ok(())
}
} }
pub fn insert_module_symbol( pub fn insert_module_symbol(

View File

@ -17,7 +17,7 @@ pub struct Scope {
id: usize, id: usize,
children: Vec<usize>, children: Vec<usize>,
concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>, concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>,
star_use_symbols: HashMap<String, StarUseSymbol>, star_use_symbols: HashMap<String, Rc<RefCell<StarUseSymbol>>>,
module_symbols: HashMap<String, ModuleSymbol>, module_symbols: HashMap<String, ModuleSymbol>,
interface_symbols: HashMap<Rc<String>, Rc<RefCell<InterfaceSymbol>>>, interface_symbols: HashMap<Rc<String>, Rc<RefCell<InterfaceSymbol>>>,
class_symbols: HashMap<Rc<String>, Rc<RefCell<ClassSymbol>>>, class_symbols: HashMap<Rc<String>, Rc<RefCell<ClassSymbol>>>,
@ -72,13 +72,11 @@ impl Scope {
) -> &mut HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> { ) -> &mut HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> {
&mut self.concrete_use_symbols &mut self.concrete_use_symbols
} }
pub fn star_use_symbols(&self) -> &HashMap<String, StarUseSymbol> { pub fn insert_star_use_symbol(&mut self, symbol: StarUseSymbol) -> Rc<RefCell<StarUseSymbol>> {
&self.star_use_symbols let as_rc = Rc::new(RefCell::new(symbol));
} self.star_use_symbols.insert(as_rc.borrow().base_fqn().to_string(), as_rc.clone());
as_rc.clone()
pub fn star_use_symbols_mut(&mut self) -> &mut HashMap<String, StarUseSymbol> {
&mut self.star_use_symbols
} }
pub fn module_symbols(&self) -> &HashMap<String, ModuleSymbol> { pub fn module_symbols(&self) -> &HashMap<String, ModuleSymbol> {
@ -167,7 +165,7 @@ impl Display for Scope {
self.debug_name() self.debug_name()
)?; )?;
write_symbols!(f, self.concrete_use_symbols()); write_symbols!(f, self.concrete_use_symbols());
write_symbols!(f, self.star_use_symbols()); todo!("self.star_use_symbols");
write_symbols!(f, self.module_symbols()); write_symbols!(f, self.module_symbols());
todo!("self.concrete_type_symbols"); todo!("self.concrete_type_symbols");
write_symbols!(f, self.function_symbols()); write_symbols!(f, self.function_symbols());

View File

@ -1,11 +1,68 @@
use crate::ast::node::UseStatement; use crate::ast::node::UseStatement;
use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolLookupError};
use codespan_reporting::diagnostic::{Diagnostic, Label};
use std::range::Range;
pub fn use_statement_base_fqn( pub fn use_statement_base_fqn(use_statement: &UseStatement) -> String {
use_statement: &UseStatement
) -> String {
use_statement use_statement
.prefixes() .prefixes()
.map(|prefix| prefix.identifier().name()) .map(|prefix| prefix.identifier().name())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("::") .join("::")
} }
pub fn handle_insert_error(
err: SymbolInsertError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolInsertError::SymbolAlreadyDefined(s) => {
let mut diagnostic = Diagnostic::error()
.with_message(format!(
"{} symbol '{}' already defined in the current scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range)
.with_message("Symbol duplicated here."),
);
if let Some(source_definition) = s.definition() {
diagnostic = diagnostic.with_label(
Label::secondary(source_definition.file_id(), source_definition.range())
.with_message("Symbol defined here."),
);
}
diagnostics.push(diagnostic);
}
}
}
pub fn handle_lookup_error(
err: SymbolLookupError,
error_symbol_name: &str,
error_file_id: usize,
error_range: Range<usize>,
symbol_types: &str,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match err {
SymbolLookupError::NoDefinition => {
let diagnostic = Diagnostic::error()
.with_message(format!(
"No such {} symbol '{}' in scope.",
symbol_types, error_symbol_name,
))
.with_label(
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
);
diagnostics.push(diagnostic);
}
}
}

View File

@ -249,9 +249,9 @@ UseStatement:
special: special:
kind: range kind: range
fields: fields:
- use_symbol: - use_symbols:
kind: UseSymbol kind: UseSymbol
wrap: rc_ref_cell vec: true
UseStatementPrefix: UseStatementPrefix:
struct: struct:
children: children: