Major refactor of name analysis and related.
This commit is contained in:
parent
dcb261fd84
commit
6b6ba1d712
@ -609,7 +609,7 @@ fn build_platform_function_declaration(
|
||||
Rule::FunctionModifier => {
|
||||
modifier = Some(build_function_modifier(file_id, inner_pair));
|
||||
}
|
||||
Rule::Platform | Rule::Fn => {},
|
||||
Rule::Platform | Rule::Fn => {}
|
||||
Rule::GenericParameters => {
|
||||
generics = build_generic_parameters(file_id, inner_pair);
|
||||
}
|
||||
@ -813,20 +813,20 @@ fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseSta
|
||||
))
|
||||
} else {
|
||||
last = Some(match inner_pair.as_rule() {
|
||||
Rule::Identifier => {
|
||||
UseStatementLast::Identifier(build_identifier(file_id, inner_pair))
|
||||
}
|
||||
Rule::Identifier => UseStatementLast::Identifier(Rc::new(RefCell::new(
|
||||
build_identifier(file_id, inner_pair),
|
||||
))),
|
||||
Rule::Star => UseStatementLast::Star,
|
||||
Rule::UseList => UseStatementLast::Identifiers(
|
||||
inner_pair
|
||||
.into_inner()
|
||||
.map(|identifier_pair| {
|
||||
expect_and_use(
|
||||
Rc::new(RefCell::new(expect_and_use(
|
||||
file_id,
|
||||
identifier_pair,
|
||||
Rule::Identifier,
|
||||
build_identifier,
|
||||
)
|
||||
)))
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
@ -842,7 +842,7 @@ fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseSta
|
||||
Range {
|
||||
start: as_span.start(),
|
||||
end: as_span.end(),
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,9 @@ use crate::ast::named::Named;
|
||||
use crate::name_analysis::symbol::Symbol;
|
||||
use pest::Parser;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::range::Range;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod build;
|
||||
pub mod named;
|
||||
@ -463,8 +465,11 @@ pub struct UseStatement {
|
||||
symbol: Option<Symbol>,
|
||||
}
|
||||
|
||||
/// First is declared_name, second is fully_qualified_name
|
||||
pub type UseStatementName = (String, String);
|
||||
pub struct UseStatementImport<'a> {
|
||||
pub declared_name: String,
|
||||
pub fqn: String,
|
||||
pub identifier: &'a mut Identifier,
|
||||
}
|
||||
|
||||
impl UseStatement {
|
||||
pub fn new(
|
||||
@ -504,28 +509,6 @@ impl UseStatement {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn names(&self) -> Vec<UseStatementName> {
|
||||
let base_name = self.base_name();
|
||||
use UseStatementLast::*;
|
||||
match &self.last {
|
||||
Identifier(identifier) => vec![(
|
||||
identifier.name().to_string(),
|
||||
base_name.to_string() + "::" + &identifier.name(),
|
||||
)],
|
||||
Identifiers(identifiers) => {
|
||||
let mut names = Vec::new();
|
||||
for identifier in identifiers {
|
||||
names.push((
|
||||
identifier.name().to_string(),
|
||||
base_name.to_string() + "::" + &identifier.name(),
|
||||
))
|
||||
}
|
||||
names
|
||||
}
|
||||
Star => panic!("Cannot call names() on a star UseStatement"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_star(&self) -> bool {
|
||||
match &self.last {
|
||||
UseStatementLast::Star => true,
|
||||
@ -552,8 +535,8 @@ impl UseStatement {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UseStatementLast {
|
||||
Identifier(Identifier),
|
||||
Identifiers(Vec<Identifier>),
|
||||
Identifier(Rc<RefCell<Identifier>>),
|
||||
Identifiers(Vec<Rc<RefCell<Identifier>>>),
|
||||
Star,
|
||||
}
|
||||
|
||||
|
@ -606,10 +606,10 @@ impl PrettyPrint for UseStatementLast {
|
||||
writer.writeln_indented("UseStatementLast")?;
|
||||
writer.increase_indent();
|
||||
match self {
|
||||
UseStatementLast::Identifier(i) => i.pretty_print(writer)?,
|
||||
UseStatementLast::Identifier(i) => i.borrow().pretty_print(writer)?,
|
||||
UseStatementLast::Identifiers(is) => {
|
||||
for i in is {
|
||||
i.pretty_print(writer)?;
|
||||
i.borrow().pretty_print(writer)?;
|
||||
}
|
||||
},
|
||||
UseStatementLast::Star => {
|
||||
|
@ -749,7 +749,7 @@ impl Unparse for UseStatementLast {
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
writer.write("{")?;
|
||||
for (i, identifier) in identifiers.iter().enumerate() {
|
||||
identifier.unparse(writer)?;
|
||||
identifier.borrow().unparse(writer)?;
|
||||
if i != identifiers.len() - 1 {
|
||||
writer.write(", ")?;
|
||||
}
|
||||
@ -757,7 +757,7 @@ impl Unparse for UseStatementLast {
|
||||
writer.write("}")?;
|
||||
Ok(())
|
||||
}
|
||||
UseStatementLast::Identifier(i) => i.unparse(writer),
|
||||
UseStatementLast::Identifier(i) => i.borrow().unparse(writer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,5 +6,6 @@ pub mod module;
|
||||
pub mod name_analysis;
|
||||
pub mod object_file;
|
||||
pub mod parser;
|
||||
mod std_core;
|
||||
pub mod util;
|
||||
pub mod vm;
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::ast::named::Named;
|
||||
use crate::ast::*;
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::fqn_context::FqnContext;
|
||||
use crate::name_analysis::symbol::*;
|
||||
use crate::name_analysis::symbol_table::{ScopeLevel, SymbolInsertError, SymbolTable};
|
||||
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use std::cell::RefCell;
|
||||
use std::range::Range;
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn handle_insert_error(
|
||||
err: SymbolInsertError,
|
||||
@ -17,25 +19,24 @@ fn handle_insert_error(
|
||||
) {
|
||||
match err {
|
||||
SymbolInsertError::SymbolAlreadyDefined(s) => {
|
||||
let already_defined_definition = s.definition();
|
||||
diagnostics.push(
|
||||
Diagnostic::error()
|
||||
.with_message(format!(
|
||||
"{} symbol '{}' already defined in the current scope.",
|
||||
symbol_types, error_symbol_name,
|
||||
))
|
||||
.with_label(
|
||||
Label::primary(error_file_id, error_range)
|
||||
.with_message("Symbol duplicated here."),
|
||||
)
|
||||
.with_label(
|
||||
Label::secondary(
|
||||
already_defined_definition.file_id(),
|
||||
already_defined_definition.range(),
|
||||
)
|
||||
let mut diagnostic = Diagnostic::error()
|
||||
.with_message(format!(
|
||||
"{} symbol '{}' already defined in the current scope.",
|
||||
symbol_types, error_symbol_name,
|
||||
))
|
||||
.with_label(
|
||||
Label::primary(error_file_id, error_range)
|
||||
.with_message("Symbol duplicated here."),
|
||||
);
|
||||
|
||||
if let Some(source_definition) = s.definition() {
|
||||
diagnostic = diagnostic.with_label(
|
||||
Label::secondary(source_definition.file_id(), source_definition.range())
|
||||
.with_message("Symbol defined here."),
|
||||
),
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,10 +129,7 @@ pub(super) fn gather_compilation_unit(
|
||||
fqn_context.push(namespace.name().to_string());
|
||||
}
|
||||
|
||||
symbol_table.push_scope(
|
||||
&format!("FileScope({})", compilation_unit.file_name),
|
||||
ScopeLevel::ModuleOrInterfaceOrClass,
|
||||
);
|
||||
symbol_table.push_scope(&format!("FileScope({})", compilation_unit.file_name));
|
||||
for use_statement in &mut compilation_unit.use_statements {
|
||||
gather_use_statement(use_statement, symbol_table, &mut fqn_context, diagnostics)
|
||||
}
|
||||
@ -142,6 +140,35 @@ pub(super) fn gather_compilation_unit(
|
||||
assert_eq!(symbol_table.current_scope_id(), 0);
|
||||
}
|
||||
|
||||
fn handle_use_statement_import(
|
||||
symbol_table: &mut SymbolTable,
|
||||
base_name: &str,
|
||||
identifier: Rc<RefCell<Identifier>>,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
let borrowed_identifier = identifier.borrow();
|
||||
let declared_name = borrowed_identifier.name().to_string();
|
||||
let insert_result = symbol_table.insert_use_statement_symbol(UseStatementSymbol::new(
|
||||
&format!("{}::{}", base_name, &declared_name),
|
||||
&declared_name,
|
||||
Some(identifier.clone()),
|
||||
));
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
err,
|
||||
&declared_name,
|
||||
borrowed_identifier.file_id,
|
||||
borrowed_identifier.range,
|
||||
"Use statement",
|
||||
diagnostics,
|
||||
);
|
||||
}
|
||||
drop(borrowed_identifier);
|
||||
identifier
|
||||
.borrow_mut()
|
||||
.set_scope_id(symbol_table.current_scope_id())
|
||||
}
|
||||
|
||||
fn gather_use_statement(
|
||||
use_statement: &mut UseStatement,
|
||||
symbol_table: &mut SymbolTable,
|
||||
@ -151,38 +178,23 @@ fn gather_use_statement(
|
||||
if use_statement.is_star() {
|
||||
todo!()
|
||||
}
|
||||
for (declared_name, fully_qualified_name) in use_statement.names() {
|
||||
let insert_result = symbol_table.insert(
|
||||
&declared_name,
|
||||
Symbol::UseStatement(UseStatementSymbol::new(
|
||||
&fully_qualified_name,
|
||||
&declared_name,
|
||||
SourceDefinition::from_use_statement(use_statement),
|
||||
)),
|
||||
);
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
err,
|
||||
&declared_name,
|
||||
use_statement.file_id,
|
||||
use_statement.range,
|
||||
"Use statement",
|
||||
diagnostics,
|
||||
);
|
||||
let base_name = use_statement.base_name().to_string();
|
||||
match &mut use_statement.last {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
handle_use_statement_import(symbol_table, &base_name, identifier.clone(), diagnostics)
|
||||
}
|
||||
match &mut use_statement.last {
|
||||
UseStatementLast::Identifier(identifier) => {
|
||||
identifier.set_scope_id(symbol_table.current_scope_id());
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
handle_use_statement_import(
|
||||
symbol_table,
|
||||
&base_name,
|
||||
identifier.clone(),
|
||||
diagnostics,
|
||||
)
|
||||
}
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
for identifier in identifiers {
|
||||
identifier.set_scope_id(symbol_table.current_scope_id());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
UseStatementLast::Star => panic!(),
|
||||
}
|
||||
use_statement.set_scope_id(symbol_table.current_scope_id());
|
||||
}
|
||||
|
||||
fn gather_module_level_declaration(
|
||||
@ -228,15 +240,12 @@ fn gather_module_declaration(
|
||||
|
||||
let module_name = declaration.identifier.name();
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_module_symbol(ModuleSymbol::new(
|
||||
&fqn_context.resolve(&module_name),
|
||||
&module_name,
|
||||
Symbol::Module(ModuleSymbol::new(
|
||||
&fqn_context.resolve(&module_name),
|
||||
&module_name,
|
||||
declaration.is_public,
|
||||
&declaration.identifier,
|
||||
)),
|
||||
);
|
||||
declaration.is_public,
|
||||
Some(&declaration.identifier),
|
||||
));
|
||||
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
@ -251,10 +260,7 @@ fn gather_module_declaration(
|
||||
|
||||
fqn_context.push(module_name.to_string());
|
||||
|
||||
symbol_table.push_scope(
|
||||
&format!("Module '{}' Scope", module_name),
|
||||
ScopeLevel::ModuleOrInterfaceOrClass,
|
||||
);
|
||||
symbol_table.push_scope(&format!("ModuleScope({})", module_name));
|
||||
for inner_declaration in &mut declaration.declarations {
|
||||
gather_module_level_declaration(inner_declaration, symbol_table, fqn_context, diagnostics);
|
||||
}
|
||||
@ -270,15 +276,12 @@ fn gather_class_declaration(
|
||||
let declared_name = class_declaration.identifier.name();
|
||||
let resolved_name = fqn_context.resolve(&declared_name);
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_type_symbol(TypeSymbol::new(
|
||||
&resolved_name,
|
||||
&declared_name,
|
||||
Symbol::Class(ClassSymbol::new(
|
||||
&resolved_name,
|
||||
&declared_name,
|
||||
class_declaration.is_public,
|
||||
&class_declaration.identifier,
|
||||
)),
|
||||
);
|
||||
class_declaration.is_public,
|
||||
Some(&class_declaration.identifier),
|
||||
));
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
err,
|
||||
@ -302,16 +305,13 @@ fn gather_function_definition(
|
||||
let declared_name = function.identifier.name();
|
||||
let resolved_name = fqn_context.resolve(&declared_name);
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
||||
&resolved_name,
|
||||
&declared_name,
|
||||
Symbol::Function(FunctionSymbol::new(
|
||||
&resolved_name,
|
||||
&declared_name,
|
||||
function.is_public,
|
||||
false,
|
||||
&function.identifier,
|
||||
)),
|
||||
);
|
||||
function.is_public,
|
||||
false,
|
||||
Some(&function.identifier),
|
||||
));
|
||||
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
@ -328,10 +328,7 @@ fn gather_function_definition(
|
||||
.identifier
|
||||
.set_scope_id(symbol_table.current_scope_id());
|
||||
|
||||
symbol_table.push_scope(
|
||||
&format!("FunctionScope({})", resolved_name),
|
||||
ScopeLevel::Function,
|
||||
);
|
||||
symbol_table.push_scope(&format!("FunctionScope({})", resolved_name));
|
||||
gather_parameters(
|
||||
&mut function.parameters,
|
||||
symbol_table,
|
||||
@ -351,16 +348,13 @@ fn gather_platform_function_definition(
|
||||
let declared_name = platform_function_declaration.identifier.name();
|
||||
let fully_qualified_name = fqn_context.resolve(&declared_name);
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_function_symbol(FunctionSymbol::new(
|
||||
&fully_qualified_name,
|
||||
&declared_name,
|
||||
Symbol::Function(FunctionSymbol::new(
|
||||
&fully_qualified_name,
|
||||
&declared_name,
|
||||
platform_function_declaration.is_public,
|
||||
true,
|
||||
&platform_function_declaration.identifier,
|
||||
)),
|
||||
);
|
||||
platform_function_declaration.is_public,
|
||||
true,
|
||||
Some(&platform_function_declaration.identifier),
|
||||
));
|
||||
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
@ -379,10 +373,7 @@ fn gather_platform_function_definition(
|
||||
.identifier
|
||||
.set_scope_id(symbol_table.current_scope_id());
|
||||
|
||||
symbol_table.push_scope(
|
||||
&format!("FunctionScope({})", declared_name_as_string),
|
||||
ScopeLevel::Function,
|
||||
);
|
||||
symbol_table.push_scope(&format!("FunctionScope({})", declared_name_as_string));
|
||||
gather_parameters(
|
||||
&mut platform_function_declaration.parameters,
|
||||
symbol_table,
|
||||
@ -411,14 +402,10 @@ fn gather_parameter(
|
||||
) {
|
||||
let parameter_name = parameter.identifier.name();
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_parameter_symbol(ParameterSymbol::new(
|
||||
¶meter_name,
|
||||
Symbol::Variable(VariableSymbol::new(
|
||||
¶meter_name,
|
||||
false,
|
||||
SourceDefinition::from_identifier(¶meter.identifier),
|
||||
)),
|
||||
);
|
||||
Some(¶meter.identifier),
|
||||
));
|
||||
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
@ -462,7 +449,7 @@ fn gather_block_statement(
|
||||
fqn_context: &mut FqnContext,
|
||||
diagnostics: &mut Vec<DmDiagnostic>,
|
||||
) {
|
||||
symbol_table.push_scope("BlockStatementScope", ScopeLevel::Function);
|
||||
symbol_table.push_scope("BlockStatementScope");
|
||||
gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics);
|
||||
symbol_table.pop_scope();
|
||||
}
|
||||
@ -512,14 +499,11 @@ fn gather_variable_declaration(
|
||||
) {
|
||||
let variable_name = variable_declaration.identifier.name();
|
||||
|
||||
let insert_result = symbol_table.insert(
|
||||
let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new(
|
||||
&variable_name,
|
||||
Symbol::Variable(VariableSymbol::new(
|
||||
&variable_name,
|
||||
variable_declaration.is_mutable,
|
||||
SourceDefinition::from_identifier(&variable_declaration.identifier),
|
||||
)),
|
||||
);
|
||||
variable_declaration.is_mutable,
|
||||
Some(&variable_declaration.identifier),
|
||||
));
|
||||
|
||||
if let Err(err) = insert_result {
|
||||
handle_insert_error(
|
||||
|
@ -35,6 +35,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::ast::build::build_ast;
|
||||
use crate::parser::{DeimosParser, Rule};
|
||||
use crate::std_core::add_std_core_symbols;
|
||||
use codespan_reporting::files::SimpleFiles;
|
||||
use codespan_reporting::term;
|
||||
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
||||
@ -61,6 +62,7 @@ mod tests {
|
||||
}
|
||||
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
add_std_core_symbols(&mut symbol_table).expect("Failed to add std_core_symbols");
|
||||
|
||||
let diagnostics = analyze_names(&mut compilation_units, &mut symbol_table);
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::ast::named::Named;
|
||||
use crate::ast::*;
|
||||
use crate::name_analysis::symbol_table::{SymbolLookupError, SymbolTable};
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
use crate::diagnostic::DmDiagnostic;
|
||||
use crate::name_analysis::symbol_table::SymbolTable;
|
||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||
|
||||
fn resolve_fully_qualified_name(
|
||||
fully_qualified_name: &mut FullyQualifiedName,
|
||||
@ -160,30 +160,11 @@ fn resolve_use_statement(
|
||||
if use_statement.is_star() {
|
||||
todo!()
|
||||
}
|
||||
for (_, fully_qualified_name) in use_statement.names() {
|
||||
let lookup_result = symbol_table.lookup_usable(
|
||||
&fully_qualified_name,
|
||||
use_statement
|
||||
.scope_id()
|
||||
.expect("UseStatement.scope_id was not set."),
|
||||
);
|
||||
match lookup_result {
|
||||
Ok(referenced_symbol) => {
|
||||
use_statement.set_symbol(referenced_symbol.clone());
|
||||
}
|
||||
Err(err) => match err {
|
||||
SymbolLookupError::NoDefinition => {
|
||||
diagnostics.push(
|
||||
Diagnostic::error()
|
||||
.with_message(&format!(
|
||||
"No definition found for symbol '{}'",
|
||||
fully_qualified_name
|
||||
))
|
||||
.with_label(Label::primary(use_statement.file_id, use_statement.range)),
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
match &use_statement.last {
|
||||
UseStatementLast::Identifier(identifier) => {}
|
||||
UseStatementLast::Identifiers(identifiers) => {}
|
||||
UseStatementLast::Star => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use std::cell::RefCell;
|
||||
use crate::ast::{Identifier, UseStatement};
|
||||
use std::fmt::Display;
|
||||
use std::range::Range;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SourceDefinition {
|
||||
@ -16,6 +18,15 @@ impl SourceDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@ -32,33 +43,50 @@ impl SourceDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SymbolInner {
|
||||
fn declared_name(&self) -> &str;
|
||||
fn definition(&self) -> &Option<SourceDefinition>;
|
||||
}
|
||||
|
||||
/* Symbol */
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Symbol {
|
||||
Function(FunctionSymbol),
|
||||
Variable(VariableSymbol),
|
||||
Module(ModuleSymbol),
|
||||
Class(ClassSymbol),
|
||||
UseStatement(UseStatementSymbol),
|
||||
UseStatement(Rc<UseStatementSymbol>),
|
||||
Module(Rc<ModuleSymbol>),
|
||||
Type(Rc<TypeSymbol>),
|
||||
Function(Rc<FunctionSymbol>),
|
||||
Parameter(Rc<ParameterSymbol>),
|
||||
Variable(Rc<VariableSymbol>),
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
Symbol::Function(s) => s.declared_name.as_str(),
|
||||
Symbol::Variable(s) => s.name.as_str(),
|
||||
Symbol::Module(s) => s.declared_name.as_str(),
|
||||
Symbol::Class(s) => s.declared_name.as_str(),
|
||||
Symbol::UseStatement(s) => s.declared_name.as_str(),
|
||||
Symbol::UseStatement(s) => s.declared_name(),
|
||||
Symbol::Module(s) => s.declared_name(),
|
||||
Symbol::Type(s) => s.declared_name(),
|
||||
Symbol::Function(s) => s.declared_name(),
|
||||
Symbol::Parameter(s) => s.declared_name(),
|
||||
Symbol::Variable(s) => s.declared_name(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn definition(&self) -> &SourceDefinition {
|
||||
pub fn definition(&self) -> &Option<SourceDefinition> {
|
||||
match self {
|
||||
Symbol::Function(s) => s.definition(),
|
||||
Symbol::Module(s) => s.definition(),
|
||||
Symbol::Variable(s) => s.definition(),
|
||||
Symbol::Class(s) => s.definition(),
|
||||
Symbol::UseStatement(s) => s.definition(),
|
||||
Symbol::Module(s) => s.definition(),
|
||||
Symbol::Type(s) => s.definition(),
|
||||
Symbol::Function(s) => s.definition(),
|
||||
Symbol::Parameter(s) => s.definition(),
|
||||
Symbol::Variable(s) => s.definition(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_use_statement_symbol(&self) -> &UseStatementSymbol {
|
||||
match self {
|
||||
Symbol::UseStatement(s) => s,
|
||||
_ => panic!("unwrap_use_statement_symbol called on non-use statement symbol"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -67,93 +95,74 @@ impl Display for Symbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use Symbol::*;
|
||||
match self {
|
||||
Function(function_symbol) => write!(f, "{}", function_symbol),
|
||||
Variable(variable_symbol) => write!(f, "{}", variable_symbol),
|
||||
Module(module_symbol) => write!(f, "{}", module_symbol),
|
||||
Class(class_symbol) => write!(f, "{}", class_symbol),
|
||||
UseStatement(use_statement_symbol) => write!(f, "{}", use_statement_symbol),
|
||||
Module(module_symbol) => write!(f, "{}", module_symbol),
|
||||
Type(class_symbol) => write!(f, "{}", class_symbol),
|
||||
Function(function_symbol) => write!(f, "{}", function_symbol),
|
||||
Parameter(parameter_symbol) => write!(f, "{}", parameter_symbol),
|
||||
Variable(variable_symbol) => write!(f, "{}", variable_symbol),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Use-statement */
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FunctionSymbol {
|
||||
pub struct UseStatementSymbol {
|
||||
pub fqn: String,
|
||||
pub declared_name: String,
|
||||
pub is_public: bool,
|
||||
pub is_platform: bool,
|
||||
definition: SourceDefinition,
|
||||
definition: Option<SourceDefinition>,
|
||||
referenced_symbol: Option<Box<Symbol>>
|
||||
}
|
||||
|
||||
impl FunctionSymbol {
|
||||
pub fn new(
|
||||
fqn: &str,
|
||||
declared_name: &str,
|
||||
is_public: bool,
|
||||
is_platform: bool,
|
||||
identifier: &Identifier,
|
||||
) -> FunctionSymbol {
|
||||
FunctionSymbol {
|
||||
impl UseStatementSymbol {
|
||||
pub fn new(fqn: &str, declared_name: &str, identifier: Option<Rc<RefCell<Identifier>>>) -> Self {
|
||||
UseStatementSymbol {
|
||||
fqn: fqn.to_string(),
|
||||
declared_name: declared_name.to_string(),
|
||||
is_public,
|
||||
is_platform,
|
||||
definition: SourceDefinition::from_identifier(identifier),
|
||||
definition: identifier.map(SourceDefinition::from_identifier_rc),
|
||||
referenced_symbol: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn definition(&self) -> &SourceDefinition {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FunctionSymbol {
|
||||
impl Display for UseStatementSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"FunctionSymbol(fqn = {}, declared_name = {}, is_public = {})",
|
||||
self.fqn, self.declared_name, self.is_public
|
||||
"UseStatementSymbol(fqn = {}, declared_name = {})",
|
||||
self.fqn, self.declared_name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VariableSymbol {
|
||||
pub name: String,
|
||||
pub is_mutable: bool,
|
||||
definition: SourceDefinition,
|
||||
}
|
||||
|
||||
impl VariableSymbol {
|
||||
pub fn new(name: &str, is_mutable: bool, definition: SourceDefinition) -> Self {
|
||||
VariableSymbol {
|
||||
name: name.to_string(),
|
||||
is_mutable,
|
||||
definition,
|
||||
}
|
||||
}
|
||||
/* Module */
|
||||
|
||||
pub fn definition(&self) -> &SourceDefinition {
|
||||
&self.definition
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for VariableSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VariableSymbol(name = {}, is_mutable = {})",
|
||||
self.name, self.is_mutable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug)]
|
||||
pub struct ModuleSymbol {
|
||||
pub fqn: String,
|
||||
pub declared_name: String,
|
||||
pub is_public: bool,
|
||||
definition: SourceDefinition,
|
||||
fqn: String,
|
||||
declared_name: String,
|
||||
is_public: bool,
|
||||
definition: Option<SourceDefinition>,
|
||||
}
|
||||
|
||||
impl ModuleSymbol {
|
||||
@ -161,17 +170,23 @@ impl ModuleSymbol {
|
||||
fqn: &str,
|
||||
declared_name: &str,
|
||||
is_public: bool,
|
||||
identifier: &Identifier,
|
||||
identifier: Option<&Identifier>,
|
||||
) -> ModuleSymbol {
|
||||
ModuleSymbol {
|
||||
fqn: fqn.to_string(),
|
||||
declared_name: declared_name.to_string(),
|
||||
is_public,
|
||||
definition: SourceDefinition::from_identifier(identifier),
|
||||
definition: identifier.map(SourceDefinition::from_identifier),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn definition(&self) -> &SourceDefinition {
|
||||
impl SymbolInner for ModuleSymbol {
|
||||
fn declared_name(&self) -> &str {
|
||||
self.declared_name.as_str()
|
||||
}
|
||||
|
||||
fn definition(&self) -> &Option<SourceDefinition> {
|
||||
&self.definition
|
||||
}
|
||||
}
|
||||
@ -186,76 +201,180 @@ impl Display for ModuleSymbol {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ClassSymbol {
|
||||
pub fqn: String,
|
||||
pub declared_name: String,
|
||||
pub is_public: bool,
|
||||
definition: SourceDefinition,
|
||||
/* Class */
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeSymbol {
|
||||
fqn: String,
|
||||
declared_name: String,
|
||||
is_public: bool,
|
||||
definition: Option<SourceDefinition>,
|
||||
}
|
||||
|
||||
impl ClassSymbol {
|
||||
pub fn new(fqn: &str, declared_name: &str, is_public: bool, identifier: &Identifier) -> Self {
|
||||
ClassSymbol {
|
||||
impl TypeSymbol {
|
||||
pub fn new(fqn: &str, declared_name: &str, is_public: bool, identifier: Option<&Identifier>) -> Self {
|
||||
TypeSymbol {
|
||||
fqn: fqn.to_string(),
|
||||
declared_name: declared_name.to_string(),
|
||||
is_public,
|
||||
definition: SourceDefinition::from_identifier(identifier),
|
||||
definition: identifier.map(SourceDefinition::from_identifier),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn definition(&self) -> &SourceDefinition {
|
||||
pub fn fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
|
||||
pub fn is_public(&self) -> bool {
|
||||
self.is_public
|
||||
}
|
||||
}
|
||||
|
||||
impl SymbolInner for TypeSymbol {
|
||||
fn declared_name(&self) -> &str {
|
||||
&self.declared_name
|
||||
}
|
||||
|
||||
fn definition(&self) -> &Option<SourceDefinition> {
|
||||
&self.definition
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ClassSymbol {
|
||||
impl Display for TypeSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ClassSymbol(fqn = {}, declared_name = {})",
|
||||
"TypeSymbol(fqn = {}, declared_name = {})",
|
||||
self.fqn, self.declared_name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UseStatementSymbol {
|
||||
pub fqn: String,
|
||||
pub declared_name: String,
|
||||
definition: SourceDefinition,
|
||||
referenced_symbol: Option<Box<Symbol>>
|
||||
/* Function */
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionSymbol {
|
||||
fqn: String,
|
||||
declared_name: String,
|
||||
is_public: bool,
|
||||
is_platform: bool,
|
||||
definition: Option<SourceDefinition>,
|
||||
}
|
||||
|
||||
impl UseStatementSymbol {
|
||||
pub fn new(fqn: &str, declared_name: &str, definition: SourceDefinition) -> Self {
|
||||
UseStatementSymbol {
|
||||
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(),
|
||||
definition,
|
||||
referenced_symbol: None,
|
||||
is_public,
|
||||
is_platform,
|
||||
definition: identifier.map(SourceDefinition::from_identifier),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn definition(&self) -> &SourceDefinition {
|
||||
&self.definition
|
||||
}
|
||||
|
||||
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()
|
||||
pub fn fqn(&self) -> &str {
|
||||
&self.fqn
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UseStatementSymbol {
|
||||
impl SymbolInner for FunctionSymbol {
|
||||
fn declared_name(&self) -> &str {
|
||||
self.declared_name.as_str()
|
||||
}
|
||||
|
||||
fn definition(&self) -> &Option<SourceDefinition> {
|
||||
&self.definition
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FunctionSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"UseStatementSymbol(fqn = {}, declared_name = {})",
|
||||
self.fqn, self.declared_name
|
||||
"FunctionSymbol(fqn = {}, declared_name = {}, is_public = {})",
|
||||
self.fqn, self.declared_name, self.is_public
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parameter */
|
||||
|
||||
#[derive(Debug)]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ParameterSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"ParameterSymbol({})",
|
||||
self.declared_name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/* Variable */
|
||||
|
||||
#[derive(Debug)]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for VariableSymbol {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"VariableSymbol(name = {}, is_mutable = {})",
|
||||
self.declared_name, self.is_mutable
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,94 +1,109 @@
|
||||
use crate::name_analysis::symbol::Symbol;
|
||||
use crate::name_analysis::symbol::{
|
||||
FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol,
|
||||
UseStatementSymbol, VariableSymbol,
|
||||
};
|
||||
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
|
||||
use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum ScopeLevel {
|
||||
Global,
|
||||
ModuleOrInterfaceOrClass,
|
||||
Function,
|
||||
}
|
||||
use std::rc::Rc;
|
||||
/* Scope */
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Scope {
|
||||
level: ScopeLevel,
|
||||
struct Scope {
|
||||
parent: Option<usize>,
|
||||
use_statement_symbols: HashMap<String, Symbol>,
|
||||
module_symbols: HashMap<String, Symbol>,
|
||||
type_symbols: HashMap<String, Symbol>,
|
||||
function_symbols: HashMap<String, Symbol>,
|
||||
variable_symbols: HashMap<String, Symbol>,
|
||||
use_statement_symbols: HashMap<String, Rc<UseStatementSymbol>>,
|
||||
module_symbols: HashMap<String, Rc<ModuleSymbol>>,
|
||||
type_symbols: HashMap<String, Rc<TypeSymbol>>,
|
||||
function_symbols: HashMap<String, Rc<FunctionSymbol>>,
|
||||
parameter_symbols: HashMap<String, Rc<ParameterSymbol>>,
|
||||
variable_symbols: HashMap<String, Rc<VariableSymbol>>,
|
||||
debug_name: String,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
pub fn new(parent: Option<usize>, debug_name: String, level: ScopeLevel) -> Scope {
|
||||
pub fn new(parent: Option<usize>, debug_name: String) -> Scope {
|
||||
Scope {
|
||||
level,
|
||||
parent,
|
||||
use_statement_symbols: HashMap::new(),
|
||||
module_symbols: HashMap::new(),
|
||||
type_symbols: HashMap::new(),
|
||||
function_symbols: HashMap::new(),
|
||||
parameter_symbols: HashMap::new(),
|
||||
variable_symbols: HashMap::new(),
|
||||
debug_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn level(&self) -> ScopeLevel {
|
||||
self.level.clone()
|
||||
fn get_any_symbol(&self, name: &str) -> Option<Symbol> {
|
||||
self.variable_symbols.get(name)
|
||||
.map(|s| Symbol::Variable(s.clone()))
|
||||
.or_else(|| self.parameter_symbols.get(name).map(|s| Symbol::Parameter(s.clone())))
|
||||
.or_else(|| self.function_symbols.get(name).map(|s| Symbol::Function(s.clone())))
|
||||
.or_else(|| self.type_symbols.get(name).map(|ts| Symbol::Type(ts.clone())))
|
||||
.or_else(|| self.module_symbols.get(name).map(|ms| Symbol::Module(ms.clone())))
|
||||
}
|
||||
|
||||
fn get_any_symbol(&self, name: &str) -> Option<&Symbol> {
|
||||
self.variable_symbols
|
||||
.get(name)
|
||||
.or_else(|| self.function_symbols.get(name))
|
||||
.or_else(|| self.type_symbols.get(name))
|
||||
.or_else(|| self.module_symbols.get(name))
|
||||
.or_else(|| self.use_statement_symbols.get(name))
|
||||
}
|
||||
|
||||
fn get_usable_symbol(&self, fqn: &str) -> Option<&Symbol> {
|
||||
for function_symbol in self.function_symbols.values() {
|
||||
match function_symbol {
|
||||
Symbol::Function(s) => {
|
||||
if s.fqn == fqn {
|
||||
return Some(function_symbol);
|
||||
}
|
||||
}
|
||||
_ => panic!("Cannot have non-function in function_symbols."),
|
||||
}
|
||||
}
|
||||
for type_symbol in self.type_symbols.values() {
|
||||
match type_symbol {
|
||||
Symbol::Class(s) => {
|
||||
if s.fqn == fqn {
|
||||
return Some(type_symbol);
|
||||
}
|
||||
}
|
||||
_ => panic!("Cannot have non-class in type_symbols."),
|
||||
fn get_module_symbol_by_declared_name(&self, name: &str) -> Option<Rc<ModuleSymbol>> {
|
||||
for module_symbol in self.module_symbols.values() {
|
||||
if module_symbol.declared_name() == name {
|
||||
return Some(module_symbol.clone());
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn symbols(&self) -> Vec<&Symbol> {
|
||||
let mut symbols: Vec<&Symbol> = Vec::new();
|
||||
symbols.extend(self.use_statement_symbols.values());
|
||||
symbols.extend(self.module_symbols.values());
|
||||
symbols.extend(self.type_symbols.values());
|
||||
symbols.extend(self.function_symbols.values());
|
||||
symbols.extend(self.variable_symbols.values());
|
||||
symbols
|
||||
fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option<Symbol> {
|
||||
for function_symbol in self.function_symbols.values() {
|
||||
if function_symbol.fqn() == fqn {
|
||||
return Some(Symbol::Function(function_symbol.clone()));
|
||||
}
|
||||
}
|
||||
for type_symbol in self.type_symbols.values() {
|
||||
if type_symbol.fqn() == fqn {
|
||||
return Some(Symbol::Type(type_symbol.clone()));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
|
||||
for function_symbol in self.function_symbols.values() {
|
||||
if function_symbol.declared_name() == declared_name {
|
||||
return Some(Symbol::Function(function_symbol.clone()));
|
||||
}
|
||||
}
|
||||
for type_symbol in self.type_symbols.values() {
|
||||
if type_symbol.declared_name() == declared_name {
|
||||
return Some(Symbol::Type(type_symbol.clone()));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_value_symbol_by_declared_name(&self, declared_name: &str) -> Option<Symbol> {
|
||||
for variable_symbol in self.variable_symbols.values() {
|
||||
if variable_symbol.declared_name() == declared_name {
|
||||
return Some(Symbol::Variable(variable_symbol.clone()));
|
||||
}
|
||||
}
|
||||
for parameter_symbol in self.parameter_symbols.values() {
|
||||
if parameter_symbol.declared_name() == declared_name {
|
||||
return Some(Symbol::Parameter(parameter_symbol.clone()));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/* Symbol table */
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SymbolInsertError {
|
||||
SymbolAlreadyDefined(Symbol),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SymbolLookupError {
|
||||
NoDefinition,
|
||||
}
|
||||
@ -103,11 +118,7 @@ pub struct SymbolTable {
|
||||
impl SymbolTable {
|
||||
pub fn new() -> Self {
|
||||
let mut t = SymbolTable {
|
||||
scopes: vec![Scope::new(
|
||||
None,
|
||||
String::from("GlobalScope"),
|
||||
ScopeLevel::Global,
|
||||
)],
|
||||
scopes: vec![Scope::new(None, String::from("GlobalScope"))],
|
||||
current_scope_id: 0,
|
||||
};
|
||||
t
|
||||
@ -121,12 +132,11 @@ impl SymbolTable {
|
||||
&self.scopes
|
||||
}
|
||||
|
||||
pub fn push_scope(&mut self, debug_name: &str, level: ScopeLevel) {
|
||||
pub fn push_scope(&mut self, debug_name: &str) {
|
||||
let id = self.scopes.len();
|
||||
self.scopes.push(Scope::new(
|
||||
Some(self.current_scope_id),
|
||||
debug_name.to_string(),
|
||||
level,
|
||||
));
|
||||
self.current_scope_id = id;
|
||||
}
|
||||
@ -137,65 +147,112 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, name: &str, symbol: Symbol) -> Result<(), SymbolInsertError> {
|
||||
match symbol {
|
||||
Symbol::Function(_) | Symbol::Variable(_) => {
|
||||
self.insert_function_or_variable(name, symbol)
|
||||
}
|
||||
Symbol::Module(_) | Symbol::Class(_) => self.insert_module_or_type(name, symbol),
|
||||
Symbol::UseStatement(_) => self.insert_use_statement_symbol(name, symbol),
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_function_or_variable(
|
||||
pub fn insert_use_statement_symbol(
|
||||
&mut self,
|
||||
name: &str,
|
||||
symbol: Symbol,
|
||||
use_statement_symbol: UseStatementSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) = self.scopes[self.current_scope_id]
|
||||
.function_symbols
|
||||
.get(name)
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
self.scopes[self.current_scope_id]
|
||||
.function_symbols
|
||||
.insert(name.to_string(), symbol);
|
||||
current_scope.use_statement_symbols.insert(
|
||||
use_statement_symbol.declared_name().to_string(),
|
||||
Rc::new(use_statement_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_module_or_type(
|
||||
pub fn insert_module_symbol(
|
||||
&mut self,
|
||||
name: &str,
|
||||
symbol: Symbol,
|
||||
module_symbol: ModuleSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) = self.scopes[self.current_scope_id].type_symbols.get(name) {
|
||||
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_module_symbol_by_declared_name(module_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(Symbol::Module(defined_symbol.clone())))
|
||||
} else {
|
||||
self.scopes[self.current_scope_id]
|
||||
.type_symbols
|
||||
.insert(name.to_string(), symbol);
|
||||
current_scope.module_symbols.insert(
|
||||
module_symbol.declared_name().to_string(),
|
||||
Rc::new(module_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_use_statement_symbol(
|
||||
pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> {
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_usable_symbol_by_declared_name(type_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
current_scope.type_symbols.insert(
|
||||
type_symbol.declared_name().to_string(),
|
||||
Rc::new(type_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_function_symbol(
|
||||
&mut self,
|
||||
name: &str,
|
||||
symbol: Symbol,
|
||||
function_symbol: FunctionSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
if let Some(defined_symbol) = self.scopes[self.current_scope_id].get_any_symbol(name) {
|
||||
Err(SymbolAlreadyDefined(defined_symbol.clone()))
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
self.scopes[self.current_scope_id]
|
||||
.use_statement_symbols
|
||||
.insert(name.to_string(), symbol);
|
||||
current_scope.function_symbols.insert(
|
||||
function_symbol.declared_name().to_string(),
|
||||
Rc::new(function_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &str, scope_id: usize) -> Result<&Symbol, SymbolLookupError> {
|
||||
pub fn insert_parameter_symbol(
|
||||
&mut self,
|
||||
parameter_symbol: ParameterSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
current_scope.parameter_symbols.insert(
|
||||
parameter_symbol.declared_name().to_string(),
|
||||
Rc::new(parameter_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_variable_symbol(
|
||||
&mut self,
|
||||
variable_symbol: VariableSymbol,
|
||||
) -> Result<(), SymbolInsertError> {
|
||||
let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap();
|
||||
if let Some(defined_symbol) =
|
||||
current_scope.get_value_symbol_by_declared_name(variable_symbol.declared_name())
|
||||
{
|
||||
Err(SymbolAlreadyDefined(defined_symbol))
|
||||
} else {
|
||||
current_scope.variable_symbols.insert(
|
||||
variable_symbol.declared_name().to_string(),
|
||||
Rc::new(variable_symbol),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup(&self, name: &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) = scope.get_any_symbol(name) {
|
||||
@ -210,16 +267,13 @@ impl SymbolTable {
|
||||
Err(NoDefinition)
|
||||
}
|
||||
|
||||
pub fn lookup_usable(
|
||||
pub fn lookup_usable_by_fqn(
|
||||
&self,
|
||||
fully_qualified_name: &str,
|
||||
scope_id: usize,
|
||||
) -> Result<&Symbol, SymbolLookupError> {
|
||||
) -> Result<Symbol, SymbolLookupError> {
|
||||
for scope in &self.scopes {
|
||||
if scope.level == ScopeLevel::Function {
|
||||
continue;
|
||||
}
|
||||
if let Some(symbol) = scope.get_usable_symbol(fully_qualified_name) {
|
||||
if let Some(symbol) = scope.get_usable_symbol_by_fqn(fully_qualified_name) {
|
||||
return Ok(symbol);
|
||||
}
|
||||
}
|
||||
|
27
src/std_core/mod.rs
Normal file
27
src/std_core/mod.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::name_analysis::symbol::{FunctionSymbol, Symbol, TypeSymbol};
|
||||
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
|
||||
pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
|
||||
symbol_table.insert_type_symbol(
|
||||
TypeSymbol::new("std::core:Array", "Array", true, None),
|
||||
)?;
|
||||
symbol_table.insert_function_symbol(
|
||||
FunctionSymbol::new(
|
||||
"std::core::println",
|
||||
"println",
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
),
|
||||
)?;
|
||||
symbol_table.insert_function_symbol(
|
||||
FunctionSymbol::new(
|
||||
"std::core::print",
|
||||
"print",
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
),
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user