Bunch of work on name analysis. Reintroduce Rc<RefCell<_>> for symbols.
This commit is contained in:
		
							parent
							
								
									273d197841
								
							
						
					
					
						commit
						b5c0e44eeb
					
				| @ -5,6 +5,22 @@ use crate::deserialize::util::{get_as_bool, make_build_fn_name, unwrap_single_me | |||||||
| use crate::spec::struct_spec::*; | use crate::spec::struct_spec::*; | ||||||
| use yaml_rust2::Yaml; | use yaml_rust2::Yaml; | ||||||
| 
 | 
 | ||||||
|  | fn deserialize_field(field_yaml: &Yaml) -> StructField { | ||||||
|  |     let (name, props) = unwrap_single_member_hash(field_yaml); | ||||||
|  |     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!() | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         None | ||||||
|  |     }; | ||||||
|  |     StructField::new(&name, kind, wrap) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn deserialize_skip_child(props: &Yaml) -> StructChild { | fn deserialize_skip_child(props: &Yaml) -> StructChild { | ||||||
|     let rule = props["rule"].as_str().unwrap(); |     let rule = props["rule"].as_str().unwrap(); | ||||||
|     StructChild::SkipChild(SkipChild::new(rule)) |     StructChild::SkipChild(SkipChild::new(rule)) | ||||||
| @ -151,6 +167,18 @@ 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() { | ||||||
|  |         struct_yaml["fields"].as_vec() | ||||||
|  |             .unwrap() | ||||||
|  |             .iter() | ||||||
|  |             .map(|field| deserialize_field(field)) | ||||||
|  |             .map(Box::new) | ||||||
|  |             .collect() | ||||||
|  |     } else { | ||||||
|  |         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() | ||||||
| @ -161,5 +189,5 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec { | |||||||
|         vec![] |         vec![] | ||||||
|     }; |     }; | ||||||
|     
 |     
 | ||||||
|     StructSpec::new(name, children, derive) |     StructSpec::new(name, children, fields, derive) | ||||||
| } | } | ||||||
|  | |||||||
| @ -114,6 +114,9 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { | |||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
|     let combined = quote! { |     let combined = quote! { | ||||||
|         use std::range::Range; |         use std::range::Range; | ||||||
|  |         use std::rc::Rc; | ||||||
|  |         use std::cell::RefCell; | ||||||
|  |         use crate::name_analysis::symbol::use_symbol::UseSymbol; | ||||||
| 
 | 
 | ||||||
|         #(#types)* |         #(#types)* | ||||||
|     }; |     }; | ||||||
|  | |||||||
| @ -1,14 +1,16 @@ | |||||||
| pub struct StructSpec { | pub struct StructSpec { | ||||||
|     build: String, |     build: String, | ||||||
|     children: Vec<Box<StructChild>>, |     children: Vec<Box<StructChild>>, | ||||||
|  |     fields: Vec<Box<StructField>>, | ||||||
|     derive: Vec<String>, |     derive: Vec<String>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl StructSpec { | impl StructSpec { | ||||||
|     pub fn new(build: &str, children: Vec<Box<StructChild>>, 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, | ||||||
|  |             fields, | ||||||
|             derive, |             derive, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -23,6 +25,10 @@ impl StructSpec { | |||||||
|         self.children.iter().map(Box::as_ref) |         self.children.iter().map(Box::as_ref) | ||||||
|     } |     } | ||||||
|     
 |     
 | ||||||
|  |     pub fn fields(&self) -> impl Iterator<Item = &StructField> { | ||||||
|  |         self.fields.iter().map(Box::as_ref) | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|     pub fn derive(&self) -> &[String] { |     pub fn derive(&self) -> &[String] { | ||||||
|         &self.derive |         &self.derive | ||||||
|     } |     } | ||||||
| @ -266,3 +272,37 @@ pub enum SpecialChildKind { | |||||||
|     FileId, |     FileId, | ||||||
|     Range, |     Range, | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub struct StructField { | ||||||
|  |     name: String, | ||||||
|  |     kind: String, | ||||||
|  |     wrap: Option<StructFieldWrap>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl StructField { | ||||||
|  |     pub fn new(name: &str, kind: &str, wrap: Option<StructFieldWrap>) -> Self { | ||||||
|  |         Self { | ||||||
|  |             name: name.to_string(), | ||||||
|  |             kind: kind.to_string(), | ||||||
|  |             wrap, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn name(&self) -> &str { | ||||||
|  |         &self.name | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn kind(&self) -> &str { | ||||||
|  |         &self.kind | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn wrap(&self) -> Option<&StructFieldWrap> { | ||||||
|  |         self.wrap.as_ref() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | pub enum StructFieldWrap { | ||||||
|  |     RcRefCell | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,10 +1,66 @@ | |||||||
| use crate::spec::struct_spec::{ | use crate::spec::struct_spec::{ | ||||||
|     MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, |     MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField, | ||||||
|     VecChild, VecChildBuild, |     StructFieldWrap, StructSpec, VecChild, VecChildBuild, | ||||||
| }; | }; | ||||||
| use proc_macro2::{Ident, TokenStream}; | use proc_macro2::{Ident, TokenStream}; | ||||||
| use quote::{format_ident, quote}; | use quote::{format_ident, quote}; | ||||||
| 
 | 
 | ||||||
|  | fn make_field_accessors(field: &StructField) -> TokenStream { | ||||||
|  |     let field_ident = format_ident!("{}", field.name()); | ||||||
|  |     let field_type = { | ||||||
|  |         let inner = format_ident!("{}", field.kind()); | ||||||
|  |         if let Some(wrap) = field.wrap() { | ||||||
|  |             match wrap { | ||||||
|  |                 StructFieldWrap::RcRefCell => { | ||||||
|  |                     quote! { Rc<RefCell<#inner>> } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             quote! { #inner } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |     let set_field_ident = format_ident!("set_{}", field.name()); | ||||||
|  |     let field_ident_mut = format_ident!("{}_mut", 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 { | ||||||
|  |     let field_ident = format_ident!("{}", field.name()); | ||||||
|  |     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() { | ||||||
|  |         match wrap { | ||||||
|  |             StructFieldWrap::RcRefCell => { | ||||||
|  |                 let inner = format_ident!("{}", field.kind()); | ||||||
|  |                 quote! { Rc<RefCell<#inner>> } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         let inner = format_ident!("{}", field.kind()); | ||||||
|  |         quote! { #inner } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     quote! { | ||||||
|  |         #field_ident: Option<#field_type> | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream { | fn make_vec_child_accessors(vec_child: &VecChild) -> TokenStream { | ||||||
|     let child_ident = format_ident!("{}", vec_child.name()); |     let child_ident = format_ident!("{}", vec_child.name()); | ||||||
|     match vec_child.build() { |     match vec_child.build() { | ||||||
| @ -184,13 +240,18 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> { | |||||||
| 
 | 
 | ||||||
| pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { | pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { | ||||||
|     let type_ident = format_ident!("{}", build_spec.build()); |     let type_ident = format_ident!("{}", build_spec.build()); | ||||||
|     let annotated_members = build_spec |     let annotated_children_members = build_spec | ||||||
|         .children() |         .children() | ||||||
|         .map(|child| make_annotated_member(child)) |         .map(|child| make_annotated_member(child)) | ||||||
|         .filter(Option::is_some) |         .filter(Option::is_some) | ||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|  |     let annotated_fields = build_spec | ||||||
|  |         .fields() | ||||||
|  |         .map(|field| make_annotated_field(field)) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|     let member_names = build_spec |     let member_names = build_spec | ||||||
|         .children() |         .children() | ||||||
|         .map(|child| make_member_ident(child)) |         .map(|child| make_member_ident(child)) | ||||||
| @ -198,17 +259,28 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { | |||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|     let accessors = build_spec |     let field_initializers = build_spec | ||||||
|  |         .fields() | ||||||
|  |         .map(|field| make_field_initializer(field)) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|  |     let child_accessors = build_spec | ||||||
|         .children() |         .children() | ||||||
|         .map(|child| make_accessors(child)) |         .map(|child| make_accessors(child)) | ||||||
|         .filter(Option::is_some) |         .filter(Option::is_some) | ||||||
|         .map(Option::unwrap) |         .map(Option::unwrap) | ||||||
|         .collect::<Vec<_>>(); |         .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|  |     let field_accessors = build_spec | ||||||
|  |         .fields() | ||||||
|  |         .map(|field| make_field_accessors(field)) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  | 
 | ||||||
|     let struct_stream = { |     let struct_stream = { | ||||||
|         let base = quote! { |         let base = quote! { | ||||||
|             pub struct #type_ident { |             pub struct #type_ident { | ||||||
|                 #(#annotated_members),* |                 #(#annotated_children_members,)* | ||||||
|  |                 #(#annotated_fields,)* | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if !build_spec.derive().is_empty() { |         if !build_spec.derive().is_empty() { | ||||||
| @ -231,13 +303,15 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream { | |||||||
|         #struct_stream |         #struct_stream | ||||||
| 
 | 
 | ||||||
|         impl #type_ident { |         impl #type_ident { | ||||||
|             pub fn new(#(#annotated_members),*) -> Self { |             pub fn new(#(#annotated_children_members),*) -> Self { | ||||||
|                 Self { |                 Self { | ||||||
|                     #(#member_names),* |                     #(#member_names,)* | ||||||
|  |                     #(#field_initializers,)* | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             #(#accessors)* |             #(#child_accessors)* | ||||||
|  |             #(#field_accessors)* | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,12 +1,14 @@ | |||||||
| use crate::ast::node::{CompilationUnit, UseStatement, UseStatementSuffix}; | use std::cell::RefCell; | ||||||
|  | use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix}; | ||||||
| use crate::diagnostic::DmDiagnostic; | 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}; | use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol, UseSymbol}; | ||||||
| use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; | ||||||
| use crate::name_analysis::util::use_statement_base_fqn; | use crate::name_analysis::util::use_statement_base_fqn; | ||||||
| use codespan_reporting::diagnostic::{Diagnostic, Label}; | use codespan_reporting::diagnostic::{Diagnostic, Label}; | ||||||
| use std::range::Range; | use std::range::Range; | ||||||
|  | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| fn handle_insert_error( | fn handle_insert_error( | ||||||
|     err: SymbolInsertError, |     err: SymbolInsertError, | ||||||
| @ -69,7 +71,7 @@ macro_rules! insert_concrete_use_symbol { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn np1_compilation_unit( | pub fn nap1_compilation_unit( | ||||||
|     file_name: &str, |     file_name: &str, | ||||||
|     compilation_unit: &mut CompilationUnit, |     compilation_unit: &mut CompilationUnit, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
| @ -85,13 +87,42 @@ pub fn np1_compilation_unit( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for use_statement in compilation_unit.use_statements_mut() { |     for use_statement in compilation_unit.use_statements_mut() { | ||||||
|         np1_use_statement(use_statement, symbol_table, diagnostics); |         nap1_use_statement(use_statement, symbol_table, diagnostics); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     symbol_table.pop_scope(); |     symbol_table.pop_scope(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn np1_use_statement( | fn handle_concrete_use_statement( | ||||||
|  |     use_statement: &mut UseStatement, | ||||||
|  |     identifier: &Identifier, | ||||||
|  |     symbol_table: &mut SymbolTable, | ||||||
|  |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | ) { | ||||||
|  |     let base_fqn = use_statement_base_fqn(use_statement); | ||||||
|  |     let to_insert = ConcreteUseSymbol::new( | ||||||
|  |         &base_fqn, | ||||||
|  |         identifier.name(), | ||||||
|  |         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)))); | ||||||
|  |         } | ||||||
|  |         Err(insert_error) => { | ||||||
|  |             handle_insert_error( | ||||||
|  |                 insert_error, | ||||||
|  |                 identifier.name(), | ||||||
|  |                 identifier.file_id(), | ||||||
|  |                 identifier.range(), | ||||||
|  |                 "Use Symbol", | ||||||
|  |                 diagnostics | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn nap1_use_statement( | ||||||
|     use_statement: &mut UseStatement, |     use_statement: &mut UseStatement, | ||||||
|     symbol_table: &mut SymbolTable, |     symbol_table: &mut SymbolTable, | ||||||
|     diagnostics: &mut Vec<DmDiagnostic>, |     diagnostics: &mut Vec<DmDiagnostic>, | ||||||
|  | |||||||
| @ -23,14 +23,13 @@ The resolve phase has one main responsibility: resolve all references based on t | |||||||
| use crate::ast::ast_node::AstNode; | use crate::ast::ast_node::AstNode; | ||||||
| use crate::ast::node::CompilationUnit; | use crate::ast::node::CompilationUnit; | ||||||
| use crate::diagnostic::DmDiagnostic; | use crate::diagnostic::DmDiagnostic; | ||||||
| use crate::name_analysis::first_pass::np1_compilation_unit; | use crate::name_analysis::first_pass::nap1_compilation_unit; | ||||||
|  | use crate::name_analysis::second_pass::nap2_compilation_unit; | ||||||
| use crate::name_analysis::symbol_table::SymbolTable; | use crate::name_analysis::symbol_table::SymbolTable; | ||||||
| use codespan_reporting::files::Files; | use codespan_reporting::files::Files; | ||||||
| use std::hash::Hash; | use std::hash::Hash; | ||||||
| use crate::name_analysis::second_pass::nap2_compilation_unit; |  | ||||||
| 
 | 
 | ||||||
| pub(self) mod fqn_context; | pub(self) mod fqn_context; | ||||||
| mod gather; |  | ||||||
| // mod resolve;
 | // mod resolve;
 | ||||||
| mod first_pass; | mod first_pass; | ||||||
| mod scope_table; | mod scope_table; | ||||||
| @ -49,7 +48,7 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>( | |||||||
|     // gather symbols
 |     // gather symbols
 | ||||||
|     for compilation_unit in compilation_units.iter_mut() { |     for compilation_unit in compilation_units.iter_mut() { | ||||||
|         let file_name = files.name(compilation_unit.file_id()).unwrap(); |         let file_name = files.name(compilation_unit.file_id()).unwrap(); | ||||||
|         np1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics); |         nap1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // resolve symbols
 |     // resolve symbols
 | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| 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::use_symbol::UseSymbol; | ||||||
| use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; | use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable}; | ||||||
| use crate::name_analysis::util::use_statement_base_fqn; | use crate::name_analysis::util::use_statement_base_fqn; | ||||||
| use codespan_reporting::diagnostic::{Diagnostic, Label}; | use codespan_reporting::diagnostic::{Diagnostic, Label}; | ||||||
| @ -50,9 +51,18 @@ fn nap2_use_statement( | |||||||
| 
 | 
 | ||||||
|     let mut handle_concrete_use_symbol = |identifier: &Identifier| { |     let mut handle_concrete_use_symbol = |identifier: &Identifier| { | ||||||
|         let fqn = format!("{}::{}", base_fqn, identifier.name()); |         let fqn = format!("{}::{}", base_fqn, identifier.name()); | ||||||
|         if let Err(error) = symbol_table.resolve_usable_by_fqn(&fqn) { |         match symbol_table.resolve_concrete_usable_by_fqn(&fqn) { | ||||||
|  |             Ok(resolved_symbol) => match *use_statement.use_symbol().unwrap().borrow() { | ||||||
|  |                 UseSymbol::Concrete(ref concrete_use_symbol) => { | ||||||
|  |                     concrete_use_symbol | ||||||
|  |                         .borrow_mut() | ||||||
|  |                         .set_resolved_symbol(resolved_symbol); | ||||||
|  |                 } | ||||||
|  |                 _ => panic!("Unexpected symbol type"), | ||||||
|  |             }, | ||||||
|  |             Err(lookup_error) => { | ||||||
|                 handle_lookup_error( |                 handle_lookup_error( | ||||||
|                 error, |                     lookup_error, | ||||||
|                     &fqn, |                     &fqn, | ||||||
|                     use_statement.file_id(), |                     use_statement.file_id(), | ||||||
|                     use_statement.range(), |                     use_statement.range(), | ||||||
| @ -60,6 +70,7 @@ fn nap2_use_statement( | |||||||
|                     diagnostics, |                     diagnostics, | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     match use_statement.suffix() { |     match use_statement.suffix() { | ||||||
|  | |||||||
| @ -4,26 +4,30 @@ pub(crate) mod module_symbol; | |||||||
| pub(crate) mod parameter_symbol; | pub(crate) mod parameter_symbol; | ||||||
| pub(crate) mod source_definition; | pub(crate) mod source_definition; | ||||||
| pub(crate) mod type_symbol; | pub(crate) mod type_symbol; | ||||||
|  | pub(crate) mod usable_symbol; | ||||||
| pub(crate) mod use_symbol; | pub(crate) mod use_symbol; | ||||||
| pub(crate) mod variable_symbol; | pub(crate) mod variable_symbol; | ||||||
| 
 | 
 | ||||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol; | ||||||
|  | use crate::name_analysis::symbol::use_symbol::UseSymbol; | ||||||
| use class_member_symbol::ClassMemberSymbol; | use class_member_symbol::ClassMemberSymbol; | ||||||
| use function_symbol::FunctionSymbol; | use function_symbol::FunctionSymbol; | ||||||
| use module_symbol::ModuleSymbol; | use module_symbol::ModuleSymbol; | ||||||
| use parameter_symbol::ParameterSymbol; | use parameter_symbol::ParameterSymbol; | ||||||
| use source_definition::SourceDefinition; | use source_definition::SourceDefinition; | ||||||
|  | use std::cell::RefCell; | ||||||
| use std::fmt::{Debug, Display}; | use std::fmt::{Debug, Display}; | ||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
|  | use std::rc::Rc; | ||||||
| use type_symbol::TypeSymbol; | use type_symbol::TypeSymbol; | ||||||
| use variable_symbol::VariableSymbol; | use variable_symbol::VariableSymbol; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| pub enum Symbol { | pub enum Symbol { | ||||||
|     ConcreteUse(ConcreteUseSymbol), |     Use(UseSymbol), | ||||||
|     StarUse(StarUseSymbol), |  | ||||||
|     Module(ModuleSymbol), |     Module(ModuleSymbol), | ||||||
|     Type(TypeSymbol), |     Type(TypeSymbol), | ||||||
|  |     ConcreteType(Rc<RefCell<ConcreteTypeSymbol>>), | ||||||
|     Function(FunctionSymbol), |     Function(FunctionSymbol), | ||||||
|     Parameter(ParameterSymbol), |     Parameter(ParameterSymbol), | ||||||
|     Variable(VariableSymbol), |     Variable(VariableSymbol), | ||||||
| @ -31,16 +35,18 @@ pub enum Symbol { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Symbol { | impl Symbol { | ||||||
|     pub fn definition(&self) -> Option<&SourceDefinition> { |     pub fn definition(&self) -> Option<SourceDefinition> { | ||||||
|         match self { |         match self { | ||||||
|             Symbol::ConcreteUse(concrete) => concrete.source_definition(), |             Symbol::Use(use_symbol) => use_symbol.source_definition(), | ||||||
|             Symbol::StarUse(star) => star.source_definition(), |             Symbol::Module(module) => module.source_definition().cloned(), | ||||||
|             Symbol::Module(module) => module.source_definition(), |             Symbol::Type(type_symbol) => type_symbol.source_definition().cloned(), | ||||||
|             Symbol::Type(type_symbol) => type_symbol.source_definition(), |             Symbol::ConcreteType(concrete_type_symbol) => concrete_type_symbol.borrow().source_definition().cloned(), | ||||||
|             Symbol::Function(function_symbol) => function_symbol.source_definition(), |             Symbol::Function(function_symbol) => function_symbol.source_definition().cloned(), | ||||||
|             Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(), |             Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(), | ||||||
|             Symbol::Variable(variable_symbol) => variable_symbol.source_definition(), |             Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(), | ||||||
|             Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_definition(), |             Symbol::ClassMember(class_member_symbol) => { | ||||||
|  |                 class_member_symbol.source_definition().cloned() | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								src/name_analysis/symbol/usable_symbol.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/name_analysis/symbol/usable_symbol.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | use crate::name_analysis::symbol::function_symbol::FunctionSymbol; | ||||||
|  | use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol}; | ||||||
|  | use std::cell::RefCell; | ||||||
|  | use std::rc::Rc; | ||||||
|  | 
 | ||||||
|  | #[derive(Clone, Debug)] | ||||||
|  | pub enum ConcreteUsableSymbol { | ||||||
|  |     Type(Rc<RefCell<ConcreteTypeSymbol>>), | ||||||
|  |     Function(Rc<RefCell<FunctionSymbol>>), | ||||||
|  | } | ||||||
| @ -1,11 +1,30 @@ | |||||||
| 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 std::cell::RefCell; | ||||||
| use std::fmt::{Debug, Formatter}; | use std::fmt::{Debug, Formatter}; | ||||||
|  | use std::rc::Rc; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone)] | ||||||
|  | pub enum UseSymbol { | ||||||
|  |     Concrete(Rc<RefCell<ConcreteUseSymbol>>), | ||||||
|  |     Star(StarUseSymbol), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl UseSymbol { | ||||||
|  |     pub fn source_definition(&self) -> Option<SourceDefinition> { | ||||||
|  |         match self { | ||||||
|  |             UseSymbol::Concrete(concrete) => concrete.borrow().source_definition().cloned(), | ||||||
|  |             UseSymbol::Star(star) => star.source_definition().cloned(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct ConcreteUseSymbol { | 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>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ConcreteUseSymbol { | impl ConcreteUseSymbol { | ||||||
| @ -18,6 +37,7 @@ impl ConcreteUseSymbol { | |||||||
|             base_fqn: base_fqn.to_string(), |             base_fqn: base_fqn.to_string(), | ||||||
|             declared_name: declared_name.to_string(), |             declared_name: declared_name.to_string(), | ||||||
|             source_definition, |             source_definition, | ||||||
|  |             resolved_symbol: None, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -32,6 +52,14 @@ impl ConcreteUseSymbol { | |||||||
|     pub fn source_definition(&self) -> Option<&SourceDefinition> { |     pub fn source_definition(&self) -> Option<&SourceDefinition> { | ||||||
|         self.source_definition.as_ref() |         self.source_definition.as_ref() | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn resolved_symbol(&self) -> Option<&ConcreteUsableSymbol> { | ||||||
|  |         self.resolved_symbol.as_ref() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn set_resolved_symbol(&mut self, symbol: ConcreteUsableSymbol) { | ||||||
|  |         self.resolved_symbol = Some(symbol); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Debug for ConcreteUseSymbol { | impl Debug for ConcreteUseSymbol { | ||||||
|  | |||||||
| @ -2,15 +2,19 @@ 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::type_symbol::TypeSymbol; | use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol; | ||||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | 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::variable_symbol::VariableSymbol; | ||||||
| use crate::name_analysis::symbol::*; | use crate::name_analysis::symbol::*; | ||||||
| use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; | 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::collections::VecDeque; | ||||||
| use std::fmt::Display; | use std::fmt::Display; | ||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
|  | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| mod scope; | mod scope; | ||||||
| 
 | 
 | ||||||
| @ -44,13 +48,14 @@ impl SymbolTable { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn push_scope(&mut self, debug_name: &str) { |     pub fn push_scope(&mut self, debug_name: &str) { | ||||||
|         let id = self.scopes.len(); |         let id_to_push = self.scopes.len(); | ||||||
|         self.scopes.push(Scope::new( |         self.scopes.push(Scope::new( | ||||||
|             Some(self.current_scope_id), |             Some(self.current_scope_id), | ||||||
|             id, |             id_to_push, | ||||||
|             debug_name.to_string(), |             debug_name.to_string(), | ||||||
|         )); |         )); | ||||||
|         self.current_scope_id = id; |         self.current_scope_mut().add_child(id_to_push); | ||||||
|  |         self.current_scope_id = id_to_push; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn pop_scope(&mut self) { |     pub fn pop_scope(&mut self) { | ||||||
| @ -70,20 +75,17 @@ impl SymbolTable { | |||||||
|     fn find_current_scope_concrete_use_symbol( |     fn find_current_scope_concrete_use_symbol( | ||||||
|         &self, |         &self, | ||||||
|         declared_name: &str, |         declared_name: &str, | ||||||
|     ) -> Option<&ConcreteUseSymbol> { |     ) -> Option<Rc<RefCell<ConcreteUseSymbol>>> { | ||||||
|         self.current_scope() |         self.current_scope() | ||||||
|             .concrete_use_symbols() |             .concrete_use_symbols() | ||||||
|             .get(declared_name) |             .get(declared_name) | ||||||
|  |             .cloned() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> { |     fn find_current_scope_star_use_symbol(&self, base_fqn: &str) -> Option<&StarUseSymbol> { | ||||||
|         self.current_scope().star_use_symbols().get(base_fqn) |         self.current_scope().star_use_symbols().get(base_fqn) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn find_current_scope_type_symbol(&self, declared_name: &str) -> Option<&TypeSymbol> { |  | ||||||
|         self.current_scope().type_symbols().get(declared_name) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     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) | ||||||
|     } |     } | ||||||
| @ -119,11 +121,13 @@ impl SymbolTable { | |||||||
| 
 | 
 | ||||||
|     fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option<Symbol> { |     fn find_current_scope_usable_symbol(&self, declared_name: &str) -> Option<Symbol> { | ||||||
|         self.find_current_scope_concrete_use_symbol(declared_name) |         self.find_current_scope_concrete_use_symbol(declared_name) | ||||||
|             .map(|concrete_use_symbol| Symbol::ConcreteUse(concrete_use_symbol.clone())) |             .map(|concrete_use_symbol| { | ||||||
|             .or_else(|| { |                 Symbol::Use(UseSymbol::Concrete(concrete_use_symbol.clone())) | ||||||
|                 self.find_current_scope_type_symbol(declared_name) |  | ||||||
|                     .map(|type_symbol| Symbol::Type(type_symbol.clone())) |  | ||||||
|             }) |             }) | ||||||
|  |             // .or_else(|| {
 | ||||||
|  |             //     self.find_current_scope_type_symbol(declared_name)
 | ||||||
|  |             //         .map(|type_symbol| Symbol::Type(type_symbol.clone()))
 | ||||||
|  |             // })
 | ||||||
|             .or_else(|| { |             .or_else(|| { | ||||||
|                 self.find_current_scope_module_symbol(declared_name) |                 self.find_current_scope_module_symbol(declared_name) | ||||||
|                     .map(|module_symbol| Symbol::Module(module_symbol.clone())) |                     .map(|module_symbol| Symbol::Module(module_symbol.clone())) | ||||||
| @ -133,17 +137,22 @@ impl SymbolTable { | |||||||
|     pub fn insert_concrete_use_symbol( |     pub fn insert_concrete_use_symbol( | ||||||
|         &mut self, |         &mut self, | ||||||
|         concrete_use_symbol: ConcreteUseSymbol, |         concrete_use_symbol: ConcreteUseSymbol, | ||||||
|     ) -> Result<(), SymbolInsertError> { |     ) -> Result<Rc<RefCell<ConcreteUseSymbol>>, SymbolInsertError> { | ||||||
|         if let Some(defined_symbol) = |         if let Some(defined_symbol) = | ||||||
|             self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name()) |             self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(defined_symbol)) |             Err(SymbolAlreadyDefined(defined_symbol)) | ||||||
|         } else { |         } else { | ||||||
|             self.current_scope_mut().concrete_use_symbols_mut().insert( |             let name = concrete_use_symbol.declared_name().to_string(); | ||||||
|                 concrete_use_symbol.declared_name().to_string(), |             self.current_scope_mut() | ||||||
|                 concrete_use_symbol, |                 .concrete_use_symbols_mut() | ||||||
|             ); |                 .insert(name.clone(), Rc::new(RefCell::new(concrete_use_symbol))); | ||||||
|             Ok(()) |             Ok(self | ||||||
|  |                 .current_scope() | ||||||
|  |                 .concrete_use_symbols() | ||||||
|  |                 .get(&name) | ||||||
|  |                 .cloned() | ||||||
|  |                 .unwrap()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -154,9 +163,9 @@ impl SymbolTable { | |||||||
|         if let Some(defined_symbol) = |         if let Some(defined_symbol) = | ||||||
|             self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn()) |             self.find_current_scope_star_use_symbol(star_use_symbol.base_fqn()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(Symbol::StarUse( |             Err(SymbolAlreadyDefined(Symbol::Use(UseSymbol::Star( | ||||||
|                 defined_symbol.clone(), |                 defined_symbol.clone(), | ||||||
|             ))) |             )))) | ||||||
|         } else { |         } else { | ||||||
|             self.current_scope_mut() |             self.current_scope_mut() | ||||||
|                 .star_use_symbols_mut() |                 .star_use_symbols_mut() | ||||||
| @ -181,15 +190,23 @@ impl SymbolTable { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> { |     fn find_current_scope_concrete_type_symbol( | ||||||
|         if let Some(defined_symbol) = |         &self, | ||||||
|             self.find_current_scope_usable_symbol(type_symbol.declared_name()) |         declared_name: &str, | ||||||
|  |     ) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> { | ||||||
|  |         self.current_scope().get_concrete_type_symbol(declared_name) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn insert_concrete_type_symbol( | ||||||
|  |         &mut self, | ||||||
|  |         symbol: ConcreteTypeSymbol, | ||||||
|  |     ) -> Result<(), SymbolInsertError> { | ||||||
|  |         if let Some(defined_type) = | ||||||
|  |             self.find_current_scope_concrete_type_symbol(symbol.declared_name()) | ||||||
|         { |         { | ||||||
|             Err(SymbolAlreadyDefined(defined_symbol)) |             Err(SymbolAlreadyDefined(Symbol::ConcreteType(defined_type))) | ||||||
|         } else { |         } else { | ||||||
|             self.current_scope_mut() |             self.current_scope_mut().insert_concrete_type_symbol(symbol); | ||||||
|                 .type_symbols_mut() |  | ||||||
|                 .insert(type_symbol.declared_name().to_string(), type_symbol); |  | ||||||
|             Ok(()) |             Ok(()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -264,66 +281,6 @@ impl SymbolTable { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn lookup_type_in_scope_by_declared_name<'a>( |  | ||||||
|         scope: &'a Scope, |  | ||||||
|         declared_name: &str, |  | ||||||
|     ) -> Option<&'a TypeSymbol> { |  | ||||||
|         scope.type_symbols().get(declared_name) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn lookup_type_by_declared_name( |  | ||||||
|         &self, |  | ||||||
|         declared_name: &str, |  | ||||||
|         scope_id: usize, |  | ||||||
|     ) -> Result<&TypeSymbol, SymbolLookupError> { |  | ||||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); |  | ||||||
|         while let Some(scope) = scope_opt { |  | ||||||
|             if let Some(symbol) = Self::lookup_type_in_scope_by_declared_name(scope, declared_name) |  | ||||||
|             { |  | ||||||
|                 return Ok(symbol); |  | ||||||
|             } |  | ||||||
|             scope_opt = if let Some(parent_id) = scope.parent() { |  | ||||||
|                 Some(&self.scopes[parent_id]) |  | ||||||
|             } else { |  | ||||||
|                 None |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         Err(NoDefinition) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lookup_type_in_scope_by_fqn<'a>(scope: &'a Scope, fqn: &str) -> Option<&'a TypeSymbol> { |  | ||||||
|         for type_symbol in scope.type_symbols().values() { |  | ||||||
|             match type_symbol { |  | ||||||
|                 TypeSymbol::Concrete(concrete_type_symbol) => { |  | ||||||
|                     if concrete_type_symbol.fqn() == fqn { |  | ||||||
|                         return Some(type_symbol); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 TypeSymbol::Generic(_) => {} |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         None |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn lookup_type_by_fqn( |  | ||||||
|         &self, |  | ||||||
|         fqn: &str, |  | ||||||
|         scope_id: usize, |  | ||||||
|     ) -> Result<&TypeSymbol, SymbolLookupError> { |  | ||||||
|         let mut scope_opt = Some(&self.scopes[scope_id]); |  | ||||||
|         while let Some(scope) = scope_opt { |  | ||||||
|             if let Some(type_symbol) = Self::lookup_type_in_scope_by_fqn(scope, fqn) { |  | ||||||
|                 return Ok(type_symbol); |  | ||||||
|             } |  | ||||||
|             scope_opt = if let Some(parent_id) = scope.parent() { |  | ||||||
|                 Some(&self.scopes[parent_id]) |  | ||||||
|             } else { |  | ||||||
|                 None |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|         Err(NoDefinition) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn lookup_addressable_in_scope_by_identifier( |     fn lookup_addressable_in_scope_by_identifier( | ||||||
|         scope: &Scope, |         scope: &Scope, | ||||||
|         identifier: &str, |         identifier: &str, | ||||||
| @ -350,12 +307,12 @@ impl SymbolTable { | |||||||
|                     .get(identifier) |                     .get(identifier) | ||||||
|                     .map(|function_symbol| Symbol::Function(function_symbol.clone())) |                     .map(|function_symbol| Symbol::Function(function_symbol.clone())) | ||||||
|             }) |             }) | ||||||
|             .or_else(|| { |         // .or_else(|| {
 | ||||||
|                 scope |         //     scope
 | ||||||
|                     .type_symbols() |         //         .type_symbols()
 | ||||||
|                     .get(identifier) |         //         .get(identifier)
 | ||||||
|                     .map(|type_symbol| Symbol::Type(type_symbol.clone())) |         //         .map(|type_symbol| Symbol::Type(type_symbol.clone()))
 | ||||||
|             }) |         // })
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn lookup_addressable_by_identifier( |     pub fn lookup_addressable_by_identifier( | ||||||
| @ -378,17 +335,36 @@ impl SymbolTable { | |||||||
|         Err(NoDefinition) |         Err(NoDefinition) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn resolve_usable_by_fqn( |     pub fn resolve_concrete_usable_by_fqn( | ||||||
|         &self, |         &self, | ||||||
|         fqn: &str |         fqn: &str, | ||||||
|     ) -> Result<Symbol, SymbolLookupError> { |     ) -> Result<ConcreteUsableSymbol, SymbolLookupError> { | ||||||
|         todo!() |         // breadth-first search, use a queue
 | ||||||
|  |         let mut search_stack: VecDeque<usize> = VecDeque::new(); | ||||||
|  |         search_stack.push_back(0); // global scope
 | ||||||
|  | 
 | ||||||
|  |         while let Some(scope_id) = search_stack.pop_front() { | ||||||
|  |             let scope = &self.scopes[scope_id]; | ||||||
|  |             for child_id in scope.children() { | ||||||
|  |                 search_stack.push_back(child_id); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|     pub fn resolve_usable_star( |             if let Some(concrete_type_symbol) = scope.get_concrete_type_symbol_by_fqn(fqn) { | ||||||
|         &self, |                 return Ok(ConcreteUsableSymbol::Type(concrete_type_symbol)); | ||||||
|         base_fqn: &str, |             } | ||||||
|     ) -> Result<(), SymbolLookupError> { | 
 | ||||||
|  |             // TODO: this is inefficient. Use a (cached) hash table of Fqn => Rc<RefCell<symbol>>
 | ||||||
|  |             for function_symbol in scope.function_symbols().values() { | ||||||
|  |                 if function_symbol.fqn() == fqn { | ||||||
|  |                     return Ok(ConcreteUsableSymbol::Function(todo!())); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Err(NoDefinition) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn resolve_usable_star(&self, base_fqn: &str) -> Result<(), SymbolLookupError> { | ||||||
|         todo!() |         todo!() | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,20 +2,24 @@ 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::type_symbol::TypeSymbol; | use crate::name_analysis::symbol::type_symbol::{ConcreteTypeSymbol, TypeSymbol}; | ||||||
| use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; | ||||||
| use crate::name_analysis::symbol::variable_symbol::VariableSymbol; | use crate::name_analysis::symbol::variable_symbol::VariableSymbol; | ||||||
|  | use std::cell::RefCell; | ||||||
| use std::collections::HashMap; | use std::collections::HashMap; | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
|  | use std::rc::Rc; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub struct Scope { | pub struct Scope { | ||||||
|     parent: Option<usize>, |     parent: Option<usize>, | ||||||
|     id: usize, |     id: usize, | ||||||
|     concrete_use_symbols: HashMap<String, ConcreteUseSymbol>, |     children: Vec<usize>, | ||||||
|  |     concrete_use_symbols: HashMap<String, Rc<RefCell<ConcreteUseSymbol>>>, | ||||||
|     star_use_symbols: HashMap<String, StarUseSymbol>, |     star_use_symbols: HashMap<String, StarUseSymbol>, | ||||||
|     module_symbols: HashMap<String, ModuleSymbol>, |     module_symbols: HashMap<String, ModuleSymbol>, | ||||||
|     type_symbols: HashMap<String, TypeSymbol>, |     concrete_type_symbols: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>, | ||||||
|  |     concrete_type_symbols_by_fqn: HashMap<String, Rc<RefCell<ConcreteTypeSymbol>>>, | ||||||
|     function_symbols: HashMap<String, FunctionSymbol>, |     function_symbols: HashMap<String, FunctionSymbol>, | ||||||
|     parameter_symbols: HashMap<String, ParameterSymbol>, |     parameter_symbols: HashMap<String, ParameterSymbol>, | ||||||
|     variable_symbols: HashMap<String, VariableSymbol>, |     variable_symbols: HashMap<String, VariableSymbol>, | ||||||
| @ -28,10 +32,12 @@ impl Scope { | |||||||
|         Self { |         Self { | ||||||
|             parent, |             parent, | ||||||
|             id, |             id, | ||||||
|  |             children: vec![], | ||||||
|             concrete_use_symbols: HashMap::new(), |             concrete_use_symbols: HashMap::new(), | ||||||
|             star_use_symbols: HashMap::new(), |             star_use_symbols: HashMap::new(), | ||||||
|             module_symbols: HashMap::new(), |             module_symbols: HashMap::new(), | ||||||
|             type_symbols: HashMap::new(), |             concrete_type_symbols: HashMap::new(), | ||||||
|  |             concrete_type_symbols_by_fqn: HashMap::new(), | ||||||
|             function_symbols: HashMap::new(), |             function_symbols: HashMap::new(), | ||||||
|             parameter_symbols: HashMap::new(), |             parameter_symbols: HashMap::new(), | ||||||
|             variable_symbols: HashMap::new(), |             variable_symbols: HashMap::new(), | ||||||
| @ -48,11 +54,21 @@ impl Scope { | |||||||
|         self.id |         self.id | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn concrete_use_symbols(&self) -> &HashMap<String, ConcreteUseSymbol> { |     pub fn add_child(&mut self, child_id: usize) { | ||||||
|  |         self.children.push(child_id); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn children(&self) -> Vec<usize> { | ||||||
|  |         self.children.clone() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn concrete_use_symbols(&self) -> &HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> { | ||||||
|         &self.concrete_use_symbols |         &self.concrete_use_symbols | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn concrete_use_symbols_mut(&mut self) -> &mut HashMap<String, ConcreteUseSymbol> { |     pub fn concrete_use_symbols_mut( | ||||||
|  |         &mut self, | ||||||
|  |     ) -> &mut HashMap<String, Rc<RefCell<ConcreteUseSymbol>>> { | ||||||
|         &mut self.concrete_use_symbols |         &mut self.concrete_use_symbols | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -72,12 +88,24 @@ impl Scope { | |||||||
|         &mut self.module_symbols |         &mut self.module_symbols | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn type_symbols(&self) -> &HashMap<String, TypeSymbol> { |     pub fn insert_concrete_type_symbol(&mut self, symbol: ConcreteTypeSymbol) { | ||||||
|         &self.type_symbols |         let as_rc = Rc::new(RefCell::new(symbol)); | ||||||
|  |         self.concrete_type_symbols.insert( | ||||||
|  |             as_rc.borrow().declared_name().to_string(), | ||||||
|  |             as_rc.clone(), | ||||||
|  |         ); | ||||||
|  |         self.concrete_type_symbols_by_fqn.insert( | ||||||
|  |             as_rc.borrow().fqn().to_string(), | ||||||
|  |             as_rc.clone(), | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
|     
 |     
 | ||||||
|     pub fn type_symbols_mut(&mut self) -> &mut HashMap<String, TypeSymbol> { |     pub fn get_concrete_type_symbol(&self, declared_name: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> { | ||||||
|         &mut self.type_symbols |         self.concrete_type_symbols.get(declared_name).cloned() | ||||||
|  |     } | ||||||
|  |     
 | ||||||
|  |     pub fn get_concrete_type_symbol_by_fqn(&self, fqn: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> { | ||||||
|  |         self.concrete_type_symbols_by_fqn.get(fqn).cloned() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> { |     pub fn function_symbols(&self) -> &HashMap<String, FunctionSymbol> { | ||||||
| @ -131,13 +159,15 @@ impl Display for Scope { | |||||||
|             f, |             f, | ||||||
|             "----Scope {} (p: {}) {}----", |             "----Scope {} (p: {}) {}----", | ||||||
|             self.id(), |             self.id(), | ||||||
|             self.parent().map(|parent_id| format!("{}", parent_id)).unwrap_or_else(|| "None".to_string()), |             self.parent() | ||||||
|  |                 .map(|parent_id| format!("{}", parent_id)) | ||||||
|  |                 .unwrap_or_else(|| "None".to_string()), | ||||||
|             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()); |         write_symbols!(f, self.star_use_symbols()); | ||||||
|         write_symbols!(f, self.module_symbols()); |         write_symbols!(f, self.module_symbols()); | ||||||
|         write_symbols!(f, self.type_symbols()); |         todo!("self.concrete_type_symbols"); | ||||||
|         write_symbols!(f, self.function_symbols()); |         write_symbols!(f, self.function_symbols()); | ||||||
|         write_symbols!(f, self.parameter_symbols()); |         write_symbols!(f, self.parameter_symbols()); | ||||||
|         write_symbols!(f, self.variable_symbols()); |         write_symbols!(f, self.variable_symbols()); | ||||||
|  | |||||||
| @ -248,6 +248,10 @@ UseStatement: | |||||||
|       - range: |       - range: | ||||||
|           special: |           special: | ||||||
|             kind: range |             kind: range | ||||||
|  |     fields: | ||||||
|  |       - use_symbol: | ||||||
|  |           kind: UseSymbol | ||||||
|  |           wrap: rc_ref_cell | ||||||
| UseStatementPrefix: | UseStatementPrefix: | ||||||
|   struct: |   struct: | ||||||
|     children: |     children: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jesse Brault
						Jesse Brault