deimos-lang/src/name_analysis/symbol.rs
2025-05-26 08:30:15 -05:00

484 lines
12 KiB
Rust

use crate::ast::node::named::Named;
use crate::ast::node::names::Identifier;
use crate::ast::node::use_statement::UseStatement;
use std::cell::RefCell;
use std::fmt::{Debug, Display, Formatter};
use std::ops::Deref;
use std::range::Range;
use std::rc::Rc;
#[derive(Clone, Debug)]
pub struct SourceDefinition {
file_id: usize,
range: Range<usize>,
}
impl SourceDefinition {
pub fn from_identifier(identifier: &Identifier) -> Self {
SourceDefinition {
file_id: identifier.file_id(),
range: identifier.range(),
}
}
pub fn from_identifier_rc(identifier: Rc<RefCell<Identifier>>) -> Self {
let borrowed = identifier.borrow();
SourceDefinition {
file_id: borrowed.file_id(),
range: borrowed.range(),
}
}
#[deprecated(note = "Use identifier instead.")]
pub fn from_use_statement(use_statement: &UseStatement) -> Self {
SourceDefinition {
file_id: use_statement.file_id(),
range: use_statement.range(),
}
}
pub fn file_id(&self) -> usize {
self.file_id
}
pub fn range(&self) -> Range<usize> {
self.range.clone()
}
}
pub trait SymbolInner {
fn declared_name(&self) -> &str;
fn definition(&self) -> Option<SourceDefinition>;
}
/* Symbol */
#[derive(Debug, Clone)]
pub enum Symbol {
UseStatement(Rc<RefCell<UseStatementSymbol>>),
Module(Rc<ModuleSymbol>),
Type(Rc<TypeSymbol>),
Function(Rc<RefCell<FunctionSymbol>>),
Parameter(Rc<ParameterSymbol>),
Variable(Rc<VariableSymbol>),
ClassMember(Rc<ClassMemberSymbol>),
}
impl Symbol {
pub fn definition(&self) -> Option<SourceDefinition> {
match self {
Symbol::UseStatement(s) => s.borrow().definition(),
Symbol::Module(s) => s.definition(),
Symbol::Type(s) => match s.deref() {
TypeSymbol::Concrete(cts) => cts.definition(),
TypeSymbol::Generic(gts) => gts.definition(),
},
Symbol::Function(s) => s.borrow().definition(),
Symbol::Parameter(s) => s.definition(),
Symbol::Variable(s) => s.definition(),
Symbol::ClassMember(s) => s.definition(),
}
}
pub fn unwrap_use_statement_symbol(&self) -> Rc<RefCell<UseStatementSymbol>> {
match self {
Symbol::UseStatement(s) => s.clone(),
_ => panic!("unwrap_use_statement_symbol called on non-use statement symbol"),
}
}
}
/* Use-statement */
pub struct UseStatementSymbol {
pub fqn: String,
pub declared_name: String,
definition: Option<SourceDefinition>,
referenced_symbol: Option<Box<Symbol>>,
}
impl UseStatementSymbol {
pub fn new(fqn: &str, declared_name: &str, identifier: Option<&Identifier>) -> Self {
UseStatementSymbol {
fqn: fqn.to_string(),
declared_name: declared_name.to_string(),
definition: identifier.map(SourceDefinition::from_identifier),
referenced_symbol: None,
}
}
pub fn set_referenced_symbol(&mut self, referenced_symbol: Symbol) {
self.referenced_symbol = Some(Box::new(referenced_symbol));
}
pub fn referenced_symbol(&self) -> Option<Box<Symbol>> {
self.referenced_symbol.clone()
}
}
impl SymbolInner for UseStatementSymbol {
fn declared_name(&self) -> &str {
&self.declared_name
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for UseStatementSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("UseStatementSymbol")
.field("fqn", &self.fqn)
.field("declared_name", &self.declared_name)
.field("referenced_symbol", &self.referenced_symbol)
.finish()
}
}
/* Module */
pub struct ModuleSymbol {
fqn: String,
declared_name: String,
is_public: bool,
definition: Option<SourceDefinition>,
}
impl ModuleSymbol {
pub fn new(
fqn: &str,
declared_name: &str,
is_public: bool,
identifier: Option<&Identifier>,
) -> ModuleSymbol {
ModuleSymbol {
fqn: fqn.to_string(),
declared_name: declared_name.to_string(),
is_public,
definition: identifier.map(SourceDefinition::from_identifier),
}
}
}
impl SymbolInner for ModuleSymbol {
fn declared_name(&self) -> &str {
self.declared_name.as_str()
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for ModuleSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ModuleSymbol")
.field("fqn", &self.fqn)
.field("declared_name", &self.declared_name)
.field("is_public", &self.is_public)
.finish()
}
}
/* TypeSymbol */
#[derive(Debug)]
pub enum TypeSymbol {
Concrete(ConcreteTypeSymbol),
Generic(GenericTypeSymbol),
}
impl TypeSymbol {
pub fn declared_name(&self) -> &str {
match self {
TypeSymbol::Concrete(t) => t.declared_name(),
TypeSymbol::Generic(t) => t.declared_name(),
}
}
}
pub struct ConcreteTypeSymbol {
fqn: String,
declared_name: String,
is_public: bool,
definition: Option<SourceDefinition>,
}
impl ConcreteTypeSymbol {
pub fn new(
fqn: &str,
declared_name: &str,
is_public: bool,
identifier: Option<&Identifier>,
) -> Self {
ConcreteTypeSymbol {
fqn: fqn.to_string(),
declared_name: declared_name.to_string(),
is_public,
definition: identifier.map(SourceDefinition::from_identifier),
}
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn is_public(&self) -> bool {
self.is_public
}
}
impl SymbolInner for ConcreteTypeSymbol {
fn declared_name(&self) -> &str {
&self.declared_name
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for ConcreteTypeSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TypeSymbol")
.field("fqn", &self.fqn)
.field("declared_name", &self.declared_name)
.field("is_public", &self.is_public)
.finish()
}
}
pub struct GenericTypeSymbol {
declared_name: String,
source_definition: SourceDefinition,
}
impl GenericTypeSymbol {
pub fn new(declared_name: &str, source_definition: SourceDefinition) -> Self {
GenericTypeSymbol {
declared_name: declared_name.to_string(),
source_definition,
}
}
}
impl SymbolInner for GenericTypeSymbol {
fn declared_name(&self) -> &str {
self.declared_name.as_str()
}
fn definition(&self) -> Option<SourceDefinition> {
Some(self.source_definition.clone())
}
}
impl Debug for GenericTypeSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GenericTypeSymbol")
.field("declared_name", &self.declared_name)
.finish()
}
}
/* Function */
pub struct FunctionSymbol {
fqn: String,
declared_name: String,
is_public: bool,
is_platform: bool,
definition: Option<SourceDefinition>,
parameters: Vec<Rc<ParameterSymbol>>,
return_type: Option<Rc<ConcreteTypeSymbol>>,
}
impl FunctionSymbol {
pub fn new(
fqn: &str,
declared_name: &str,
is_public: bool,
is_platform: bool,
identifier: Option<&Identifier>,
) -> FunctionSymbol {
FunctionSymbol {
fqn: fqn.to_string(),
declared_name: declared_name.to_string(),
is_public,
is_platform,
definition: identifier.map(SourceDefinition::from_identifier),
parameters: Vec::new(),
return_type: None,
}
}
pub fn with_parameters(self, parameters: Vec<ParameterSymbol>) -> Self {
Self {
fqn: self.fqn,
declared_name: self.declared_name,
is_public: self.is_public,
is_platform: self.is_platform,
definition: self.definition,
parameters: parameters
.into_iter()
.map(|parameter| Rc::new(parameter))
.collect(),
return_type: self.return_type,
}
}
pub fn with_return_type(self, return_type: ConcreteTypeSymbol) -> Self {
Self {
fqn: self.fqn,
declared_name: self.declared_name,
is_public: self.is_public,
is_platform: self.is_platform,
definition: self.definition,
parameters: self.parameters,
return_type: Some(Rc::new(return_type)),
}
}
pub fn fqn(&self) -> &str {
&self.fqn
}
pub fn set_parameters(&mut self, parameters: Vec<Rc<ParameterSymbol>>) {
self.parameters = parameters;
}
pub fn set_return_type(&mut self, return_type: Rc<ConcreteTypeSymbol>) {
self.return_type = Some(return_type);
}
}
impl SymbolInner for FunctionSymbol {
fn declared_name(&self) -> &str {
self.declared_name.as_str()
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for FunctionSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FunctionSymbol")
.field("fqn", &self.fqn)
.field("declared_name", &self.declared_name)
.field("is_public", &self.is_public)
.field("is_platform", &self.is_platform)
.field("parameters", &self.parameters)
.field("return_type", &self.return_type)
.finish()
}
}
/* Parameter */
pub struct ParameterSymbol {
declared_name: String,
definition: Option<SourceDefinition>,
}
impl ParameterSymbol {
pub fn new(declared_name: &str, identifier: Option<&Identifier>) -> Self {
ParameterSymbol {
declared_name: declared_name.to_string(),
definition: identifier.map(SourceDefinition::from_identifier),
}
}
}
impl SymbolInner for ParameterSymbol {
fn declared_name(&self) -> &str {
&self.declared_name
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for ParameterSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ParameterSymbol")
.field("declared_name", &self.declared_name)
.finish()
}
}
/* Variable */
pub struct VariableSymbol {
declared_name: String,
is_mutable: bool,
definition: Option<SourceDefinition>,
}
impl VariableSymbol {
pub fn new(declared_name: &str, is_mutable: bool, identifier: Option<&Identifier>) -> Self {
VariableSymbol {
declared_name: declared_name.to_string(),
is_mutable,
definition: identifier.map(SourceDefinition::from_identifier),
}
}
}
impl SymbolInner for VariableSymbol {
fn declared_name(&self) -> &str {
self.declared_name.as_str()
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for VariableSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("VariableSymbol")
.field("declared_name", &self.declared_name)
.field("is_mutable", &self.is_mutable)
.finish()
}
}
/* Class Member */
pub struct ClassMemberSymbol {
declared_name: String,
is_field: bool,
definition: Option<SourceDefinition>,
}
impl ClassMemberSymbol {
pub fn new(declared_name: &str, is_field: bool, definition: Option<SourceDefinition>) -> Self {
ClassMemberSymbol {
declared_name: declared_name.to_string(),
is_field,
definition,
}
}
}
impl SymbolInner for ClassMemberSymbol {
fn declared_name(&self) -> &str {
self.declared_name.as_str()
}
fn definition(&self) -> Option<SourceDefinition> {
self.definition.clone()
}
}
impl Debug for ClassMemberSymbol {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClassMemberSymbol")
.field("declared_name", &self.declared_name)
.finish()
}
}