WIP more name analysis.
This commit is contained in:
parent
bdbc2543b8
commit
664aebfd61
@ -10,15 +10,14 @@ fn deserialize_field(field_yaml: &Yaml) -> StructField {
|
||||
let kind = props["kind"].as_str().unwrap();
|
||||
let wrap = if let Some(wrap) = props["wrap"].as_str() {
|
||||
match wrap {
|
||||
"rc_ref_cell" => {
|
||||
Some(StructFieldWrap::RcRefCell)
|
||||
}
|
||||
_ => panic!()
|
||||
"rc_ref_cell" => Some(StructFieldWrap::RcRefCell),
|
||||
_ => panic!(),
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
@ -112,7 +111,11 @@ fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild {
|
||||
match props["kind"].as_str().unwrap() {
|
||||
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
|
||||
"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
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +172,8 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
};
|
||||
|
||||
let fields = if struct_yaml["fields"].is_array() {
|
||||
struct_yaml["fields"].as_vec()
|
||||
struct_yaml["fields"]
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|field| deserialize_field(field))
|
||||
@ -180,7 +184,8 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
};
|
||||
|
||||
let derive = if struct_yaml["derive"].is_array() {
|
||||
struct_yaml["derive"].as_vec()
|
||||
struct_yaml["derive"]
|
||||
.as_vec()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|derive| derive.as_str().unwrap().to_string())
|
||||
|
||||
@ -6,7 +6,12 @@ pub struct 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 {
|
||||
build: build.to_string(),
|
||||
children,
|
||||
@ -51,10 +56,8 @@ impl StructChild {
|
||||
|
||||
pub fn unwrap_special(&self) -> Option<&SpecialChild> {
|
||||
match self {
|
||||
StructChild::Special(special_child) => {
|
||||
Some(special_child)
|
||||
},
|
||||
_ => None
|
||||
StructChild::Special(special_child) => Some(special_child),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,7 +257,7 @@ impl SpecialChild {
|
||||
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
kind
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,14 +281,16 @@ pub struct StructField {
|
||||
name: String,
|
||||
kind: String,
|
||||
wrap: Option<StructFieldWrap>,
|
||||
vec: bool,
|
||||
}
|
||||
|
||||
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 {
|
||||
name: name.to_string(),
|
||||
kind: kind.to_string(),
|
||||
wrap,
|
||||
vec,
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,9 +305,13 @@ impl StructField {
|
||||
pub fn wrap(&self) -> Option<&StructFieldWrap> {
|
||||
self.wrap.as_ref()
|
||||
}
|
||||
|
||||
pub fn vec(&self) -> bool {
|
||||
self.vec
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum StructFieldWrap {
|
||||
RcRefCell
|
||||
RcRefCell,
|
||||
}
|
||||
|
||||
@ -19,9 +19,20 @@ fn make_field_accessors(field: &StructField) -> TokenStream {
|
||||
quote! { #inner }
|
||||
}
|
||||
};
|
||||
let set_field_ident = format_ident!("set_{}", field.name());
|
||||
let field_ident_mut = format_ident!("{}_mut", field.name());
|
||||
|
||||
if field.vec() {
|
||||
quote! {
|
||||
pub fn #field_ident(&self) -> &[#field_type] {
|
||||
self.#field_ident.as_slice()
|
||||
}
|
||||
|
||||
pub fn #field_ident_mut(&mut self) -> &mut Vec<#field_type> {
|
||||
&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()
|
||||
@ -36,18 +47,23 @@ fn make_field_accessors(field: &StructField) -> TokenStream {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_field_initializer(field: &StructField) -> TokenStream {
|
||||
let field_ident = format_ident!("{}", field.name());
|
||||
if field.vec() {
|
||||
quote! { #field_ident: vec![] }
|
||||
} else {
|
||||
quote! { #field_ident: None }
|
||||
}
|
||||
}
|
||||
|
||||
fn make_annotated_field(field: &StructField) -> TokenStream {
|
||||
let field_ident = format_ident!("{}", field.name());
|
||||
let field_type = if let Some(wrap) = field.wrap() {
|
||||
let inner = format_ident!("{}", field.kind());
|
||||
match wrap {
|
||||
StructFieldWrap::RcRefCell => {
|
||||
let inner = format_ident!("{}", field.kind());
|
||||
quote! { Rc<RefCell<#inner>> }
|
||||
}
|
||||
}
|
||||
@ -56,10 +72,16 @@ fn make_annotated_field(field: &StructField) -> TokenStream {
|
||||
quote! { #inner }
|
||||
};
|
||||
|
||||
if field.vec() {
|
||||
quote! {
|
||||
#field_ident: Vec<#field_type>
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#field_ident: Option<#field_type>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream {
|
||||
let child_ident = format_ident!("{}", vec_child.name());
|
||||
|
||||
@ -3,50 +3,17 @@ use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::fqn_context::FqnContext;
|
||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||
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::util::use_statement_base_fqn;
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use crate::name_analysis::util;
|
||||
use crate::name_analysis::util::{handle_insert_error, use_statement_base_fqn};
|
||||
use std::cell::RefCell;
|
||||
use std::range::Range;
|
||||
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 {
|
||||
($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) {
|
||||
handle_insert_error(
|
||||
util::handle_insert_error(
|
||||
insert_error,
|
||||
$name,
|
||||
$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(
|
||||
file_name: &str,
|
||||
compilation_unit: &mut CompilationUnit,
|
||||
@ -95,12 +48,12 @@ pub fn nap1_compilation_unit(
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
|
||||
fn handle_concrete_use_statement(
|
||||
use_statement: &mut UseStatement,
|
||||
fn maybe_insert_concrete_use_symbol(
|
||||
use_statement: &UseStatement,
|
||||
identifier: &Identifier,
|
||||
symbol_table: &mut SymbolTable,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
let base_fqn = use_statement_base_fqn(use_statement);
|
||||
let to_insert = ConcreteUseSymbol::new(
|
||||
&base_fqn,
|
||||
@ -108,9 +61,7 @@ fn handle_concrete_use_statement(
|
||||
Some(SourceDefinition::from_identifier(identifier)),
|
||||
);
|
||||
match symbol_table.insert_concrete_use_symbol(to_insert) {
|
||||
Ok(inserted) => {
|
||||
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(inserted))));
|
||||
}
|
||||
Ok(inserted) => Some(inserted),
|
||||
Err(insert_error) => {
|
||||
handle_insert_error(
|
||||
insert_error,
|
||||
@ -120,6 +71,7 @@ fn handle_concrete_use_statement(
|
||||
"Use Symbol",
|
||||
diagnostics,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,54 +85,51 @@ fn nap1_use_statement(
|
||||
|
||||
match use_statement.suffix() {
|
||||
UseStatementSuffix::Identifier(identifier) => {
|
||||
insert_concrete_use_symbol!(
|
||||
ConcreteUseSymbol::new(
|
||||
&base_fqn,
|
||||
identifier.name(),
|
||||
Some(SourceDefinition::from_identifier(identifier))
|
||||
),
|
||||
let maybe_symbol = maybe_insert_concrete_use_symbol(
|
||||
use_statement,
|
||||
&identifier,
|
||||
symbol_table,
|
||||
&base_fqn,
|
||||
identifier,
|
||||
"Use Statement",
|
||||
diagnostics
|
||||
diagnostics,
|
||||
);
|
||||
use_statement.set_use_symbol(Rc::new(RefCell::new(UseSymbol::Concrete(Rc::new(
|
||||
RefCell::new(ConcreteUseSymbol::new(
|
||||
&base_fqn,
|
||||
identifier.name(),
|
||||
Some(SourceDefinition::from_use_statement(use_statement)),
|
||||
)),
|
||||
)))));
|
||||
if let Some(concrete_use_symbol) = maybe_symbol {
|
||||
use_statement.use_symbols_mut().push(UseSymbol::Concrete(concrete_use_symbol));
|
||||
}
|
||||
}
|
||||
UseStatementSuffix::Star => {
|
||||
insert_symbol!(
|
||||
insert_star_use_symbol,
|
||||
StarUseSymbol::new(
|
||||
let maybe_symbol = match symbol_table.insert_star_use_symbol(
|
||||
StarUseSymbol::new(&base_fqn, Some(SourceDefinition::from_use_statement(use_statement)))
|
||||
) {
|
||||
Ok(inserted) => {
|
||||
Some(todo!())
|
||||
},
|
||||
Err(insert_error) => {
|
||||
handle_insert_error(
|
||||
insert_error,
|
||||
&base_fqn,
|
||||
Some(SourceDefinition::from_use_statement(use_statement))
|
||||
),
|
||||
symbol_table,
|
||||
&base_fqn,
|
||||
use_statement,
|
||||
"Use Statement",
|
||||
diagnostics
|
||||
use_statement.file_id(),
|
||||
use_statement.range(),
|
||||
"Star Use Symbol",
|
||||
diagnostics,
|
||||
);
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
UseStatementSuffix::UseList(use_list) => {
|
||||
for identifier in use_list.identifiers() {
|
||||
insert_concrete_use_symbol!(
|
||||
ConcreteUseSymbol::new(
|
||||
&base_fqn,
|
||||
identifier.name(),
|
||||
Some(SourceDefinition::from_identifier(identifier))
|
||||
),
|
||||
symbol_table,
|
||||
&base_fqn,
|
||||
let maybe_symbols = use_list.identifiers()
|
||||
.map(|identifier| {
|
||||
maybe_insert_concrete_use_symbol(
|
||||
use_statement,
|
||||
identifier,
|
||||
"Use Statement",
|
||||
diagnostics
|
||||
);
|
||||
symbol_table,
|
||||
diagnostics,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
for maybe_symbol in maybe_symbols {
|
||||
if let Some(symbol) = maybe_symbol {
|
||||
use_statement.use_symbols_mut().push(UseSymbol::Concrete(symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,34 +1,12 @@
|
||||
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::usable_symbol::ConcreteUsableSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, UseSymbol};
|
||||
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||
use crate::name_analysis::symbol_tree::SymbolTree;
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use std::range::Range;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::name_analysis::util::{handle_lookup_error, use_statement_base_fqn};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn nap2_compilation_unit(
|
||||
compilation_unit: &mut CompilationUnit,
|
||||
@ -44,13 +22,12 @@ pub fn nap2_compilation_unit(
|
||||
// TODO: declarations
|
||||
}
|
||||
|
||||
fn handle_concrete_use_symbol(
|
||||
fn find_usable_symbol(
|
||||
use_statement: &UseStatement,
|
||||
identifier: &Identifier,
|
||||
symbol_tree: &SymbolTree,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let mut fqn_parts: Vec<&str> = {
|
||||
) -> Option<UsableSymbol> {
|
||||
let fqn_parts: Vec<&str> = {
|
||||
let mut base: Vec<&str> = use_statement
|
||||
.prefixes()
|
||||
.map(|prefix| prefix.identifier().name())
|
||||
@ -58,36 +35,67 @@ fn handle_concrete_use_symbol(
|
||||
base.push(identifier.name());
|
||||
base
|
||||
};
|
||||
let found = symbol_tree
|
||||
symbol_tree
|
||||
.find_interface(&fqn_parts)
|
||||
.map(|interface_symbol| ConcreteUsableSymbol::Interface(interface_symbol))
|
||||
.map(|interface_symbol| UsableSymbol::Interface(interface_symbol))
|
||||
.or_else(|| {
|
||||
symbol_tree
|
||||
.find_class(&fqn_parts)
|
||||
.map(|class_symbol| ConcreteUsableSymbol::Class(class_symbol))
|
||||
.map(|class_symbol| UsableSymbol::Class(class_symbol))
|
||||
})
|
||||
.or_else(|| {
|
||||
symbol_tree
|
||||
.find_function(&fqn_parts)
|
||||
.map(|function_symbol| ConcreteUsableSymbol::Function(function_symbol))
|
||||
});
|
||||
if let Some(concrete_usable_symbol) = found {
|
||||
let use_symbol_ref = use_statement.use_symbol().unwrap().borrow();
|
||||
match *use_symbol_ref {
|
||||
UseSymbol::Concrete(ref concrete_use_symbol) => {
|
||||
.map(|function_symbol| UsableSymbol::Function(function_symbol))
|
||||
})
|
||||
}
|
||||
|
||||
fn find_matching_concrete_use_symbol(
|
||||
use_statement: &UseStatement,
|
||||
identifier: &Identifier,
|
||||
) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
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()
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.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(concrete_usable_symbol);
|
||||
}
|
||||
_ => panic!(
|
||||
"Unexpected UseSymbol type (expected Concrete, found: {:?}",
|
||||
*use_symbol_ref
|
||||
),
|
||||
.set_resolved_symbol(usable_symbol);
|
||||
} else {
|
||||
panic!("Can't find matching ConcreteUseSymbol");
|
||||
}
|
||||
} else {
|
||||
handle_lookup_error(
|
||||
SymbolLookupError::NoDefinition,
|
||||
&fqn_parts.join("::"),
|
||||
&format!(
|
||||
"{}::{}",
|
||||
use_statement_base_fqn(use_statement),
|
||||
identifier.name()
|
||||
),
|
||||
use_statement.file_id(),
|
||||
use_statement.range(),
|
||||
"Usable Symbol",
|
||||
@ -103,14 +111,14 @@ fn nap2_use_statement(
|
||||
) {
|
||||
match use_statement.suffix() {
|
||||
UseStatementSuffix::Identifier(identifier) => {
|
||||
handle_concrete_use_symbol(use_statement, identifier, symbol_tree, diagnostics);
|
||||
handle_concrete_use(use_statement, identifier, symbol_tree, diagnostics);
|
||||
}
|
||||
UseStatementSuffix::Star => {
|
||||
todo!("Resolve star symbols")
|
||||
}
|
||||
UseStatementSuffix::UseList(use_list) => {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ConcreteUsableSymbol {
|
||||
pub enum UsableSymbol {
|
||||
Interface(Rc<RefCell<InterfaceSymbol>>),
|
||||
Class(Rc<RefCell<ClassSymbol>>),
|
||||
Function(Rc<RefCell<FunctionSymbol>>),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
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::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
@ -24,7 +24,7 @@ pub struct ConcreteUseSymbol {
|
||||
base_fqn: String,
|
||||
declared_name: String,
|
||||
source_definition: Option<SourceDefinition>,
|
||||
resolved_symbol: Option<ConcreteUsableSymbol>,
|
||||
resolved_symbol: Option<UsableSymbol>,
|
||||
}
|
||||
|
||||
impl ConcreteUseSymbol {
|
||||
@ -53,11 +53,11 @@ impl ConcreteUseSymbol {
|
||||
self.source_definition.as_ref()
|
||||
}
|
||||
|
||||
pub fn resolved_symbol(&self) -> Option<&ConcreteUsableSymbol> {
|
||||
pub fn resolved_symbol(&self) -> Option<&UsableSymbol> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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::module_symbol::ModuleSymbol;
|
||||
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::variable_symbol::VariableSymbol;
|
||||
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 scope::Scope;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
@ -81,10 +79,6 @@ impl SymbolTable {
|
||||
.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> {
|
||||
self.current_scope().module_symbols().get(declared_name)
|
||||
}
|
||||
@ -158,19 +152,11 @@ impl SymbolTable {
|
||||
pub fn insert_star_use_symbol(
|
||||
&mut self,
|
||||
star_use_symbol: StarUseSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(Symbol::Use(UseSymbol::Star(
|
||||
defined_symbol.clone(),
|
||||
))))
|
||||
} else {
|
||||
self.current_scope_mut()
|
||||
.star_use_symbols_mut()
|
||||
.insert(star_use_symbol.base_fqn().to_string(), star_use_symbol);
|
||||
Ok(())
|
||||
}
|
||||
) -> Result<Rc<RefCell<StarUseSymbol>>, SymbolInsertError> {
|
||||
let inserted = self
|
||||
.current_scope_mut()
|
||||
.insert_star_use_symbol(star_use_symbol);
|
||||
Ok(inserted)
|
||||
}
|
||||
|
||||
pub fn insert_module_symbol(
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct Scope {
|
||||
id: usize,
|
||||
children: Vec<usize>,
|
||||
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>,
|
||||
interface_symbols: HashMap<Rc<String>, Rc<RefCell<InterfaceSymbol>>>,
|
||||
class_symbols: HashMap<Rc<String>, Rc<RefCell<ClassSymbol>>>,
|
||||
@ -73,12 +73,10 @@ impl Scope {
|
||||
&mut self.concrete_use_symbols
|
||||
}
|
||||
|
||||
pub fn star_use_symbols(&self) -> &HashMap<String, StarUseSymbol> {
|
||||
&self.star_use_symbols
|
||||
}
|
||||
|
||||
pub fn star_use_symbols_mut(&mut self) -> &mut HashMap<String, StarUseSymbol> {
|
||||
&mut self.star_use_symbols
|
||||
pub fn insert_star_use_symbol(&mut self, symbol: StarUseSymbol) -> Rc<RefCell<StarUseSymbol>> {
|
||||
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 module_symbols(&self) -> &HashMap<String, ModuleSymbol> {
|
||||
@ -167,7 +165,7 @@ impl Display for Scope {
|
||||
self.debug_name()
|
||||
)?;
|
||||
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());
|
||||
todo!("self.concrete_type_symbols");
|
||||
write_symbols!(f, self.function_symbols());
|
||||
|
||||
@ -1,11 +1,68 @@
|
||||
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(
|
||||
use_statement: &UseStatement
|
||||
) -> String {
|
||||
pub fn use_statement_base_fqn(use_statement: &UseStatement) -> String {
|
||||
use_statement
|
||||
.prefixes()
|
||||
.map(|prefix| prefix.identifier().name())
|
||||
.collect::<Vec<_>>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,9 +249,9 @@ UseStatement:
|
||||
special:
|
||||
kind: range
|
||||
fields:
|
||||
- use_symbol:
|
||||
- use_symbols:
|
||||
kind: UseSymbol
|
||||
wrap: rc_ref_cell
|
||||
vec: true
|
||||
UseStatementPrefix:
|
||||
struct:
|
||||
children:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user