deimos-lang/dmc-lib/src/ast/generic_parameter.rs

111 lines
3.4 KiB
Rust

use crate::ast::NodesToSymbols;
use crate::ast::helpers::insert_resolved_names_into;
use crate::ast::type_use::TypeUse;
use crate::diagnostic::{Diagnostic, Diagnostics};
use crate::source_range::SourceRange;
use crate::symbol::generic_parameter_symbol::GenericParameterSymbol;
use crate::symbol_table::SymbolTable;
use crate::type_info::TypeInfo;
use crate::types_table::TypesTable;
use crate::{diagnostics_result, handle_diagnostics};
use std::cell::RefCell;
use std::rc::Rc;
pub struct GenericParameter {
declared_name: Rc<str>,
declared_name_source_range: SourceRange,
extends: Vec<TypeUse>,
scope_id: Option<usize>,
generic_parameter_symbol: Option<Rc<RefCell<GenericParameterSymbol>>>,
}
impl GenericParameter {
pub fn new(
declared_name: &str,
declared_name_source_range: SourceRange,
extends: Vec<TypeUse>,
) -> Self {
Self {
declared_name: declared_name.into(),
declared_name_source_range,
extends,
scope_id: None,
generic_parameter_symbol: None,
}
}
pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) {
self.scope_id = Some(container_scope);
for type_use in &mut self.extends {
type_use.init_scopes(symbol_table, container_scope);
}
}
pub fn make_symbol(&self) -> GenericParameterSymbol {
GenericParameterSymbol::new(
&self.declared_name,
&self.declared_name_source_range,
self.scope_id.unwrap(),
)
}
pub fn resolve_names(&self, symbol_table: &SymbolTable) -> (NodesToSymbols, Diagnostics) {
let mut diagnostics = Diagnostics::new();
let mut names_table = NodesToSymbols::new();
for type_use in &self.extends {
let (ns, mut ds) = type_use.resolve_names(symbol_table);
insert_resolved_names_into(ns, &mut names_table);
diagnostics.append(&mut ds);
}
(names_table, diagnostics)
}
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
self.extends
.iter()
.flat_map(|type_use| type_use.check_names(symbol_table))
.collect()
}
pub fn gather_types(
&self,
symbol_table: &SymbolTable,
types_table: &mut TypesTable,
) -> Result<(), Vec<Diagnostic>> {
// self param
let generic_parameter_symbol = symbol_table
.get_generic_parameter_symbol_owned(self.scope_id.unwrap(), &self.declared_name)
.unwrap();
types_table.generic_parameter_types_mut().insert(
generic_parameter_symbol.clone(),
TypeInfo::GenericType(generic_parameter_symbol),
);
let mut diagnostics = Vec::new();
for type_use in &self.extends {
handle_diagnostics!(
type_use.gather_types(symbol_table, types_table),
diagnostics
);
}
diagnostics_result!(diagnostics)
}
pub fn type_check(
&mut self,
symbol_table: &SymbolTable,
types_table: &TypesTable,
) -> Result<(), Vec<Diagnostic>> {
let mut diagnostics: Vec<Diagnostic> = vec![];
// check extends type uses
for type_use in &mut self.extends {
handle_diagnostics!(type_use.type_check(symbol_table, types_table), diagnostics);
}
diagnostics_result!(diagnostics)
}
}