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 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 {
|
||||
let rule = props["rule"].as_str().unwrap();
|
||||
StructChild::SkipChild(SkipChild::new(rule))
|
||||
@ -151,6 +167,18 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
} else {
|
||||
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() {
|
||||
struct_yaml["derive"].as_vec()
|
||||
.unwrap()
|
||||
@ -161,5 +189,5 @@ pub fn deserialize_struct_spec(name: &str, struct_yaml: &Yaml) -> StructSpec {
|
||||
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<_>>();
|
||||
let combined = quote! {
|
||||
use std::range::Range;
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
|
||||
#(#types)*
|
||||
};
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
pub struct StructSpec {
|
||||
build: String,
|
||||
children: Vec<Box<StructChild>>,
|
||||
fields: Vec<Box<StructField>>,
|
||||
derive: Vec<String>,
|
||||
}
|
||||
|
||||
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 {
|
||||
build: build.to_string(),
|
||||
children,
|
||||
fields,
|
||||
derive,
|
||||
}
|
||||
}
|
||||
@ -23,6 +25,10 @@ impl StructSpec {
|
||||
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] {
|
||||
&self.derive
|
||||
}
|
||||
@ -266,3 +272,37 @@ pub enum SpecialChildKind {
|
||||
FileId,
|
||||
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::{
|
||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
||||
VecChild, VecChildBuild,
|
||||
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructField,
|
||||
StructFieldWrap, StructSpec, VecChild, VecChildBuild,
|
||||
};
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
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 {
|
||||
let child_ident = format_ident!("{}", vec_child.name());
|
||||
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 {
|
||||
let type_ident = format_ident!("{}", build_spec.build());
|
||||
let annotated_members = build_spec
|
||||
let annotated_children_members = build_spec
|
||||
.children()
|
||||
.map(|child| make_annotated_member(child))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let annotated_fields = build_spec
|
||||
.fields()
|
||||
.map(|field| make_annotated_field(field))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let member_names = build_spec
|
||||
.children()
|
||||
.map(|child| make_member_ident(child))
|
||||
@ -198,17 +259,28 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||
.map(Option::unwrap)
|
||||
.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()
|
||||
.map(|child| make_accessors(child))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let field_accessors = build_spec
|
||||
.fields()
|
||||
.map(|field| make_field_accessors(field))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let struct_stream = {
|
||||
let base = quote! {
|
||||
pub struct #type_ident {
|
||||
#(#annotated_members),*
|
||||
#(#annotated_children_members,)*
|
||||
#(#annotated_fields,)*
|
||||
}
|
||||
};
|
||||
if !build_spec.derive().is_empty() {
|
||||
@ -231,13 +303,15 @@ pub fn make_struct_type(build_spec: &StructSpec) -> TokenStream {
|
||||
#struct_stream
|
||||
|
||||
impl #type_ident {
|
||||
pub fn new(#(#annotated_members),*) -> Self {
|
||||
pub fn new(#(#annotated_children_members),*) -> 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::name_analysis::fqn_context::FqnContext;
|
||||
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::util::use_statement_base_fqn;
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use std::range::Range;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn handle_insert_error(
|
||||
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,
|
||||
compilation_unit: &mut CompilationUnit,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -85,13 +87,42 @@ pub fn np1_compilation_unit(
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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,
|
||||
symbol_table: &mut SymbolTable,
|
||||
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::node::CompilationUnit;
|
||||
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 codespan_reporting::files::Files;
|
||||
use std::hash::Hash;
|
||||
use crate::name_analysis::second_pass::nap2_compilation_unit;
|
||||
|
||||
pub(self) mod fqn_context;
|
||||
mod gather;
|
||||
// mod resolve;
|
||||
mod first_pass;
|
||||
mod scope_table;
|
||||
@ -49,7 +48,7 @@ pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
|
||||
// gather symbols
|
||||
for compilation_unit in compilation_units.iter_mut() {
|
||||
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
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::ast::node::{CompilationUnit, Identifier, UseStatement, UseStatementSuffix};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol::use_symbol::UseSymbol;
|
||||
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||
use crate::name_analysis::util::use_statement_base_fqn;
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
@ -47,18 +48,28 @@ fn nap2_use_statement(
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let base_fqn = use_statement_base_fqn(use_statement);
|
||||
|
||||
|
||||
let mut handle_concrete_use_symbol = |identifier: &Identifier| {
|
||||
let fqn = format!("{}::{}", base_fqn, identifier.name());
|
||||
if let Err(error) = symbol_table.resolve_usable_by_fqn(&fqn) {
|
||||
handle_lookup_error(
|
||||
error,
|
||||
&fqn,
|
||||
use_statement.file_id(),
|
||||
use_statement.range(),
|
||||
"Usable Symbol",
|
||||
diagnostics,
|
||||
);
|
||||
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(
|
||||
lookup_error,
|
||||
&fqn,
|
||||
use_statement.file_id(),
|
||||
use_statement.range(),
|
||||
"Usable Symbol",
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -4,26 +4,30 @@ pub(crate) mod module_symbol;
|
||||
pub(crate) mod parameter_symbol;
|
||||
pub(crate) mod source_definition;
|
||||
pub(crate) mod type_symbol;
|
||||
pub(crate) mod usable_symbol;
|
||||
pub(crate) mod use_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 function_symbol::FunctionSymbol;
|
||||
use module_symbol::ModuleSymbol;
|
||||
use parameter_symbol::ParameterSymbol;
|
||||
use source_definition::SourceDefinition;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use type_symbol::TypeSymbol;
|
||||
use variable_symbol::VariableSymbol;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Symbol {
|
||||
ConcreteUse(ConcreteUseSymbol),
|
||||
StarUse(StarUseSymbol),
|
||||
Use(UseSymbol),
|
||||
Module(ModuleSymbol),
|
||||
Type(TypeSymbol),
|
||||
ConcreteType(Rc<RefCell<ConcreteTypeSymbol>>),
|
||||
Function(FunctionSymbol),
|
||||
Parameter(ParameterSymbol),
|
||||
Variable(VariableSymbol),
|
||||
@ -31,16 +35,18 @@ pub enum Symbol {
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
pub fn definition(&self) -> Option<&SourceDefinition> {
|
||||
pub fn definition(&self) -> Option<SourceDefinition> {
|
||||
match self {
|
||||
Symbol::ConcreteUse(concrete) => concrete.source_definition(),
|
||||
Symbol::StarUse(star) => star.source_definition(),
|
||||
Symbol::Module(module) => module.source_definition(),
|
||||
Symbol::Type(type_symbol) => type_symbol.source_definition(),
|
||||
Symbol::Function(function_symbol) => function_symbol.source_definition(),
|
||||
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition(),
|
||||
Symbol::Variable(variable_symbol) => variable_symbol.source_definition(),
|
||||
Symbol::ClassMember(class_member_symbol) => class_member_symbol.source_definition(),
|
||||
Symbol::Use(use_symbol) => use_symbol.source_definition(),
|
||||
Symbol::Module(module) => module.source_definition().cloned(),
|
||||
Symbol::Type(type_symbol) => type_symbol.source_definition().cloned(),
|
||||
Symbol::ConcreteType(concrete_type_symbol) => concrete_type_symbol.borrow().source_definition().cloned(),
|
||||
Symbol::Function(function_symbol) => function_symbol.source_definition().cloned(),
|
||||
Symbol::Parameter(parameter_symbol) => parameter_symbol.source_definition().cloned(),
|
||||
Symbol::Variable(variable_symbol) => variable_symbol.source_definition().cloned(),
|
||||
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::usable_symbol::ConcreteUsableSymbol;
|
||||
use std::cell::RefCell;
|
||||
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)]
|
||||
pub struct ConcreteUseSymbol {
|
||||
base_fqn: String,
|
||||
declared_name: String,
|
||||
source_definition: Option<SourceDefinition>,
|
||||
resolved_symbol: Option<ConcreteUsableSymbol>,
|
||||
}
|
||||
|
||||
impl ConcreteUseSymbol {
|
||||
@ -18,6 +37,7 @@ impl ConcreteUseSymbol {
|
||||
base_fqn: base_fqn.to_string(),
|
||||
declared_name: declared_name.to_string(),
|
||||
source_definition,
|
||||
resolved_symbol: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +52,14 @@ impl ConcreteUseSymbol {
|
||||
pub fn source_definition(&self) -> Option<&SourceDefinition> {
|
||||
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 {
|
||||
|
||||
@ -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::module_symbol::ModuleSymbol;
|
||||
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||
use crate::name_analysis::symbol::type_symbol::ConcreteTypeSymbol;
|
||||
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::*;
|
||||
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;
|
||||
|
||||
mod scope;
|
||||
|
||||
@ -44,13 +48,14 @@ impl SymbolTable {
|
||||
}
|
||||
|
||||
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(
|
||||
Some(self.current_scope_id),
|
||||
id,
|
||||
id_to_push,
|
||||
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) {
|
||||
@ -70,20 +75,17 @@ impl SymbolTable {
|
||||
fn find_current_scope_concrete_use_symbol(
|
||||
&self,
|
||||
declared_name: &str,
|
||||
) -> Option<&ConcreteUseSymbol> {
|
||||
) -> Option<Rc<RefCell<ConcreteUseSymbol>>> {
|
||||
self.current_scope()
|
||||
.concrete_use_symbols()
|
||||
.get(declared_name)
|
||||
.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_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> {
|
||||
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> {
|
||||
self.find_current_scope_concrete_use_symbol(declared_name)
|
||||
.map(|concrete_use_symbol| Symbol::ConcreteUse(concrete_use_symbol.clone()))
|
||||
.or_else(|| {
|
||||
self.find_current_scope_type_symbol(declared_name)
|
||||
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
.map(|concrete_use_symbol| {
|
||||
Symbol::Use(UseSymbol::Concrete(concrete_use_symbol.clone()))
|
||||
})
|
||||
// .or_else(|| {
|
||||
// self.find_current_scope_type_symbol(declared_name)
|
||||
// .map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
// })
|
||||
.or_else(|| {
|
||||
self.find_current_scope_module_symbol(declared_name)
|
||||
.map(|module_symbol| Symbol::Module(module_symbol.clone()))
|
||||
@ -133,17 +137,22 @@ impl SymbolTable {
|
||||
pub fn insert_concrete_use_symbol(
|
||||
&mut self,
|
||||
concrete_use_symbol: ConcreteUseSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
) -> Result<Rc<RefCell<ConcreteUseSymbol>>, SymbolInsertError> {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_usable_symbol(concrete_use_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
self.current_scope_mut().concrete_use_symbols_mut().insert(
|
||||
concrete_use_symbol.declared_name().to_string(),
|
||||
concrete_use_symbol,
|
||||
);
|
||||
Ok(())
|
||||
let name = concrete_use_symbol.declared_name().to_string();
|
||||
self.current_scope_mut()
|
||||
.concrete_use_symbols_mut()
|
||||
.insert(name.clone(), Rc::new(RefCell::new(concrete_use_symbol)));
|
||||
Ok(self
|
||||
.current_scope()
|
||||
.concrete_use_symbols()
|
||||
.get(&name)
|
||||
.cloned()
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,9 +163,9 @@ impl SymbolTable {
|
||||
if let Some(defined_symbol) =
|
||||
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(),
|
||||
)))
|
||||
))))
|
||||
} else {
|
||||
self.current_scope_mut()
|
||||
.star_use_symbols_mut()
|
||||
@ -181,15 +190,23 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) =
|
||||
self.find_current_scope_usable_symbol(type_symbol.declared_name())
|
||||
fn find_current_scope_concrete_type_symbol(
|
||||
&self,
|
||||
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 {
|
||||
self.current_scope_mut()
|
||||
.type_symbols_mut()
|
||||
.insert(type_symbol.declared_name().to_string(), type_symbol);
|
||||
self.current_scope_mut().insert_concrete_type_symbol(symbol);
|
||||
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(
|
||||
scope: &Scope,
|
||||
identifier: &str,
|
||||
@ -350,12 +307,12 @@ impl SymbolTable {
|
||||
.get(identifier)
|
||||
.map(|function_symbol| Symbol::Function(function_symbol.clone()))
|
||||
})
|
||||
.or_else(|| {
|
||||
scope
|
||||
.type_symbols()
|
||||
.get(identifier)
|
||||
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
})
|
||||
// .or_else(|| {
|
||||
// scope
|
||||
// .type_symbols()
|
||||
// .get(identifier)
|
||||
// .map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||
// })
|
||||
}
|
||||
|
||||
pub fn lookup_addressable_by_identifier(
|
||||
@ -378,17 +335,36 @@ impl SymbolTable {
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
pub fn resolve_usable_by_fqn(
|
||||
pub fn resolve_concrete_usable_by_fqn(
|
||||
&self,
|
||||
fqn: &str
|
||||
) -> Result<Symbol, SymbolLookupError> {
|
||||
todo!()
|
||||
fqn: &str,
|
||||
) -> Result<ConcreteUsableSymbol, SymbolLookupError> {
|
||||
// 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);
|
||||
}
|
||||
|
||||
if let Some(concrete_type_symbol) = scope.get_concrete_type_symbol_by_fqn(fqn) {
|
||||
return Ok(ConcreteUsableSymbol::Type(concrete_type_symbol));
|
||||
}
|
||||
|
||||
// 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> {
|
||||
pub fn resolve_usable_star(&self, base_fqn: &str) -> Result<(), SymbolLookupError> {
|
||||
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::module_symbol::ModuleSymbol;
|
||||
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::variable_symbol::VariableSymbol;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scope {
|
||||
parent: Option<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>,
|
||||
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>,
|
||||
parameter_symbols: HashMap<String, ParameterSymbol>,
|
||||
variable_symbols: HashMap<String, VariableSymbol>,
|
||||
@ -28,10 +32,12 @@ impl Scope {
|
||||
Self {
|
||||
parent,
|
||||
id,
|
||||
children: vec![],
|
||||
concrete_use_symbols: HashMap::new(),
|
||||
star_use_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(),
|
||||
parameter_symbols: HashMap::new(),
|
||||
variable_symbols: HashMap::new(),
|
||||
@ -48,11 +54,21 @@ impl Scope {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -72,12 +88,24 @@ impl Scope {
|
||||
&mut self.module_symbols
|
||||
}
|
||||
|
||||
pub fn type_symbols(&self) -> &HashMap<String, TypeSymbol> {
|
||||
&self.type_symbols
|
||||
pub fn insert_concrete_type_symbol(&mut self, symbol: ConcreteTypeSymbol) {
|
||||
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> {
|
||||
&mut self.type_symbols
|
||||
|
||||
pub fn get_concrete_type_symbol(&self, declared_name: &str) -> Option<Rc<RefCell<ConcreteTypeSymbol>>> {
|
||||
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> {
|
||||
@ -131,13 +159,15 @@ impl Display for Scope {
|
||||
f,
|
||||
"----Scope {} (p: {}) {}----",
|
||||
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()
|
||||
)?;
|
||||
write_symbols!(f, self.concrete_use_symbols());
|
||||
write_symbols!(f, self.star_use_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.parameter_symbols());
|
||||
write_symbols!(f, self.variable_symbols());
|
||||
|
||||
@ -248,6 +248,10 @@ UseStatement:
|
||||
- range:
|
||||
special:
|
||||
kind: range
|
||||
fields:
|
||||
- use_symbol:
|
||||
kind: UseSymbol
|
||||
wrap: rc_ref_cell
|
||||
UseStatementPrefix:
|
||||
struct:
|
||||
children:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user