use crate::scope::Scope; use crate::scope::block_scope::BlockScope; use crate::scope::class_body_scope::ClassBodyScope; use crate::scope::class_scope::ClassScope; use crate::scope::function_scope::FunctionScope; use crate::scope::module_scope::ModuleScope; use crate::symbol::Symbol; use crate::symbol::class_symbol::ClassSymbol; use crate::symbol::expressible_symbol::ExpressibleSymbol; use crate::symbol::field_symbol::FieldSymbol; use crate::symbol::function_symbol::FunctionSymbol; use crate::symbol::generic_parameter_symbol::GenericParameterSymbol; use crate::symbol::parameter_symbol::ParameterSymbol; use crate::symbol::type_symbol::TypeSymbol; use crate::symbol::variable_symbol::VariableSymbol; use std::collections::HashMap; use std::rc::Rc; fn find_class_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::Class(symbol.clone())) } fn find_generic_parameter_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::GenericParameter(symbol.clone())) } fn find_field_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::Field(symbol.clone())) } fn find_function_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::Function(symbol.clone())) } fn find_parameter_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::Parameter(symbol.clone())) } fn find_variable_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| Symbol::Variable(symbol.clone())) } /* Expressible symbol refs */ fn find_class_expressible_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| ExpressibleSymbol::Class(symbol.clone())) } fn find_field_expressible_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| ExpressibleSymbol::Field(symbol.clone())) } fn find_function_expressible_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| ExpressibleSymbol::Function(symbol.clone())) } fn find_parameter_expressible_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| ExpressibleSymbol::Parameter(symbol.clone())) } fn find_variable_expressible_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| ExpressibleSymbol::Variable(symbol.clone())) } /* Find type symbols */ fn find_class_type_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| TypeSymbol::Class(symbol.clone())) } fn find_generic_parameter_type_symbol_ref( symbols: &HashMap, Rc>, name: &str, ) -> Option { symbols .get(name) .map(|symbol| TypeSymbol::GenericParameter(symbol.clone())) } /* Public helper functions */ /* Various find in functions */ pub fn find_in_module_by_name(module_scope: &ModuleScope, name: &str) -> Option { find_function_symbol_ref(&module_scope.function_symbols(), name) .or_else(|| find_class_symbol_ref(&module_scope.class_symbols(), name)) } pub fn find_in_class_by_name(class_scope: &ClassScope, name: &str) -> Option { find_generic_parameter_symbol_ref(&class_scope.generic_parameter_symbols(), name) } pub fn find_in_class_body_by_name(class_body_scope: &ClassBodyScope, name: &str) -> Option { find_class_symbol_ref(&class_body_scope.class_symbols(), name) .or_else(|| find_function_symbol_ref(&class_body_scope.function_symbols(), name)) .or_else(|| find_field_symbol_ref(&class_body_scope.field_symbols(), name)) } pub fn find_in_function_by_name(function_scope: &FunctionScope, name: &str) -> Option { find_parameter_symbol_ref(&function_scope.parameter_symbols(), name) } pub fn find_in_block_by_name(block_scope: &BlockScope, name: &str) -> Option { find_variable_symbol_ref(&block_scope.variable_symbols(), name) } /* Find expressible */ fn find_expressible_in_module_by_name( module_scope: &ModuleScope, name: &str, ) -> Option { find_class_expressible_symbol_ref(&module_scope.class_symbols(), name) .or_else(|| find_function_expressible_symbol_ref(&module_scope.function_symbols(), name)) } fn find_expressible_in_class_body_by_name( class_body_scope: &ClassBodyScope, name: &str, ) -> Option { find_class_expressible_symbol_ref(&class_body_scope.class_symbols(), name) .or_else(|| { find_function_expressible_symbol_ref(&class_body_scope.function_symbols(), name) }) .or_else(|| find_field_expressible_symbol_ref(&class_body_scope.field_symbols(), name)) } fn find_expressible_in_function_by_name( function_scope: &FunctionScope, name: &str, ) -> Option { find_parameter_expressible_symbol_ref(function_scope.parameter_symbols(), name) } fn find_expressible_in_block_by_name( block_scope: &BlockScope, name: &str, ) -> Option { find_variable_expressible_symbol_ref(block_scope.variable_symbols(), name) } pub fn find_expressible_symbol(scope: &Scope, name: &str) -> Option { match scope { Scope::Module(module_scope) => find_expressible_in_module_by_name(module_scope, name), Scope::Class(_) => None, Scope::ClassBody(class_body_scope) => { find_expressible_in_class_body_by_name(class_body_scope, name) } Scope::Function(function_scope) => { find_expressible_in_function_by_name(function_scope, name) } Scope::Block(block_scope) => find_expressible_in_block_by_name(block_scope, name), } } /* Find type */ fn find_type_symbol_in_module(module_scope: &ModuleScope, name: &str) -> Option { find_class_type_symbol_ref(&module_scope.class_symbols(), name) } fn find_type_symbol_in_class_body( class_body_scope: &ClassBodyScope, name: &str, ) -> Option { find_class_type_symbol_ref(&class_body_scope.class_symbols(), name) } fn find_type_symbol_in_class(class_scope: &ClassScope, name: &str) -> Option { find_generic_parameter_type_symbol_ref(&class_scope.generic_parameter_symbols(), name) } pub fn find_type_symbol(scope: &Scope, name: &str) -> Option { match scope { Scope::Module(module_scope) => find_type_symbol_in_module(module_scope, name), Scope::Class(class_scope) => find_type_symbol_in_class(class_scope, name), Scope::ClassBody(class_body_scope) => { find_type_symbol_in_class_body(class_body_scope, name) } _ => None, } }