Resolve local variables.
This commit is contained in:
parent
dd249dd5bd
commit
34fae6ccca
@ -7,8 +7,8 @@ fn getWorlds() -> List<World> = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
fn findWorldByColor(worlds: List<World>, color: String) -> String
|
fn findWorldByColor(worlds: List<World>, color: String) -> String
|
||||||
worlds.find { it.color == color }
|
worlds.find { it -> it.color == color }
|
||||||
.map { it.name }
|
.map { it -> it.name }
|
||||||
.expect "No world has the given color ${color}"
|
.expect "No world has the given color ${color}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ use crate::name_analysis::symbol::type_symbol::{
|
|||||||
};
|
};
|
||||||
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
|
||||||
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
|
||||||
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolLookupError, SymbolTable};
|
||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
use std::range::Range;
|
use std::range::Range;
|
||||||
|
|
||||||
@ -56,6 +56,29 @@ fn handle_insert_error(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_lookup_error(
|
||||||
|
err: SymbolLookupError,
|
||||||
|
error_symbol_name: &str,
|
||||||
|
error_file_id: usize,
|
||||||
|
error_range: Range<usize>,
|
||||||
|
symbol_types: &str,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
match err {
|
||||||
|
SymbolLookupError::NoDefinition => {
|
||||||
|
let diagnostic = Diagnostic::error()
|
||||||
|
.with_message(format!(
|
||||||
|
"No such {} symbol '{}' in scope.",
|
||||||
|
symbol_types, error_symbol_name,
|
||||||
|
))
|
||||||
|
.with_label(
|
||||||
|
Label::primary(error_file_id, error_range).with_message("Symbol used here."),
|
||||||
|
);
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn gather_node_children<'a>(
|
fn gather_node_children<'a>(
|
||||||
node: &'a dyn AstNode<'a>,
|
node: &'a dyn AstNode<'a>,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
@ -244,11 +267,8 @@ fn gather_node<'a>(
|
|||||||
diagnostics,
|
diagnostics,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AstNodeRef::LValue(l_value) => {
|
|
||||||
gather_node_children(l_value, symbol_table, fqn_context, scope_table, diagnostics);
|
|
||||||
}
|
|
||||||
AstNodeRef::VariableUse(variable_use) => {
|
AstNodeRef::VariableUse(variable_use) => {
|
||||||
gather_variable_use(variable_use, symbol_table, scope_table);
|
gather_variable_use(variable_use, symbol_table, diagnostics);
|
||||||
}
|
}
|
||||||
AstNodeRef::TernaryExpression(ternary_expression) => {
|
AstNodeRef::TernaryExpression(ternary_expression) => {
|
||||||
gather_ternary_expression(
|
gather_ternary_expression(
|
||||||
@ -1234,9 +1254,21 @@ fn gather_for_statement<'a>(
|
|||||||
fn gather_variable_use<'a>(
|
fn gather_variable_use<'a>(
|
||||||
variable_use: &'a VariableUse,
|
variable_use: &'a VariableUse,
|
||||||
symbol_table: &mut SymbolTable,
|
symbol_table: &mut SymbolTable,
|
||||||
scope_table: &mut ScopeTable<'a>,
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
) {
|
) {
|
||||||
scope_table.insert_variable_use_scope(variable_use, symbol_table.current_scope_id());
|
if let Err(lookup_error) = symbol_table.lookup_addressable_by_identifier(
|
||||||
|
variable_use.identifier().name(),
|
||||||
|
symbol_table.current_scope_id(),
|
||||||
|
) {
|
||||||
|
handle_lookup_error(
|
||||||
|
lookup_error,
|
||||||
|
variable_use.identifier().name(),
|
||||||
|
variable_use.identifier().file_id(),
|
||||||
|
variable_use.identifier().range(),
|
||||||
|
"Variable",
|
||||||
|
diagnostics,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_ternary_expression<'a>(
|
fn gather_ternary_expression<'a>(
|
||||||
|
|||||||
@ -45,8 +45,11 @@ impl SymbolTable {
|
|||||||
|
|
||||||
pub fn push_scope(&mut self, debug_name: &str) {
|
pub fn push_scope(&mut self, debug_name: &str) {
|
||||||
let id = self.scopes.len();
|
let id = self.scopes.len();
|
||||||
self.scopes
|
self.scopes.push(Scope::new(
|
||||||
.push(Scope::new(Some(self.current_scope_id), id, debug_name.to_string()));
|
Some(self.current_scope_id),
|
||||||
|
id,
|
||||||
|
debug_name.to_string(),
|
||||||
|
));
|
||||||
self.current_scope_id = id;
|
self.current_scope_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +319,61 @@ impl SymbolTable {
|
|||||||
Some(&self.scopes[parent_id])
|
Some(&self.scopes[parent_id])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Err(NoDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lookup_addressable_in_scope_by_identifier(
|
||||||
|
scope: &Scope,
|
||||||
|
identifier: &str,
|
||||||
|
) -> Option<Symbol> {
|
||||||
|
scope
|
||||||
|
.variable_symbols()
|
||||||
|
.get(identifier)
|
||||||
|
.map(|variable_symbol| Symbol::Variable(variable_symbol.clone()))
|
||||||
|
.or_else(|| {
|
||||||
|
scope
|
||||||
|
.parameter_symbols()
|
||||||
|
.get(identifier)
|
||||||
|
.map(|parameter_symbol| Symbol::Parameter(parameter_symbol.clone()))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
scope
|
||||||
|
.class_member_symbols()
|
||||||
|
.get(identifier)
|
||||||
|
.map(|class_member_symbol| Symbol::ClassMember(class_member_symbol.clone()))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
scope
|
||||||
|
.function_symbols()
|
||||||
|
.get(identifier)
|
||||||
|
.map(|function_symbol| Symbol::Function(function_symbol.clone()))
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
scope
|
||||||
|
.type_symbols()
|
||||||
|
.get(identifier)
|
||||||
|
.map(|type_symbol| Symbol::Type(type_symbol.clone()))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_addressable_by_identifier(
|
||||||
|
&self,
|
||||||
|
identifier: &str,
|
||||||
|
scope_id: usize,
|
||||||
|
) -> Result<Symbol, SymbolLookupError> {
|
||||||
|
let mut scope_opt = Some(&self.scopes[scope_id]);
|
||||||
|
while let Some(scope) = scope_opt {
|
||||||
|
if let Some(symbol) = Self::lookup_addressable_in_scope_by_identifier(scope, identifier)
|
||||||
|
{
|
||||||
|
return Ok(symbol);
|
||||||
}
|
}
|
||||||
|
scope_opt = if let Some(parent_id) = scope.parent() {
|
||||||
|
Some(&self.scopes[parent_id])
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Err(NoDefinition)
|
Err(NoDefinition)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user