150 lines
4.6 KiB
Rust
150 lines
4.6 KiB
Rust
use crate::ast::fqn_context::FqnContext;
|
|
use crate::ast::helpers::{collect_diagnostics_into_mut, collect_parameter_symbols_into};
|
|
use crate::ast::parameter::Parameter;
|
|
use crate::ast::type_use::TypeUse;
|
|
use crate::diagnostic::Diagnostic;
|
|
use crate::source_range::SourceRange;
|
|
use crate::symbol::Symbol;
|
|
use crate::symbol::function_symbol::FunctionSymbol;
|
|
use crate::symbol_table::SymbolTable;
|
|
use crate::type_info::TypeInfo;
|
|
use crate::types_table::TypesTable;
|
|
use crate::{diagnostics_result, handle_diagnostics};
|
|
use std::rc::Rc;
|
|
|
|
pub struct ExternFunction {
|
|
declared_name: Rc<str>,
|
|
declared_name_source_range: SourceRange,
|
|
parameters: Vec<Parameter>,
|
|
return_type: TypeUse,
|
|
scope_id: Option<usize>,
|
|
}
|
|
|
|
impl ExternFunction {
|
|
pub fn new(
|
|
name: &str,
|
|
declared_name_source_range: SourceRange,
|
|
parameters: Vec<Parameter>,
|
|
return_type: TypeUse,
|
|
) -> Self {
|
|
Self {
|
|
declared_name: name.into(),
|
|
declared_name_source_range,
|
|
parameters,
|
|
return_type,
|
|
scope_id: None,
|
|
}
|
|
}
|
|
|
|
pub fn declared_name(&self) -> &str {
|
|
&self.declared_name
|
|
}
|
|
|
|
pub fn init_scopes(&mut self, symbol_table: &mut SymbolTable, container_scope: usize) {
|
|
self.scope_id = Some(container_scope);
|
|
|
|
let function_scope = symbol_table
|
|
.push_function_scope(&format!("extern_function_scope({})", self.declared_name));
|
|
|
|
for parameter in &mut self.parameters {
|
|
parameter.init_scopes(symbol_table, function_scope);
|
|
}
|
|
self.return_type.init_scopes(symbol_table, function_scope);
|
|
|
|
symbol_table.pop_scope();
|
|
}
|
|
|
|
pub fn make_symbols(&self, fqn_context: &FqnContext) -> (Rc<FunctionSymbol>, Vec<Symbol>) {
|
|
let mut all_symbols: Vec<Symbol> = Vec::new();
|
|
|
|
let mut parameter_symbols = Vec::new();
|
|
collect_parameter_symbols_into(&self.parameters, &mut all_symbols, &mut parameter_symbols);
|
|
|
|
let function_symbol = Rc::new(FunctionSymbol::new(
|
|
&self.declared_name,
|
|
self.declared_name_source_range.clone(),
|
|
fqn_context.resolve(self.declared_name()),
|
|
true,
|
|
false,
|
|
self.scope_id.unwrap(),
|
|
parameter_symbols,
|
|
));
|
|
all_symbols.push(Symbol::Function(function_symbol.clone()));
|
|
|
|
(function_symbol, all_symbols)
|
|
}
|
|
|
|
pub fn check_names(&self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
|
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
|
for parameter in &self.parameters {
|
|
diagnostics.append(&mut parameter.check_names(symbol_table));
|
|
}
|
|
diagnostics.append(&mut self.return_type.check_names(symbol_table));
|
|
diagnostics
|
|
}
|
|
|
|
pub fn gather_types(&self, symbol_table: &SymbolTable, types_table: &mut TypesTable) {
|
|
let function_symbol = symbol_table
|
|
.get_function_symbol_owned(self.scope_id.unwrap(), self.declared_name())
|
|
.unwrap();
|
|
|
|
// self function type
|
|
types_table.function_types_mut().insert(
|
|
function_symbol.clone(),
|
|
TypeInfo::Function(function_symbol.clone()),
|
|
);
|
|
|
|
// return type (temporary)
|
|
let resolved_return_type = self
|
|
.return_type
|
|
.type_info(symbol_table, types_table)
|
|
.clone();
|
|
types_table
|
|
.function_return_types_mut()
|
|
.insert(function_symbol, resolved_return_type);
|
|
|
|
// parameters
|
|
for parameter in &self.parameters {
|
|
parameter.gather_types_into(symbol_table, types_table);
|
|
}
|
|
}
|
|
|
|
fn type_check_parameters(
|
|
&mut self,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
diagnostics: &mut Vec<Diagnostic>,
|
|
) {
|
|
collect_diagnostics_into_mut(
|
|
&mut self.parameters,
|
|
|p| p.type_check(symbol_table, types_table),
|
|
diagnostics,
|
|
);
|
|
}
|
|
|
|
fn type_check_return_type(
|
|
&mut self,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
diagnostics: &mut Vec<Diagnostic>,
|
|
) {
|
|
handle_diagnostics!(
|
|
self.return_type.type_check(symbol_table, types_table),
|
|
diagnostics
|
|
);
|
|
}
|
|
|
|
pub fn type_check(
|
|
&mut self,
|
|
symbol_table: &SymbolTable,
|
|
types_table: &TypesTable,
|
|
) -> Result<(), Vec<Diagnostic>> {
|
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
|
|
|
self.type_check_parameters(symbol_table, types_table, &mut diagnostics);
|
|
self.type_check_return_type(symbol_table, types_table, &mut diagnostics);
|
|
|
|
diagnostics_result!(diagnostics)
|
|
}
|
|
}
|