Move parameter gathering to second pass in order to match analysis of all locals there.
This commit is contained in:
parent
13330300c1
commit
0550df534e
@ -59,7 +59,9 @@ pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parse_errors.is_empty() {
|
if !parse_errors.is_empty() {
|
||||||
return Err(Box::new(ParseErrors { errors: parse_errors }));
|
return Err(Box::new(ParseErrors {
|
||||||
|
errors: parse_errors,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
|||||||
@ -1,25 +1,20 @@
|
|||||||
use crate::ast::node::{
|
use crate::ast::node::{
|
||||||
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody,
|
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody
|
||||||
GenericParameters, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration, Parameter,
|
, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration
|
||||||
Parameters, PrimitiveType, ReturnType, StarUseStatement, TypeUse, TypedArray, UseStatement,
|
, StarUseStatement, UseStatement,
|
||||||
UseStatementIdentifier, UseStatementPrefix,
|
UseStatementIdentifier, UseStatementPrefix,
|
||||||
};
|
};
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
|
||||||
use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol;
|
|
||||||
use crate::name_analysis::symbol::module_level_symbol::ModuleLevelSymbol;
|
use crate::name_analysis::symbol::module_level_symbol::ModuleLevelSymbol;
|
||||||
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
|
||||||
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
|
|
||||||
use crate::name_analysis::symbol::primitive_type_symbol::PrimitiveTypeSymbol;
|
|
||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
use crate::name_analysis::symbol::type_symbol::TypeSymbol;
|
|
||||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
use crate::name_analysis::symbol_table::SymbolTable;
|
use crate::name_analysis::symbol_table::SymbolTable;
|
||||||
use crate::name_analysis::util::{
|
use crate::name_analysis::util::{
|
||||||
format_fqn, handle_insert_error, handle_lookup_error, join_fqn_parts,
|
handle_insert_error, join_fqn_parts,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::format;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn na_p1_compilation_unit(
|
pub fn na_p1_compilation_unit(
|
||||||
@ -250,7 +245,7 @@ fn na_p1_function(
|
|||||||
false,
|
false,
|
||||||
Some(SourceDefinition::from_identifier(function.identifier())),
|
Some(SourceDefinition::from_identifier(function.identifier())),
|
||||||
);
|
);
|
||||||
let function_symbol = match symbol_table.insert_function_symbol(to_insert) {
|
let maybe_function_symbol = match symbol_table.insert_function_symbol(to_insert) {
|
||||||
Ok(function_symbol) => Some(function_symbol),
|
Ok(function_symbol) => Some(function_symbol),
|
||||||
Err(symbol_insert_error) => {
|
Err(symbol_insert_error) => {
|
||||||
handle_insert_error(
|
handle_insert_error(
|
||||||
@ -264,232 +259,14 @@ fn na_p1_function(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if function_symbol.is_some() {
|
if maybe_function_symbol.is_some() {
|
||||||
let mut as_ref_mut = function_symbol.as_ref().unwrap().borrow_mut();
|
function.set_function_symbol(maybe_function_symbol.as_ref().unwrap().clone());
|
||||||
|
}
|
||||||
|
|
||||||
// push a scope for this function
|
// create a scope for this function
|
||||||
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
|
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
|
||||||
|
function.set_scope_id(symbol_table.current_scope_id());
|
||||||
// generics
|
|
||||||
na_p1_generic_parameters(function.generics_mut(), symbol_table, diagnostics);
|
|
||||||
|
|
||||||
// parameters
|
|
||||||
as_ref_mut.set_parameter_symbols(na_p1_parameters(
|
|
||||||
function.parameters_mut(),
|
|
||||||
symbol_table,
|
|
||||||
diagnostics,
|
|
||||||
));
|
|
||||||
|
|
||||||
// return type
|
|
||||||
let return_type = na_p1_return_type(function.return_type_mut(), symbol_table, diagnostics);
|
|
||||||
if let Some(type_symbol) = return_type {
|
|
||||||
as_ref_mut.set_return_type(type_symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
symbol_table.push_scope(&format!(
|
|
||||||
"FunctionBodyScope {}",
|
|
||||||
function.identifier().name()
|
|
||||||
));
|
|
||||||
|
|
||||||
na_p1_function_body(
|
|
||||||
function.function_body_mut(),
|
|
||||||
symbol_table,
|
|
||||||
diagnostics
|
|
||||||
);
|
|
||||||
|
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope();
|
||||||
symbol_table.pop_scope();
|
|
||||||
}
|
|
||||||
|
|
||||||
function_symbol
|
maybe_function_symbol
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_parameters(
|
|
||||||
parameters: &mut Parameters,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) -> Vec<Rc<RefCell<ParameterSymbol>>> {
|
|
||||||
parameters
|
|
||||||
.parameters_mut()
|
|
||||||
.map(|parameter| na_p1_parameter(parameter, symbol_table, diagnostics))
|
|
||||||
.filter(Option::is_some)
|
|
||||||
.map(Option::unwrap)
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_parameter(
|
|
||||||
parameter: &mut Parameter,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) -> Option<Rc<RefCell<ParameterSymbol>>> {
|
|
||||||
let parameter_type_symbol = na_p1_type_use(parameter.type_use_mut(), symbol_table, diagnostics);
|
|
||||||
let to_insert = ParameterSymbol::new(
|
|
||||||
parameter.identifier().name(),
|
|
||||||
Some(SourceDefinition::from_identifier(parameter.identifier())),
|
|
||||||
parameter_type_symbol,
|
|
||||||
);
|
|
||||||
match symbol_table.insert_parameter_symbol(to_insert) {
|
|
||||||
Ok(parameter_symbol) => Some(parameter_symbol),
|
|
||||||
Err(symbol_insert_error) => {
|
|
||||||
handle_insert_error(
|
|
||||||
symbol_insert_error,
|
|
||||||
parameter.identifier().name(),
|
|
||||||
parameter.identifier().file_id(),
|
|
||||||
parameter.identifier().range(),
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_return_type(
|
|
||||||
return_type: &mut ReturnType,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) -> Option<TypeSymbol> {
|
|
||||||
na_p1_type_use(return_type.type_use_mut(), symbol_table, diagnostics)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_type_use(
|
|
||||||
type_use: &mut TypeUse,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) -> Option<TypeSymbol> {
|
|
||||||
match type_use {
|
|
||||||
TypeUse::PrimitiveType(primitive_type) => {
|
|
||||||
Some(TypeSymbol::Primitive(match primitive_type {
|
|
||||||
PrimitiveType::Byte => PrimitiveTypeSymbol::Byte,
|
|
||||||
PrimitiveType::Short => PrimitiveTypeSymbol::Short,
|
|
||||||
PrimitiveType::Char => PrimitiveTypeSymbol::Char,
|
|
||||||
PrimitiveType::Int => PrimitiveTypeSymbol::Int,
|
|
||||||
PrimitiveType::Long => PrimitiveTypeSymbol::Long,
|
|
||||||
PrimitiveType::Double => PrimitiveTypeSymbol::Double,
|
|
||||||
PrimitiveType::Bool => PrimitiveTypeSymbol::Boolean,
|
|
||||||
PrimitiveType::String => PrimitiveTypeSymbol::String,
|
|
||||||
PrimitiveType::TypedArray(typed_array) => {
|
|
||||||
na_p1_typed_array(typed_array, symbol_table, diagnostics)
|
|
||||||
}
|
|
||||||
PrimitiveType::Any => PrimitiveTypeSymbol::Any,
|
|
||||||
PrimitiveType::Void => PrimitiveTypeSymbol::Void,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
TypeUse::InterfaceOrClassTypeUse(interface_or_class_type) => {
|
|
||||||
match interface_or_class_type.identifier_or_fqn() {
|
|
||||||
IdentifierOrFqn::Identifier(identifier) => {
|
|
||||||
match symbol_table.lookup_type(identifier.name()) {
|
|
||||||
Ok(type_symbol) => {
|
|
||||||
interface_or_class_type.set_type_symbol(type_symbol.clone());
|
|
||||||
Some(type_symbol)
|
|
||||||
}
|
|
||||||
Err(symbol_lookup_error) => {
|
|
||||||
handle_lookup_error(
|
|
||||||
symbol_lookup_error,
|
|
||||||
identifier.name(),
|
|
||||||
identifier.file_id(),
|
|
||||||
identifier.range(),
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IdentifierOrFqn::FullyQualifiedName(fqn) => {
|
|
||||||
let fqn_parts = fqn
|
|
||||||
.identifiers()
|
|
||||||
.map(Identifier::name)
|
|
||||||
.collect::<Vec<&str>>();
|
|
||||||
match symbol_table.lookup_type_by_fqn(&fqn_parts) {
|
|
||||||
Ok(type_symbol) => {
|
|
||||||
interface_or_class_type.set_type_symbol(type_symbol.clone());
|
|
||||||
Some(type_symbol)
|
|
||||||
}
|
|
||||||
Err(symbol_lookup_error) => {
|
|
||||||
handle_lookup_error(
|
|
||||||
symbol_lookup_error,
|
|
||||||
&format_fqn(&fqn_parts),
|
|
||||||
fqn.file_id(),
|
|
||||||
fqn.range(),
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TypeUse::TupleTypeUse(tuple_type) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeUse::FunctionTypeUse(function_type) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_typed_array(
|
|
||||||
typed_array: &mut TypedArray,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) -> PrimitiveTypeSymbol {
|
|
||||||
let inner_type_use = typed_array
|
|
||||||
.generic_arguments_mut()
|
|
||||||
.type_use_list_mut()
|
|
||||||
.type_uses_mut()
|
|
||||||
.next()
|
|
||||||
.unwrap();
|
|
||||||
let inner_type_symbol = na_p1_type_use(inner_type_use, symbol_table, diagnostics);
|
|
||||||
PrimitiveTypeSymbol::TypedArray {
|
|
||||||
inner_type: inner_type_symbol.map(Box::from),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_generic_parameters(
|
|
||||||
generic_parameters: &mut GenericParameters,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) {
|
|
||||||
for identifier in generic_parameters.identifier_list().identifiers() {
|
|
||||||
let generic_type_symbol = GenericTypeSymbol::new(
|
|
||||||
identifier.name(),
|
|
||||||
Some(SourceDefinition::from_identifier(identifier)),
|
|
||||||
);
|
|
||||||
match symbol_table.insert_generic_type_symbol(generic_type_symbol) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(symbol_insert_error) => {
|
|
||||||
handle_insert_error(
|
|
||||||
symbol_insert_error,
|
|
||||||
identifier.name(),
|
|
||||||
identifier.file_id(),
|
|
||||||
identifier.range(),
|
|
||||||
diagnostics,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn na_p1_function_body(
|
|
||||||
function_body: &mut FunctionBody,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) {
|
|
||||||
match function_body {
|
|
||||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
|
||||||
// set scope id for pass 2; see below
|
|
||||||
alias_body.set_scope_id(symbol_table.current_scope_id());
|
|
||||||
}
|
|
||||||
FunctionBody::FunctionEqualsBody(equals_body) => {
|
|
||||||
// see below
|
|
||||||
equals_body.set_scope_id(symbol_table.current_scope_id());
|
|
||||||
}
|
|
||||||
FunctionBody::FunctionBlockBody(block_body) => {
|
|
||||||
// we need to do all insertion/resolution in pass 2, because we
|
|
||||||
// might call functions/use classes/etc from the same compilation
|
|
||||||
// unit which haven't been defined yet. So the strategy is to set
|
|
||||||
// the scope id for the body and then in pass 2, set the symbol
|
|
||||||
// table's current scope to that id.
|
|
||||||
block_body.set_scope_id(symbol_table.current_scope_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ pub fn analyze_names<
|
|||||||
'a,
|
'a,
|
||||||
F: Files<'a, FileId = usize, Name = &'a str, Source = &'a str> + ?Sized,
|
F: Files<'a, FileId = usize, Name = &'a str, Source = &'a str> + ?Sized,
|
||||||
>(
|
>(
|
||||||
compilation_units: &mut Vec<CompilationUnit>,
|
compilation_units: &mut [CompilationUnit],
|
||||||
files: &'a F,
|
files: &'a F,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Vec<DmDiagnostic> {
|
) -> Vec<DmDiagnostic> {
|
||||||
@ -57,7 +57,7 @@ pub fn analyze_names<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
for compilation_unit in compilation_units {
|
for compilation_unit in compilation_units.iter_mut() {
|
||||||
na_p2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
na_p2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +68,7 @@ pub fn analyze_names<
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ast::build::build_ast;
|
use crate::ast::build::build_ast;
|
||||||
|
use crate::name_analysis::symbol::use_symbol::StarUseSymbol;
|
||||||
use crate::parser::{DeimosParser, Rule};
|
use crate::parser::{DeimosParser, Rule};
|
||||||
use crate::std_core::add_std_core_symbols;
|
use crate::std_core::add_std_core_symbols;
|
||||||
use codespan_reporting::files::SimpleFiles;
|
use codespan_reporting::files::SimpleFiles;
|
||||||
@ -75,14 +76,17 @@ mod tests {
|
|||||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::name_analysis::symbol::use_symbol::StarUseSymbol;
|
use crate::ast::ast_node::AstNodeRef;
|
||||||
|
use crate::ast::walk::walk_depth_first;
|
||||||
|
use crate::name_analysis::symbol::{LVSymbol, PrimitiveTypeSymbol, TypeSymbol};
|
||||||
|
|
||||||
fn parse_compilation_units<'a>(
|
fn parse_compilation_units<'a>(
|
||||||
files: &mut SimpleFiles<&'a str, &'a str>,
|
files: &mut SimpleFiles<&'a str, &'a str>,
|
||||||
sources: HashMap<&'a str, &'a str>,
|
sources: HashMap<&'a str, &'a str>,
|
||||||
) -> Vec<CompilationUnit> {
|
) -> Vec<CompilationUnit> {
|
||||||
let mut compilation_units: Vec<CompilationUnit> = vec![];
|
let mut compilation_units = vec![];
|
||||||
|
|
||||||
for (file_name, source) in sources {
|
for (file_name, source) in sources {
|
||||||
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
|
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
|
||||||
@ -104,11 +108,15 @@ mod tests {
|
|||||||
sources: HashMap<&'a str, &'a str>,
|
sources: HashMap<&'a str, &'a str>,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
number_of_diagnostics: usize,
|
number_of_diagnostics: usize,
|
||||||
) -> Vec<CompilationUnit> {
|
) -> (Vec<CompilationUnit>, SimpleFiles<&'a str, &'a str>) {
|
||||||
let mut files = SimpleFiles::<&'a str, &'a str>::new();
|
let mut files = SimpleFiles::<&'a str, &'a str>::new();
|
||||||
let mut compilation_units = parse_compilation_units(&mut files, sources);
|
let mut to_analyze = parse_compilation_units(&mut files, sources);
|
||||||
|
|
||||||
let diagnostics = analyze_names(&mut compilation_units, &files, symbol_table);
|
let diagnostics = analyze_names(
|
||||||
|
&mut to_analyze,
|
||||||
|
&files,
|
||||||
|
symbol_table
|
||||||
|
);
|
||||||
|
|
||||||
if diagnostics.len() != number_of_diagnostics {
|
if diagnostics.len() != number_of_diagnostics {
|
||||||
let writer = StandardStream::stderr(ColorChoice::Always);
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
||||||
@ -123,16 +131,31 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(number_of_diagnostics, diagnostics.len());
|
assert_eq!(number_of_diagnostics, diagnostics.len());
|
||||||
|
|
||||||
compilation_units
|
(to_analyze, files)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_no_diagnostics(
|
fn assert_no_diagnostics<'a>(
|
||||||
sources: HashMap<&str, &str>,
|
sources: HashMap<&'a str, &'a str>,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
) -> Vec<CompilationUnit> {
|
) -> (Vec<CompilationUnit>, SimpleFiles<&'a str, &'a str>) {
|
||||||
assert_number_of_diagnostics(sources, symbol_table, 0)
|
assert_number_of_diagnostics(sources, symbol_table, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_names_to_cus_map<'a>(
|
||||||
|
compilation_units: &'a [CompilationUnit],
|
||||||
|
files: &SimpleFiles<&'a str, &str>,
|
||||||
|
) -> HashMap<&'a str, &'a CompilationUnit> {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
for compilation_unit in compilation_units {
|
||||||
|
let file_id = compilation_unit.file_id();
|
||||||
|
let name = files.name(file_id).unwrap();
|
||||||
|
map.insert(name, compilation_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn params_seen() {
|
fn params_seen() {
|
||||||
let sources = HashMap::from([(
|
let sources = HashMap::from([(
|
||||||
@ -144,7 +167,79 @@ mod tests {
|
|||||||
",
|
",
|
||||||
)]);
|
)]);
|
||||||
|
|
||||||
assert_no_diagnostics(sources, &mut SymbolTable::new());
|
let mut symbol_table = SymbolTable::new();
|
||||||
|
let (cus, files) = assert_no_diagnostics(sources, &mut symbol_table);
|
||||||
|
let results_map = make_names_to_cus_map(&cus, &files);
|
||||||
|
let main_cu = *results_map.get("main.dm").unwrap();
|
||||||
|
|
||||||
|
let mut found_main = false;
|
||||||
|
let mut found_x = false;
|
||||||
|
let mut found_args_ref = false;
|
||||||
|
|
||||||
|
walk_depth_first(main_cu, &mut |node| {
|
||||||
|
use AstNodeRef::*;
|
||||||
|
match node {
|
||||||
|
Function(function) => {
|
||||||
|
if function.identifier().name() == "main" {
|
||||||
|
found_main = true;
|
||||||
|
let function_symbol_ref = function.function_symbol().unwrap().borrow();
|
||||||
|
assert_eq!("main", function_symbol_ref.declared_name());
|
||||||
|
let parameter_symbols = function_symbol_ref.parameter_symbols();
|
||||||
|
assert_eq!(parameter_symbols.len(), 1);
|
||||||
|
let args_ref = parameter_symbols[0].borrow();
|
||||||
|
assert_eq!(args_ref.declared_name(), "args");
|
||||||
|
let args_type_symbol = args_ref.type_symbol().unwrap();
|
||||||
|
match args_type_symbol {
|
||||||
|
TypeSymbol::Primitive(primitive_type_symbol) => {
|
||||||
|
match primitive_type_symbol {
|
||||||
|
PrimitiveTypeSymbol::TypedArray { inner_type } => {
|
||||||
|
match *inner_type.clone().unwrap() {
|
||||||
|
TypeSymbol::Primitive(primitive_type_symbol) => {
|
||||||
|
match primitive_type_symbol {
|
||||||
|
PrimitiveTypeSymbol::String => {}
|
||||||
|
_ => panic!("Expected String for args' inner type.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a primitive type symbol for args' inner type.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a TypeArray for args."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a primitive type symbol for args.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VariableDeclaration(variable_declaration) => {
|
||||||
|
if variable_declaration.identifier().name() == "x" {
|
||||||
|
found_x = true;
|
||||||
|
assert_eq!(
|
||||||
|
variable_declaration.variable_symbol().unwrap().borrow().declared_name(),
|
||||||
|
"x"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableUse(variable_use) => {
|
||||||
|
if variable_use.identifier().name() == "args" {
|
||||||
|
found_args_ref = true;
|
||||||
|
match variable_use.lv_symbol().unwrap() {
|
||||||
|
LVSymbol::Parameter(parameter_symbol) => {
|
||||||
|
assert_eq!(
|
||||||
|
parameter_symbol.borrow().declared_name(),
|
||||||
|
"args"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => panic!("Expected args variable use to be a parameter symbol.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert!(found_main);
|
||||||
|
assert!(found_x);
|
||||||
|
assert!(found_args_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -1,9 +1,22 @@
|
|||||||
use crate::ast::node::{AssignmentStatement, CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Expression, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody, FunctionBody, Identifier, LValue, ModuleLevelDeclaration, StarUseStatement, Statement, TypeUse, UseStatement, UseStatementIdentifier, UseStatementPrefix, VariableDeclaration, VariableUse};
|
use crate::ast::node::{
|
||||||
|
AssignmentStatement, CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix,
|
||||||
|
Expression, ExpressionStatement, Function, FunctionAliasBody, FunctionBlockBody, FunctionBody,
|
||||||
|
FunctionEqualsBody, GenericParameters, Identifier, IdentifierOrFqn, LValue, LValueSuffix,
|
||||||
|
ModuleLevelDeclaration, Parameter, Parameters, PrimitiveType, ReturnType, StarUseStatement,
|
||||||
|
Statement, TypeUse, TypedArray, UseStatement, UseStatementIdentifier, UseStatementPrefix,
|
||||||
|
VariableDeclaration, VariableUse,
|
||||||
|
};
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
use crate::name_analysis::symbol::source_definition::SourceDefinition;
|
||||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
|
use crate::name_analysis::symbol::{
|
||||||
|
GenericTypeSymbol, ParameterSymbol, PrimitiveTypeSymbol, TypeSymbol,
|
||||||
|
};
|
||||||
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||||
use crate::name_analysis::util::{handle_insert_error, handle_lookup_error, join_fqn_parts};
|
use crate::name_analysis::util::{
|
||||||
|
format_fqn, handle_insert_error, handle_lookup_error, join_fqn_parts,
|
||||||
|
};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn na_p2_compilation_unit(
|
pub fn na_p2_compilation_unit(
|
||||||
@ -149,9 +162,206 @@ fn na_p2_function(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
|
// change to this function's scope
|
||||||
|
symbol_table.set_current_scope(*function.scope_id().unwrap());
|
||||||
|
|
||||||
|
// generics
|
||||||
|
na_p2_generic_parameters(function.generics_mut(), symbol_table, diagnostics);
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
let parameter_symbols = na_p2_parameters(function.parameters_mut(), symbol_table, diagnostics);
|
||||||
|
function
|
||||||
|
.function_symbol()
|
||||||
|
.unwrap()
|
||||||
|
.borrow_mut()
|
||||||
|
.set_parameter_symbols(parameter_symbols);
|
||||||
|
|
||||||
|
// return type
|
||||||
|
let maybe_return_type_symbol =
|
||||||
|
na_p2_return_type(function.return_type_mut(), symbol_table, diagnostics);
|
||||||
|
if let Some(return_type_symbol) = maybe_return_type_symbol {
|
||||||
|
function
|
||||||
|
.function_symbol()
|
||||||
|
.unwrap()
|
||||||
|
.borrow_mut()
|
||||||
|
.set_return_type(return_type_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// push a scope for the body and check the body
|
||||||
|
symbol_table.push_scope(&format!(
|
||||||
|
"FunctionBodyScope {}",
|
||||||
|
function.identifier().name()
|
||||||
|
));
|
||||||
na_p2_function_body(function.function_body_mut(), symbol_table, diagnostics);
|
na_p2_function_body(function.function_body_mut(), symbol_table, diagnostics);
|
||||||
|
symbol_table.pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn na_p2_generic_parameters(
|
||||||
|
generic_parameters: &mut GenericParameters,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
for identifier in generic_parameters.identifier_list().identifiers() {
|
||||||
|
let generic_type_symbol = GenericTypeSymbol::new(
|
||||||
|
identifier.name(),
|
||||||
|
Some(SourceDefinition::from_identifier(identifier)),
|
||||||
|
);
|
||||||
|
match symbol_table.insert_generic_type_symbol(generic_type_symbol) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(symbol_insert_error) => {
|
||||||
|
handle_insert_error(
|
||||||
|
symbol_insert_error,
|
||||||
|
identifier.name(),
|
||||||
|
identifier.file_id(),
|
||||||
|
identifier.range(),
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_parameters(
|
||||||
|
parameters: &mut Parameters,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) -> Vec<Rc<RefCell<ParameterSymbol>>> {
|
||||||
|
parameters
|
||||||
|
.parameters_mut()
|
||||||
|
.map(|parameter| na_p2_parameter(parameter, symbol_table, diagnostics))
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_parameter(
|
||||||
|
parameter: &mut Parameter,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) -> Option<Rc<RefCell<ParameterSymbol>>> {
|
||||||
|
let parameter_type_symbol = na_p2_type_use(parameter.type_use_mut(), symbol_table, diagnostics);
|
||||||
|
let to_insert = ParameterSymbol::new(
|
||||||
|
parameter.identifier().name(),
|
||||||
|
Some(SourceDefinition::from_identifier(parameter.identifier())),
|
||||||
|
parameter_type_symbol,
|
||||||
|
);
|
||||||
|
match symbol_table.insert_parameter_symbol(to_insert) {
|
||||||
|
Ok(parameter_symbol) => Some(parameter_symbol),
|
||||||
|
Err(symbol_insert_error) => {
|
||||||
|
handle_insert_error(
|
||||||
|
symbol_insert_error,
|
||||||
|
parameter.identifier().name(),
|
||||||
|
parameter.identifier().file_id(),
|
||||||
|
parameter.identifier().range(),
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_return_type(
|
||||||
|
return_type: &mut ReturnType,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) -> Option<TypeSymbol> {
|
||||||
|
na_p2_type_use(return_type.type_use_mut(), symbol_table, diagnostics)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_type_use(
|
||||||
|
type_use: &mut TypeUse,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) -> Option<TypeSymbol> {
|
||||||
|
match type_use {
|
||||||
|
TypeUse::PrimitiveType(primitive_type) => {
|
||||||
|
Some(TypeSymbol::Primitive(match primitive_type {
|
||||||
|
PrimitiveType::Byte => PrimitiveTypeSymbol::Byte,
|
||||||
|
PrimitiveType::Short => PrimitiveTypeSymbol::Short,
|
||||||
|
PrimitiveType::Char => PrimitiveTypeSymbol::Char,
|
||||||
|
PrimitiveType::Int => PrimitiveTypeSymbol::Int,
|
||||||
|
PrimitiveType::Long => PrimitiveTypeSymbol::Long,
|
||||||
|
PrimitiveType::Double => PrimitiveTypeSymbol::Double,
|
||||||
|
PrimitiveType::Bool => PrimitiveTypeSymbol::Boolean,
|
||||||
|
PrimitiveType::String => PrimitiveTypeSymbol::String,
|
||||||
|
PrimitiveType::TypedArray(typed_array) => {
|
||||||
|
na_p2_typed_array(typed_array, symbol_table, diagnostics)
|
||||||
|
}
|
||||||
|
PrimitiveType::Any => PrimitiveTypeSymbol::Any,
|
||||||
|
PrimitiveType::Void => PrimitiveTypeSymbol::Void,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
TypeUse::InterfaceOrClassTypeUse(interface_or_class_type) => {
|
||||||
|
match interface_or_class_type.identifier_or_fqn() {
|
||||||
|
IdentifierOrFqn::Identifier(identifier) => {
|
||||||
|
match symbol_table.lookup_type(identifier.name()) {
|
||||||
|
Ok(type_symbol) => {
|
||||||
|
interface_or_class_type.set_type_symbol(type_symbol.clone());
|
||||||
|
Some(type_symbol)
|
||||||
|
}
|
||||||
|
Err(symbol_lookup_error) => {
|
||||||
|
handle_lookup_error(
|
||||||
|
symbol_lookup_error,
|
||||||
|
identifier.name(),
|
||||||
|
identifier.file_id(),
|
||||||
|
identifier.range(),
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IdentifierOrFqn::FullyQualifiedName(fqn) => {
|
||||||
|
let fqn_parts = fqn
|
||||||
|
.identifiers()
|
||||||
|
.map(Identifier::name)
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
match symbol_table.lookup_type_by_fqn(&fqn_parts) {
|
||||||
|
Ok(type_symbol) => {
|
||||||
|
interface_or_class_type.set_type_symbol(type_symbol.clone());
|
||||||
|
Some(type_symbol)
|
||||||
|
}
|
||||||
|
Err(symbol_lookup_error) => {
|
||||||
|
handle_lookup_error(
|
||||||
|
symbol_lookup_error,
|
||||||
|
&format_fqn(&fqn_parts),
|
||||||
|
fqn.file_id(),
|
||||||
|
fqn.range(),
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeUse::TupleTypeUse(tuple_type) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
TypeUse::FunctionTypeUse(function_type) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_typed_array(
|
||||||
|
typed_array: &mut TypedArray,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) -> PrimitiveTypeSymbol {
|
||||||
|
let inner_type_use = typed_array
|
||||||
|
.generic_arguments_mut()
|
||||||
|
.type_use_list_mut()
|
||||||
|
.type_uses_mut()
|
||||||
|
.next()
|
||||||
|
.unwrap();
|
||||||
|
let inner_type_symbol = na_p2_type_use(inner_type_use, symbol_table, diagnostics);
|
||||||
|
PrimitiveTypeSymbol::TypedArray {
|
||||||
|
inner_type: inner_type_symbol.map(Box::from),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// **Note:** caller needs to push a scope before calling.
|
||||||
fn na_p2_function_body(
|
fn na_p2_function_body(
|
||||||
function_body: &mut FunctionBody,
|
function_body: &mut FunctionBody,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
@ -161,7 +371,9 @@ fn na_p2_function_body(
|
|||||||
FunctionBody::FunctionAliasBody(alias_body) => {
|
FunctionBody::FunctionAliasBody(alias_body) => {
|
||||||
na_p2_function_alias_body(alias_body, symbol_table, diagnostics);
|
na_p2_function_alias_body(alias_body, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
FunctionBody::FunctionEqualsBody(equals_body) => {}
|
FunctionBody::FunctionEqualsBody(equals_body) => {
|
||||||
|
na_p2_function_equals_body(equals_body, symbol_table, diagnostics);
|
||||||
|
}
|
||||||
FunctionBody::FunctionBlockBody(block_body) => {
|
FunctionBody::FunctionBlockBody(block_body) => {
|
||||||
na_p2_function_block_body(block_body, symbol_table, diagnostics);
|
na_p2_function_block_body(block_body, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
@ -173,10 +385,8 @@ fn na_p2_function_alias_body(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
let maybe_function_symbol = symbol_table.lookup_function_symbol(
|
let maybe_function_symbol =
|
||||||
function_alias_body.identifier().name(),
|
symbol_table.lookup_function_symbol(function_alias_body.identifier().name());
|
||||||
*function_alias_body.scope_id().unwrap(),
|
|
||||||
);
|
|
||||||
match maybe_function_symbol {
|
match maybe_function_symbol {
|
||||||
Ok(function_symbol) => {
|
Ok(function_symbol) => {
|
||||||
function_alias_body.set_resolved_function_symbol(function_symbol);
|
function_alias_body.set_resolved_function_symbol(function_symbol);
|
||||||
@ -193,12 +403,23 @@ fn na_p2_function_alias_body(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn na_p2_function_equals_body(
|
||||||
|
function_equals_body: &mut FunctionEqualsBody,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
na_p2_expression(
|
||||||
|
function_equals_body.expression_mut(),
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn na_p2_function_block_body(
|
fn na_p2_function_block_body(
|
||||||
function_block_body: &mut FunctionBlockBody,
|
function_block_body: &mut FunctionBlockBody,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
symbol_table.set_current_scope(*function_block_body.scope_id().unwrap());
|
|
||||||
for statement in function_block_body.statements_mut() {
|
for statement in function_block_body.statements_mut() {
|
||||||
na_p2_statement(statement, symbol_table, diagnostics);
|
na_p2_statement(statement, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
@ -278,8 +499,16 @@ fn na_p2_assignment_statement(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
na_p2_l_value(assignment_statement.l_value_mut(), symbol_table, diagnostics);
|
na_p2_l_value(
|
||||||
na_p2_expression(assignment_statement.expression_mut(), symbol_table, diagnostics);
|
assignment_statement.l_value_mut(),
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
|
na_p2_expression(
|
||||||
|
assignment_statement.expression_mut(),
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn na_p2_l_value(
|
fn na_p2_l_value(
|
||||||
@ -288,7 +517,29 @@ fn na_p2_l_value(
|
|||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
na_p2_variable_use(l_value.variable_use_mut(), symbol_table, diagnostics);
|
na_p2_variable_use(l_value.variable_use_mut(), symbol_table, diagnostics);
|
||||||
// TODO: suffixes
|
// "Name analysis" of suffixes is done during type-checking. We don't want to deal with getting
|
||||||
|
// out the different potential return types of things until that point, especially if we end up
|
||||||
|
// adding dynamic objects to the language. However, suffixes may contain things (like arguments)
|
||||||
|
// which we do need to recurse into.
|
||||||
|
for l_value_suffix in l_value.suffixes_mut() {
|
||||||
|
na_p2_l_value_suffix(l_value_suffix, symbol_table, diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn na_p2_l_value_suffix(
|
||||||
|
l_value_suffix: &mut LValueSuffix,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
match l_value_suffix {
|
||||||
|
LValueSuffix::ObjectProperty(_) => {
|
||||||
|
// no-op; properties are checked during type-checking for soundness
|
||||||
|
}
|
||||||
|
LValueSuffix::ObjectIndex(object_index) => {
|
||||||
|
// check inner expression
|
||||||
|
na_p2_expression(object_index.expression_mut(), symbol_table, diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn na_p2_expression_statement(
|
fn na_p2_expression_statement(
|
||||||
@ -296,7 +547,11 @@ fn na_p2_expression_statement(
|
|||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
na_p2_expression(expression_statement.expression_mut(), symbol_table, diagnostics);
|
na_p2_expression(
|
||||||
|
expression_statement.expression_mut(),
|
||||||
|
symbol_table,
|
||||||
|
diagnostics,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn na_p2_variable_use(
|
fn na_p2_variable_use(
|
||||||
@ -370,25 +625,3 @@ fn na_p2_expression(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn na_p2_type_use(
|
|
||||||
type_use: &mut TypeUse,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
diagnostics: &mut Vec<DmDiagnostic>,
|
|
||||||
) {
|
|
||||||
match type_use {
|
|
||||||
TypeUse::PrimitiveType(primitive_type_use) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeUse::InterfaceOrClassTypeUse(interface_or_class_type_use) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeUse::TupleTypeUse(tuple_type_use) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
TypeUse::FunctionTypeUse(function_type_use) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,14 @@ impl ParameterSymbol {
|
|||||||
pub fn declared_name_owned(&self) -> Rc<str> {
|
pub fn declared_name_owned(&self) -> Rc<str> {
|
||||||
self.declared_name.clone()
|
self.declared_name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn type_symbol(&self) -> Option<&TypeSymbol> {
|
||||||
|
self.type_symbol.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_symbol_mut(&mut self) -> Option<&mut TypeSymbol> {
|
||||||
|
self.type_symbol.as_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol for ParameterSymbol {
|
impl Symbol for ParameterSymbol {
|
||||||
|
|||||||
@ -267,8 +267,8 @@ impl SymbolTable {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_function_symbol(&self, declared_name: &str, scope_id: usize) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolLookupError> {
|
pub fn lookup_function_symbol(&self, declared_name: &str) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolLookupError> {
|
||||||
let mut current_scope: Option<&Scope> = self.scopes.get(scope_id);
|
let mut current_scope: Option<&Scope> = Some(self.current_scope());
|
||||||
while let Some(scope) = current_scope.take() {
|
while let Some(scope) = current_scope.take() {
|
||||||
if let Some(function_symbol) = scope.find_function_symbol(declared_name) {
|
if let Some(function_symbol) = scope.find_function_symbol(declared_name) {
|
||||||
return Ok(function_symbol.clone());
|
return Ok(function_symbol.clone());
|
||||||
|
|||||||
@ -447,6 +447,12 @@ Function:
|
|||||||
node:
|
node:
|
||||||
or_else: void
|
or_else: void
|
||||||
- function_body
|
- function_body
|
||||||
|
fields:
|
||||||
|
- function_symbol:
|
||||||
|
kind: FunctionSymbol
|
||||||
|
wrap: rc_ref_cell
|
||||||
|
- scope_id:
|
||||||
|
kind: usize
|
||||||
OperatorFunction:
|
OperatorFunction:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
@ -609,9 +615,6 @@ FunctionEqualsBody:
|
|||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
- expression
|
- expression
|
||||||
fields:
|
|
||||||
- scope_id:
|
|
||||||
kind: usize
|
|
||||||
FunctionAliasBody:
|
FunctionAliasBody:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
@ -620,8 +623,6 @@ FunctionAliasBody:
|
|||||||
rule: Alias
|
rule: Alias
|
||||||
- identifier
|
- identifier
|
||||||
fields:
|
fields:
|
||||||
- scope_id:
|
|
||||||
kind: usize
|
|
||||||
- resolved_function_symbol:
|
- resolved_function_symbol:
|
||||||
kind: FunctionSymbol
|
kind: FunctionSymbol
|
||||||
wrap: rc_ref_cell
|
wrap: rc_ref_cell
|
||||||
@ -634,9 +635,6 @@ FunctionBlockBody:
|
|||||||
- end_kw:
|
- end_kw:
|
||||||
skip:
|
skip:
|
||||||
rule: End
|
rule: End
|
||||||
fields:
|
|
||||||
- scope_id:
|
|
||||||
kind: usize
|
|
||||||
|
|
||||||
# Class constructs
|
# Class constructs
|
||||||
ClassConstructor:
|
ClassConstructor:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user