Compare commits

..

No commits in common. "13330300c1a744b58d88a8564a2a353fa6868063" and "5721bd1e83198d67654a1d2694d1da5eae6f244d" have entirely different histories.

20 changed files with 363 additions and 986 deletions

View File

@ -116,7 +116,8 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
use std::range::Range; use std::range::Range;
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use crate::name_analysis::symbol::*; use crate::name_analysis::symbol::type_symbol::*;
use crate::name_analysis::symbol::use_symbol::*;
#(#types)* #(#types)*
}; };

View File

@ -79,9 +79,9 @@ pub mod build {
include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs")); include!(concat!(env!("OUT_DIR"), "/src/ast/build.rs"));
pub fn build_ast(file_id: usize, parsed_pairs: &mut Pairs<Rule>) -> CompilationUnit { pub fn build_ast(file_id: usize, parsed_pairs: &mut Pairs<Rule>) -> Box<CompilationUnit> {
let compilation_unit_pair = parsed_pairs.next().unwrap(); let compilation_unit_pair = parsed_pairs.next().unwrap();
build_compilation_unit(file_id, compilation_unit_pair) Box::new(build_compilation_unit(file_id, compilation_unit_pair))
} }
#[cfg(test)] #[cfg(test)]
@ -174,6 +174,22 @@ pub mod pretty_print {
pub mod ast_node { pub mod ast_node {
include!(concat!(env!("OUT_DIR"), "/src/ast/ast_node.rs")); include!(concat!(env!("OUT_DIR"), "/src/ast/ast_node.rs"));
#[cfg(test)]
mod tests {
use crate::ast::ast_node::AstNode;
use crate::ast::node::CompilationUnit;
fn get_cu() -> CompilationUnit {
todo!()
}
#[test]
fn simple() {
let cu = get_cu();
for child in cu.children() {}
}
}
} }
pub mod walk { pub mod walk {

View File

@ -3,69 +3,40 @@ use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use deimos::ast::build::build_ast; use deimos::ast::build::build_ast;
use deimos::name_analysis::analyze_names; use deimos::name_analysis::analyze_names;
use deimos::name_analysis::symbol_table::symbol_tree::SymbolTree;
use deimos::name_analysis::symbol_table::SymbolTable; use deimos::name_analysis::symbol_table::SymbolTable;
use deimos::parser::{DeimosParser, Rule}; use deimos::parser::{DeimosParser, Rule};
use deimos::std_core::add_std_core_symbols; use deimos::std_core::add_std_core_symbols;
use pest::Parser; use pest::Parser;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use std::path::PathBuf; use std::path::PathBuf;
struct ParseErrors { pub fn name_analysis(paths: &Vec<PathBuf>) -> Result<(), Box<dyn std::error::Error>> {
errors: Vec<pest::error::Error<Rule>>, let mut compilation_units = vec![];
} let mut files: SimpleFiles<String, String> = SimpleFiles::new();
impl Debug for ParseErrors {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(self, f)
}
}
impl Display for ParseErrors {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
writeln!(f, "There were errors during parsing.")?;
for parse_error in &self.errors {
writeln!(f, "{}", parse_error)?;
}
Ok(())
}
}
impl std::error::Error for ParseErrors {}
pub fn name_analysis(paths: &[PathBuf]) -> Result<(), Box<dyn std::error::Error>> {
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
for path in paths { for path in paths {
let src = std::fs::read_to_string(path).unwrap(); let src = std::fs::read_to_string(path).unwrap();
paths_and_sources.insert(path.display().to_string(), src); let parse_result = DeimosParser::parse(Rule::CompilationUnit, &src);
} let file_id = files.add(path.display().to_string(), src.clone()); // I don't love this clone
let mut compilation_units = vec![];
let mut files: SimpleFiles<&str, &str> = SimpleFiles::new();
let mut parse_errors = vec![];
for (path, source) in &paths_and_sources {
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
match parse_result { match parse_result {
Ok(mut pairs) => { Ok(mut pairs) => {
let file_id = files.add(path, source);
let compilation_unit = build_ast(file_id, &mut pairs); let compilation_unit = build_ast(file_id, &mut pairs);
compilation_units.push(compilation_unit); compilation_units.push(compilation_unit);
Ok::<(), Box<dyn std::error::Error>>(())
} }
Err(error) => { Err(e) => Err(e.into()),
parse_errors.push(error); }?;
}
}
}
if !parse_errors.is_empty() {
return Err(Box::new(ParseErrors { errors: parse_errors }));
} }
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table); let diagnostics = analyze_names(
&mut compilation_units,
&files,
&mut symbol_table,
);
if diagnostics.is_empty() { if diagnostics.is_empty() {
println!("Name analysis complete."); println!("Name analysis complete.");
println!("{}", symbol_table); println!("{}", symbol_table);

View File

@ -1,8 +1,8 @@
use crate::ast::node::{ use crate::ast::node::{
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody, CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Function, FunctionBody,
GenericParameters, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration, Parameter, GenericParameters, Identifier, IdentifierOrFqn, Module, ModuleLevelDeclaration, Parameters,
Parameters, PrimitiveType, ReturnType, StarUseStatement, TypeUse, TypedArray, UseStatement, PrimitiveType, ReturnType, TypeUse, TypedArray, UseStatement, UseStatementIdentifier,
UseStatementIdentifier, UseStatementPrefix, 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;
@ -13,13 +13,10 @@ use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::primitive_type_symbol::PrimitiveTypeSymbol; 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::type_symbol::TypeSymbol;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; use crate::name_analysis::symbol::use_symbol::ConcreteUseSymbol;
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};
format_fqn, handle_insert_error, handle_lookup_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(
@ -63,7 +60,7 @@ fn na_p1_use_statement(
na_p1_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics); na_p1_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics);
} }
UseStatement::StarUseStatement(star_use_statement) => { UseStatement::StarUseStatement(star_use_statement) => {
na_p1_star_use_statement(star_use_statement, symbol_table, diagnostics); todo!()
} }
} }
} }
@ -103,7 +100,7 @@ fn na_p1_concrete_use_statement(
} }
fn handle_concrete_use_statement_identifier( fn handle_concrete_use_statement_identifier(
prefixes: &[Rc<str>], prefixes: &Vec<Rc<str>>,
use_statement_identifier: &mut UseStatementIdentifier, use_statement_identifier: &mut UseStatementIdentifier,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
@ -137,40 +134,6 @@ fn handle_concrete_use_statement_identifier(
} }
} }
fn na_p1_star_use_statement(
star_use_statement: &mut StarUseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let fqn_parts = star_use_statement
.prefixes()
.map(UseStatementPrefix::identifier)
.map(Identifier::name)
.map(|name| Rc::from(name))
.collect::<Vec<Rc<str>>>();
let to_insert = StarUseSymbol::new(
&fqn_parts,
Some(SourceDefinition::from_star_use_statement(
star_use_statement,
)),
);
match symbol_table.insert_star_use_symbol(to_insert) {
Ok(star_use_symbol) => {
star_use_statement.set_symbol(star_use_symbol);
}
Err(symbol_insert_error) => {
handle_insert_error(
symbol_insert_error,
&join_fqn_parts(&fqn_parts),
star_use_statement.file_id(),
star_use_statement.range(),
diagnostics,
);
}
}
}
fn na_p1_module_level_declaration( fn na_p1_module_level_declaration(
module_level_declaration: &mut ModuleLevelDeclaration, module_level_declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
@ -244,6 +207,8 @@ fn na_p1_function(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) -> Option<Rc<RefCell<FunctionSymbol>>> { ) -> Option<Rc<RefCell<FunctionSymbol>>> {
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
let to_insert = FunctionSymbol::new( let to_insert = FunctionSymbol::new(
&symbol_table.resolve_fqn(Rc::from(function.identifier().name())), &symbol_table.resolve_fqn(Rc::from(function.identifier().name())),
function.is_public(), function.is_public(),
@ -251,7 +216,28 @@ fn na_p1_function(
Some(SourceDefinition::from_identifier(function.identifier())), Some(SourceDefinition::from_identifier(function.identifier())),
); );
let function_symbol = match symbol_table.insert_function_symbol(to_insert) { let function_symbol = match symbol_table.insert_function_symbol(to_insert) {
Ok(function_symbol) => Some(function_symbol), Ok(function_symbol) => {
{
let mut as_ref_mut = function_symbol.borrow_mut();
// 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);
}
}
Some(function_symbol)
}
Err(symbol_insert_error) => { Err(symbol_insert_error) => {
handle_insert_error( handle_insert_error(
symbol_insert_error, symbol_insert_error,
@ -264,42 +250,7 @@ fn na_p1_function(
} }
}; };
if function_symbol.is_some() {
let mut as_ref_mut = function_symbol.as_ref().unwrap().borrow_mut();
// push a scope for this function
symbol_table.push_scope(&format!("FunctionScope {}", function.identifier().name()));
// 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 function_symbol
} }
@ -309,38 +260,7 @@ fn na_p1_parameters(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) -> Vec<Rc<RefCell<ParameterSymbol>>> { ) -> Vec<Rc<RefCell<ParameterSymbol>>> {
parameters todo!()
.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( fn na_p1_return_type(
@ -474,22 +394,5 @@ fn na_p1_function_body(
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match function_body { todo!()
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());
}
}
} }

View File

@ -36,11 +36,8 @@ pub mod symbol;
pub mod symbol_table; pub mod symbol_table;
mod util; mod util;
pub fn analyze_names< pub fn analyze_names<'a, F: Files<'a, FileId = usize, Name = String>>(
'a, compilation_units: &mut Vec<Box<CompilationUnit>>,
F: Files<'a, FileId = usize, Name = &'a str, Source = &'a str> + ?Sized,
>(
compilation_units: &mut Vec<CompilationUnit>,
files: &'a F, files: &'a F,
symbol_table: &mut SymbolTable, symbol_table: &mut SymbolTable,
) -> Vec<DmDiagnostic> { ) -> Vec<DmDiagnostic> {
@ -49,11 +46,7 @@ pub fn analyze_names<
// gather symbols // gather symbols
for compilation_unit in compilation_units.iter_mut() { for compilation_unit in compilation_units.iter_mut() {
let file_name = files.name(compilation_unit.file_id()).unwrap(); let file_name = files.name(compilation_unit.file_id()).unwrap();
na_p1_compilation_unit(file_name, compilation_unit, symbol_table, &mut diagnostics); na_p1_compilation_unit(&file_name, compilation_unit, symbol_table, &mut diagnostics);
}
if !diagnostics.is_empty() {
return diagnostics;
} }
// resolve symbols // resolve symbols
@ -61,160 +54,221 @@ pub fn analyze_names<
na_p2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics); na_p2_compilation_unit(compilation_unit, symbol_table, &mut diagnostics);
} }
diagnostics diagnostics.into()
} }
#[cfg(test)] // #[cfg(test)]
mod tests { // mod tests {
use super::*; // use super::*;
use crate::ast::build::build_ast; // use crate::ast::build::build_ast;
use crate::parser::{DeimosParser, Rule}; // use crate::ast::children::NodeRef;
use crate::std_core::add_std_core_symbols; // use crate::ast::walk::walk_depth_first;
use codespan_reporting::files::SimpleFiles; // use crate::parser::{DeimosParser, Rule};
use codespan_reporting::term; // use crate::std_core::add_std_core_symbols;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; // use codespan_reporting::files::SimpleFiles;
use pest::Parser; // use codespan_reporting::term;
use std::collections::HashMap; // use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use std::rc::Rc; // use indoc::indoc;
use crate::name_analysis::symbol::use_symbol::StarUseSymbol; // use pest::Parser;
// use std::collections::HashMap;
fn parse_compilation_units<'a>( //
files: &mut SimpleFiles<&'a str, &'a str>, // fn assert_number_of_diagnostics(
sources: HashMap<&'a str, &'a str>, // sources: HashMap<&str, &str>,
) -> Vec<CompilationUnit> { // symbol_table: &mut SymbolTable,
let mut compilation_units: Vec<CompilationUnit> = vec![]; // n_diagnostics: usize,
// ) -> Vec<CompilationUnit> {
for (file_name, source) in sources { // let mut files = SimpleFiles::new();
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source); // let mut compilation_units = vec![];
if let Err(err) = &parse_result { //
panic!("{}", err); // for (file_name, source) in sources {
} // let file_id = files.add(file_name, source);
let mut pairs = parse_result.unwrap(); // let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
if pairs.as_str().trim() != source.trim() { // if let Err(err) = &parse_result {
panic!("Parsing did not consume entire input."); // panic!("{}", err);
} // }
let file_id = files.add(file_name, source); // let mut pairs = parse_result.unwrap();
compilation_units.push(build_ast(file_id, &mut pairs)); // if pairs.as_str().trim() != source.trim() {
} // panic!("Parsing did not consume entire input.");
// }
compilation_units //
} // compilation_units.push(build_ast(file_name, file_id, pairs.next().unwrap()));
// }
fn assert_number_of_diagnostics<'a>( //
sources: HashMap<&'a str, &'a str>, // let diagnostics = analyze_names(&mut compilation_units, symbol_table);
symbol_table: &mut SymbolTable, //
number_of_diagnostics: usize, // if diagnostics.len() != n_diagnostics {
) -> Vec<CompilationUnit> { // let writer = StandardStream::stderr(ColorChoice::Always);
let mut files = SimpleFiles::<&'a str, &'a str>::new(); // let config = term::Config::default();
let mut compilation_units = parse_compilation_units(&mut files, sources); //
// for diagnostic in &diagnostics {
let diagnostics = analyze_names(&mut compilation_units, &files, symbol_table); // term::emit(&mut writer.lock(), &config, &files, &diagnostic).unwrap();
// }
if diagnostics.len() != number_of_diagnostics { //
let writer = StandardStream::stderr(ColorChoice::Always); // eprintln!("{}", symbol_table);
let config = term::Config::default(); // }
//
for diagnostic in &diagnostics { // assert_eq!(n_diagnostics, diagnostics.len());
term::emit(&mut writer.lock(), &config, &files, &diagnostic).unwrap(); //
} // compilation_units
// }
eprintln!("{}", symbol_table); //
} // fn assert_no_diagnostics(
// sources: HashMap<&str, &str>,
assert_eq!(number_of_diagnostics, diagnostics.len()); // symbol_table: &mut SymbolTable,
// ) -> Vec<CompilationUnit> {
compilation_units // assert_number_of_diagnostics(sources, symbol_table, 0)
} // }
//
fn assert_no_diagnostics( // fn assert_saved_symbols(compilation_unit: &CompilationUnit) {
sources: HashMap<&str, &str>, // walk_depth_first(compilation_unit, &mut |node_ref| match node_ref {
symbol_table: &mut SymbolTable, // NodeRef::Identifier(identifier) => {
) -> Vec<CompilationUnit> { // if identifier.saved_symbol().is_none() {
assert_number_of_diagnostics(sources, symbol_table, 0) // panic!("{:?} does not have a saved symbol.", identifier)
} // }
// }
#[test] // NodeRef::FullyQualifiedName(fqn) => {
fn params_seen() { // if fqn.saved_symbol().is_none() {
let sources = HashMap::from([( // panic!("{:?} does not have a saved symbol.", fqn)
"main.dm", // }
" // }
fn main(args: Array<String>) // NodeRef::UseStatement(use_statement) => match use_statement {
let x = args // _ => todo!(),
end // },
", // _ => {}
)]); // })
// }
assert_no_diagnostics(sources, &mut SymbolTable::new()); //
} // fn assert_resolved_symbols(compilation_unit: &CompilationUnit) {
// walk_depth_first(compilation_unit, &mut |node_ref| match node_ref {
#[test] // NodeRef::UseStatement(use_statement) => match use_statement {
fn two_files() { // _ => todo!(),
let sources = HashMap::from([ // },
( // _ => {}
"main.dm", // })
" // }
use test::Greeter //
", // #[test]
), // fn params_seen() {
( // let sources: HashMap<&str, &str> = HashMap::from([(
"deps.dm", // "main.dm",
" // indoc! {"
ns test // fn main(args: Array<String>) {
// let x = args;
pub class Greeter end // }"},
", // )]);
), //
]); // let cus = assert_no_diagnostics(sources, &mut SymbolTable::new());
assert_no_diagnostics(sources, &mut SymbolTable::new()); // for ref cu in cus {
} // assert_saved_symbols(cu);
// }
#[test] // }
fn sees_std_core_println() { //
let sources: HashMap<&str, &str> = HashMap::from([( // #[test]
"main.dm", // fn two_files() {
" // let sources: HashMap<&str, &str> = HashMap::from([
fn main(args: Array<String>) // (
std::core::println args // "main.dm",
end // indoc! {"
", // use test::Greeter;
)]); // "},
// ),
let mut symbol_table = SymbolTable::new(); // (
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); // "deps.dm",
assert_no_diagnostics(sources, &mut symbol_table); // indoc! {"
} // ns test;
//
#[test] // pub class Greeter {}
fn sees_duplicate_fn() { // "},
let sources: HashMap<&str, &str> = HashMap::from([( // ),
"main.dm", // ]);
" //
fn main(args: Array<String>) end // let cus = assert_no_diagnostics(sources, &mut SymbolTable::new());
fn main(args: Array<String>) end // for ref cu in cus {
", // assert_saved_symbols(cu);
)]); // assert_resolved_symbols(cu);
assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1); // }
} // }
//
#[test] // #[test]
fn sees_println() { // fn sees_std_core_println() {
let sources = HashMap::from([( // let sources: HashMap<&str, &str> = HashMap::from([(
"main.dm", // "main.dm",
" // indoc! {"
fn main(args: Array<String>) // fn main(args: Array<String>) {
println args // println(args)
end // }
" // "},
)]); // )]);
let mut symbol_table = SymbolTable::new(); //
let global_std_core_use = StarUseSymbol::new( // let mut symbol_table = SymbolTable::new();
&[Rc::from("std"), Rc::from("core")], // add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
None // let cus = assert_no_diagnostics(sources, &mut symbol_table);
); // for ref cu in cus {
symbol_table.insert_star_use_symbol(global_std_core_use) // assert_saved_symbols(cu);
.expect("Failed to insert star use symbol."); // assert_resolved_symbols(cu);
// }
add_std_core_symbols(&mut symbol_table).expect("Failed to add std/core symbols."); // }
assert_no_diagnostics(sources, &mut symbol_table); //
} // #[test]
} // fn sees_duplicate_fn() {
// let sources: HashMap<&str, &str> = HashMap::from([(
// "main.dm",
// indoc! {"
// fn main(args: Array<String>) {}
// fn main(args: Array<String>) {}
// "},
// )]);
// assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1);
// }
//
// #[test]
// fn use_class_from_other_file() {
// let sources: HashMap<&str, &str> = HashMap::from([
// (
// "main.dm",
// indoc! {"
// use greeter::Greeter;
//
// fn test(greeter: Greeter) {}
// "},
// ),
// (
// "greeter.dm",
// indoc! {"
// ns greeter;
//
// class Greeter {}
// "},
// ),
// ]);
// let mut symbol_table = SymbolTable::new();
// let cus = assert_no_diagnostics(sources, &mut symbol_table);
// for ref cu in cus {
// assert_saved_symbols(cu);
// assert_resolved_symbols(cu);
// }
// }
//
// #[test]
// fn shadow_import() {
// let sources: HashMap<&str, &str> = HashMap::from([
// (
// "main.dm",
// indoc! {"
// use greeter::Greeter;
//
// class Greeter {}
// "},
// ),
// (
// "greeter.dm",
// indoc! {"
// ns greeter;
//
// class Greeter {}
// "},
// ),
// ]);
// assert_number_of_diagnostics(sources, &mut SymbolTable::new(), 1);
// }
// }

View File

@ -1,27 +1,27 @@
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::{
CompilationUnit, ConcreteUseStatement, ConcreteUseStatementSuffix, Identifier, UseStatement,
UseStatementIdentifier, UseStatementPrefix,
};
use crate::diagnostic::DmDiagnostic; use crate::diagnostic::DmDiagnostic;
use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
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::handle_lookup_error;
use std::rc::Rc;
pub fn na_p2_compilation_unit( pub fn na_p2_compilation_unit(
compilation_unit: &mut CompilationUnit, compilation_unit: &mut CompilationUnit,
symbol_table: &mut SymbolTable, symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
// TODO: check namespace for proper file name
for use_statement in compilation_unit.use_statements_mut() { for use_statement in compilation_unit.use_statements_mut() {
na_p2_use_statement(use_statement, symbol_table, diagnostics); na_p2_use_statement(use_statement, symbol_table, diagnostics);
} }
for declaration in compilation_unit.module_level_declarations_mut() {
na_p2_module_level_declaration(declaration, symbol_table, diagnostics); // TODO: declarations
}
} }
fn na_p2_use_statement( fn na_p2_use_statement(
use_statement: &mut UseStatement, use_statement: &mut UseStatement,
symbol_table: &mut SymbolTable, symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
match use_statement { match use_statement {
@ -29,22 +29,22 @@ fn na_p2_use_statement(
na_p2_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics); na_p2_concrete_use_statement(concrete_use_statement, symbol_table, diagnostics);
} }
UseStatement::StarUseStatement(star_use_statement) => { UseStatement::StarUseStatement(star_use_statement) => {
na_p2_star_use_statement(star_use_statement, symbol_table, diagnostics); todo!()
} }
} }
} }
fn na_p2_concrete_use_statement( fn na_p2_concrete_use_statement(
concrete_use_statement: &mut ConcreteUseStatement, concrete_use_statement: &mut ConcreteUseStatement,
symbol_table: &mut SymbolTable, symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
let base_fqn_parts = concrete_use_statement let base_fqn_parts: Vec<String> = concrete_use_statement
.prefixes() .prefixes()
.map(UseStatementPrefix::identifier) .map(UseStatementPrefix::identifier)
.map(Identifier::name) .map(Identifier::name)
.map(Rc::from) .map(ToString::to_string)
.collect::<Vec<Rc<str>>>(); .collect();
match concrete_use_statement.suffix_mut() { match concrete_use_statement.suffix_mut() {
ConcreteUseStatementSuffix::UseStatementIdentifier(use_statement_identifier) => { ConcreteUseStatementSuffix::UseStatementIdentifier(use_statement_identifier) => {
@ -69,14 +69,17 @@ fn na_p2_concrete_use_statement(
} }
fn handle_concrete_use_statement_identifier( fn handle_concrete_use_statement_identifier(
base_fqn_parts: &[Rc<str>], base_fqn_parts: &[String],
use_statement_identifier: &mut UseStatementIdentifier, use_statement_identifier: &mut UseStatementIdentifier,
symbol_table: &mut SymbolTable, symbol_table: &SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>, diagnostics: &mut Vec<DmDiagnostic>,
) { ) {
let fqn_parts = { let fqn_parts = {
let mut all_parts = base_fqn_parts.to_vec(); let mut all_parts: Vec<&str> = vec![];
all_parts.push(Rc::from(use_statement_identifier.identifier().name())); for part in base_fqn_parts {
all_parts.push(part);
}
all_parts.push(use_statement_identifier.identifier().name());
all_parts all_parts
}; };
@ -90,305 +93,10 @@ fn handle_concrete_use_statement_identifier(
} else { } else {
handle_lookup_error( handle_lookup_error(
SymbolLookupError::NoDefinition, SymbolLookupError::NoDefinition,
&join_fqn_parts(&fqn_parts), &fqn_parts.join("::"),
use_statement_identifier.identifier().file_id(), use_statement_identifier.identifier().file_id(),
use_statement_identifier.identifier().range(), use_statement_identifier.identifier().range(),
diagnostics, diagnostics,
); );
} }
} }
fn na_p2_star_use_statement(
star_use_statement: &mut StarUseStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let mut symbol_ref_mut = star_use_statement.symbol().unwrap().borrow_mut();
match symbol_table.find_usable_symbols_by_base_fqn(symbol_ref_mut.fqn_parts()) {
Ok(usable_symbols) => {
symbol_ref_mut.set_resolved_symbols(usable_symbols);
}
Err(symbol_lookup_error) => {
handle_lookup_error(
symbol_lookup_error,
&join_fqn_parts(symbol_ref_mut.fqn_parts()),
star_use_statement.file_id(),
star_use_statement.range(),
diagnostics,
);
}
}
}
fn na_p2_module_level_declaration(
module_level_declaration: &mut ModuleLevelDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match module_level_declaration {
ModuleLevelDeclaration::Module(module_declaration) => {
todo!()
}
ModuleLevelDeclaration::Interface(interface) => {
todo!()
}
ModuleLevelDeclaration::Class(class) => {
todo!()
}
ModuleLevelDeclaration::Function(function) => {
na_p2_function(function, symbol_table, diagnostics);
}
ModuleLevelDeclaration::PlatformFunction(platform_function) => {
todo!()
}
}
}
fn na_p2_function(
function: &mut Function,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
na_p2_function_body(function.function_body_mut(), symbol_table, diagnostics);
}
fn na_p2_function_body(
function_body: &mut FunctionBody,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match function_body {
FunctionBody::FunctionAliasBody(alias_body) => {
na_p2_function_alias_body(alias_body, symbol_table, diagnostics);
}
FunctionBody::FunctionEqualsBody(equals_body) => {}
FunctionBody::FunctionBlockBody(block_body) => {
na_p2_function_block_body(block_body, symbol_table, diagnostics);
}
}
}
fn na_p2_function_alias_body(
function_alias_body: &mut FunctionAliasBody,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
let maybe_function_symbol = symbol_table.lookup_function_symbol(
function_alias_body.identifier().name(),
*function_alias_body.scope_id().unwrap(),
);
match maybe_function_symbol {
Ok(function_symbol) => {
function_alias_body.set_resolved_function_symbol(function_symbol);
}
Err(symbol_lookup_error) => {
handle_lookup_error(
symbol_lookup_error,
function_alias_body.identifier().name(),
function_alias_body.identifier().file_id(),
function_alias_body.identifier().range(),
diagnostics,
);
}
}
}
fn na_p2_function_block_body(
function_block_body: &mut FunctionBlockBody,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
symbol_table.set_current_scope(*function_block_body.scope_id().unwrap());
for statement in function_block_body.statements_mut() {
na_p2_statement(statement, symbol_table, diagnostics);
}
}
fn na_p2_statement(
statement: &mut Statement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match statement {
Statement::VariableDeclaration(variable_declaration) => {
na_p2_variable_declaration(variable_declaration, symbol_table, diagnostics);
}
Statement::AssignmentStatement(assignment_statement) => {
na_p2_assignment_statement(assignment_statement, symbol_table, diagnostics);
}
Statement::ExpressionStatement(expression_statement) => {
na_p2_expression_statement(expression_statement, symbol_table, diagnostics);
}
Statement::UseStatement(use_statement) => {
todo!()
}
Statement::IfStatement(if_statement) => {
todo!()
}
Statement::WhileStatement(while_statement) => {
todo!()
}
Statement::ForStatement(for_statement) => {
todo!()
}
}
}
fn na_p2_variable_declaration(
variable_declaration: &mut VariableDeclaration,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
// handle variable itself
let to_insert = VariableSymbol::new(
variable_declaration.identifier().name(),
variable_declaration.is_mut(),
Some(SourceDefinition::from_identifier(
variable_declaration.identifier(),
)),
);
match symbol_table.insert_variable_symbol(to_insert) {
Ok(variable_symbol) => {
variable_declaration.set_variable_symbol(variable_symbol);
}
Err(symbol_insert_error) => {
handle_insert_error(
symbol_insert_error,
variable_declaration.identifier().name(),
variable_declaration.identifier().file_id(),
variable_declaration.identifier().range(),
diagnostics,
);
}
}
// type-use
if let Some(type_use) = variable_declaration.type_use_mut() {
na_p2_type_use(type_use, symbol_table, diagnostics);
}
// initializer
if let Some(expression) = variable_declaration.expression_mut() {
na_p2_expression(expression, symbol_table, diagnostics);
}
}
fn na_p2_assignment_statement(
assignment_statement: &mut AssignmentStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
na_p2_l_value(assignment_statement.l_value_mut(), symbol_table, diagnostics);
na_p2_expression(assignment_statement.expression_mut(), symbol_table, diagnostics);
}
fn na_p2_l_value(
l_value: &mut LValue,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
na_p2_variable_use(l_value.variable_use_mut(), symbol_table, diagnostics);
// TODO: suffixes
}
fn na_p2_expression_statement(
expression_statement: &mut ExpressionStatement,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
na_p2_expression(expression_statement.expression_mut(), symbol_table, diagnostics);
}
fn na_p2_variable_use(
variable_use: &mut VariableUse,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match symbol_table.lookup_lv_symbol(variable_use.identifier().name()) {
Ok(lv_symbol) => {
variable_use.set_lv_symbol(lv_symbol);
}
Err(symbol_lookup_error) => {
handle_lookup_error(
symbol_lookup_error,
variable_use.identifier().name(),
variable_use.identifier().file_id(),
variable_use.identifier().range(),
diagnostics,
);
}
}
}
fn na_p2_expression(
expression: &mut Expression,
symbol_table: &mut SymbolTable,
diagnostics: &mut Vec<DmDiagnostic>,
) {
match expression {
Expression::Ternary(ternary) => {
todo!()
}
Expression::Or(or) => {
todo!()
}
Expression::And(and) => {
todo!()
}
Expression::Comparison(comparison) => {
todo!()
}
Expression::Shift(shift) => {
todo!()
}
Expression::Additive(additive) => {
todo!()
}
Expression::Multiplicative(multiplicative) => {
todo!()
}
Expression::Prefix(prefix) => {
todo!()
}
Expression::Suffix(suffix) => {
todo!()
}
Expression::Literal(literal) => {
todo!()
}
Expression::VariableUse(variable_use) => {
na_p2_variable_use(variable_use, symbol_table, diagnostics);
}
Expression::Fqn(fqn) => {
todo!()
}
Expression::Closure(closure) => {
todo!()
}
Expression::List(list) => {
todo!()
}
}
}
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!()
}
}
}

View File

@ -1,5 +1,4 @@
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::Symbol;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
#[derive(Clone)] #[derive(Clone)]
@ -36,10 +35,8 @@ impl ClassMemberSymbol {
pub fn declared_name(&self) -> &str { pub fn declared_name(&self) -> &str {
&self.declared_name &self.declared_name
} }
}
impl Symbol for ClassMemberSymbol { pub fn source_definition(&self) -> Option<&SourceDefinition> {
fn source_definition(&self) -> Option<&SourceDefinition> {
self.source_definition.as_ref() self.source_definition.as_ref()
} }
} }

View File

@ -1,28 +0,0 @@
use std::cell::RefCell;
use std::rc::Rc;
use crate::name_analysis::symbol::class_member_symbol::ClassMemberSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::Symbol;
use crate::name_analysis::symbol::variable_symbol::VariableSymbol;
pub enum LVSymbol {
ClassMember(Rc<RefCell<ClassMemberSymbol>>),
Parameter(Rc<RefCell<ParameterSymbol>>),
Variable(Rc<RefCell<VariableSymbol>>),
}
impl LVSymbol {
pub fn to_symbol(self) -> Rc<RefCell<dyn Symbol>> {
match self {
LVSymbol::ClassMember(class_member_symbol) => {
class_member_symbol as Rc<RefCell<dyn Symbol>>
}
LVSymbol::Parameter(parameter_symbol) => {
parameter_symbol as Rc<RefCell<dyn Symbol>>
}
LVSymbol::Variable(variable_symbol) => {
variable_symbol as Rc<RefCell<dyn Symbol>>
}
}
}
}

View File

@ -3,7 +3,6 @@ pub mod class_symbol;
pub mod function_symbol; pub mod function_symbol;
pub mod generic_type_symbol; pub mod generic_type_symbol;
pub mod interface_symbol; pub mod interface_symbol;
pub mod lv_symbol;
pub mod module_level_symbol; pub mod module_level_symbol;
pub mod module_symbol; pub mod module_symbol;
pub mod parameter_symbol; pub mod parameter_symbol;
@ -17,13 +16,6 @@ pub mod variable_symbol;
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use std::fmt::Debug; use std::fmt::Debug;
pub use self::{
class_member_symbol::*, class_symbol::*, function_symbol::*, function_symbol::*,
generic_type_symbol::*, interface_symbol::*, lv_symbol::*, module_level_symbol::*,
module_symbol::*, parameter_symbol::*, primitive_type_symbol::*, type_symbol::*,
usable_symbol::*, use_symbol::*, variable_symbol::*,
};
pub trait Symbol: Debug { pub trait Symbol: Debug {
fn source_definition(&self) -> Option<&SourceDefinition>; fn source_definition(&self) -> Option<&SourceDefinition>;
} }

View File

@ -1,11 +1,9 @@
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::type_symbol::TypeSymbol;
use crate::name_analysis::symbol::Symbol;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc;
pub struct ParameterSymbol { pub struct ParameterSymbol {
declared_name: Rc<str>, declared_name: String,
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
type_symbol: Option<TypeSymbol>, type_symbol: Option<TypeSymbol>,
} }
@ -16,8 +14,8 @@ impl ParameterSymbol {
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
type_symbol: Option<TypeSymbol>, type_symbol: Option<TypeSymbol>,
) -> Self { ) -> Self {
Self { ParameterSymbol {
declared_name: Rc::from(declared_name), declared_name: declared_name.to_string(),
source_definition, source_definition,
type_symbol, type_symbol,
} }
@ -27,13 +25,7 @@ impl ParameterSymbol {
&self.declared_name &self.declared_name
} }
pub fn declared_name_owned(&self) -> Rc<str> { pub fn source_definition(&self) -> Option<&SourceDefinition> {
self.declared_name.clone()
}
}
impl Symbol for ParameterSymbol {
fn source_definition(&self) -> Option<&SourceDefinition> {
self.source_definition.as_ref() self.source_definition.as_ref()
} }
} }

View File

@ -1,4 +1,4 @@
use crate::ast::node::{Identifier, Operator, StarUseStatement}; use crate::ast::node::{Identifier, Operator};
use std::range::Range; use std::range::Range;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -22,13 +22,6 @@ impl SourceDefinition {
} }
} }
pub fn from_star_use_statement(star_use_statement: &StarUseStatement) -> Self {
Self {
file_id: star_use_statement.file_id(),
range: star_use_statement.range(),
}
}
pub fn file_id(&self) -> usize { pub fn file_id(&self) -> usize {
self.file_id self.file_id
} }

View File

@ -5,7 +5,7 @@ use crate::name_analysis::symbol::Symbol;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
#[derive(Debug, Clone)] #[derive(Debug)]
pub enum UsableSymbol { pub enum UsableSymbol {
Interface(Rc<RefCell<InterfaceSymbol>>), Interface(Rc<RefCell<InterfaceSymbol>>),
Class(Rc<RefCell<ClassSymbol>>), Class(Rc<RefCell<ClassSymbol>>),

View File

@ -76,7 +76,6 @@ impl Debug for ConcreteUseSymbol {
pub struct StarUseSymbol { pub struct StarUseSymbol {
fqn_parts: Vec<Rc<str>>, fqn_parts: Vec<Rc<str>>,
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
resolved_symbols: Vec<UsableSymbol>,
} }
impl StarUseSymbol { impl StarUseSymbol {
@ -84,21 +83,12 @@ impl StarUseSymbol {
Self { Self {
fqn_parts: fqn_parts.to_vec(), fqn_parts: fqn_parts.to_vec(),
source_definition, source_definition,
resolved_symbols: vec![],
} }
} }
pub fn fqn_parts(&self) -> &[Rc<str>] { pub fn fqn_parts(&self) -> &[Rc<str>] {
&self.fqn_parts &self.fqn_parts
} }
pub fn resolved_symbols(&self) -> &[UsableSymbol] {
&self.resolved_symbols
}
pub fn set_resolved_symbols(&mut self, symbols: Vec<UsableSymbol>) {
self.resolved_symbols = symbols;
}
} }
impl Symbol for StarUseSymbol { impl Symbol for StarUseSymbol {

View File

@ -1,23 +1,17 @@
use crate::name_analysis::symbol::source_definition::SourceDefinition; use crate::name_analysis::symbol::source_definition::SourceDefinition;
use crate::name_analysis::symbol::Symbol;
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::rc::Rc;
#[derive(Clone)] #[derive(Clone)]
pub struct VariableSymbol { pub struct VariableSymbol {
declared_name: Rc<str>, declared_name: String,
is_mutable: bool, is_mutable: bool,
source_definition: Option<SourceDefinition>, source_definition: Option<SourceDefinition>,
} }
impl VariableSymbol { impl VariableSymbol {
pub fn new( pub fn new(declared_name: &str, is_mutable: bool, source_definition: Option<SourceDefinition>) -> Self {
declared_name: &str,
is_mutable: bool,
source_definition: Option<SourceDefinition>,
) -> Self {
VariableSymbol { VariableSymbol {
declared_name: Rc::from(declared_name), declared_name: declared_name.to_string(),
is_mutable, is_mutable,
source_definition, source_definition,
} }
@ -27,17 +21,11 @@ impl VariableSymbol {
&self.declared_name &self.declared_name
} }
pub fn declared_name_owned(&self) -> Rc<str> {
self.declared_name.clone()
}
pub fn is_mutable(&self) -> bool { pub fn is_mutable(&self) -> bool {
self.is_mutable self.is_mutable
} }
}
impl Symbol for VariableSymbol { pub fn source_definition(&self) -> Option<&SourceDefinition> {
fn source_definition(&self) -> Option<&SourceDefinition> {
self.source_definition.as_ref() self.source_definition.as_ref()
} }
} }

View File

@ -1,11 +1,9 @@
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_symbol::ModuleSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::parameter_symbol::ParameterSymbol;
use crate::name_analysis::symbol::type_symbol::TypeSymbol; use crate::name_analysis::symbol::type_symbol::TypeSymbol;
use crate::name_analysis::symbol::usable_symbol::UsableSymbol; use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol}; use crate::name_analysis::symbol::use_symbol::{ConcreteUseSymbol, StarUseSymbol};
use crate::name_analysis::symbol::{LVSymbol, Symbol}; use crate::name_analysis::symbol::Symbol;
use crate::name_analysis::symbol_table::fqn_context::FqnContext; use crate::name_analysis::symbol_table::fqn_context::FqnContext;
use crate::name_analysis::symbol_table::symbol_tree::SymbolTree; use crate::name_analysis::symbol_table::symbol_tree::SymbolTree;
use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined;
@ -14,7 +12,7 @@ use std::cell::RefCell;
use std::fmt::Display; use std::fmt::Display;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use crate::name_analysis::symbol::variable_symbol::VariableSymbol; use crate::name_analysis::symbol::generic_type_symbol::GenericTypeSymbol;
pub(self) mod fqn_context; pub(self) mod fqn_context;
mod scope; mod scope;
@ -27,7 +25,6 @@ pub enum SymbolInsertError {
pub enum SymbolLookupError { pub enum SymbolLookupError {
NoDefinition, NoDefinition,
NoSuchNamespace,
} }
#[derive(Debug)] #[derive(Debug)]
@ -69,10 +66,6 @@ impl SymbolTable {
} }
} }
pub fn set_current_scope(&mut self, id: usize) {
self.current_scope_id = id;
}
pub fn set_current_fqn(&mut self, names: &[&str]) { pub fn set_current_fqn(&mut self, names: &[&str]) {
self.fqn_context = Box::new(FqnContext::new()); self.fqn_context = Box::new(FqnContext::new());
for name in names { for name in names {
@ -102,7 +95,7 @@ impl SymbolTable {
parts parts
} }
pub fn find_usable_symbol(&self, fqn_parts: &[Rc<str>]) -> Option<UsableSymbol> { pub fn find_usable_symbol(&self, fqn_parts: &[&str]) -> Option<UsableSymbol> {
self.symbol_tree self.symbol_tree
.find_interface(fqn_parts) .find_interface(fqn_parts)
.map(|interface_symbol| UsableSymbol::Interface(interface_symbol)) .map(|interface_symbol| UsableSymbol::Interface(interface_symbol))
@ -118,17 +111,6 @@ impl SymbolTable {
}) })
} }
pub fn register_module(&mut self, fqn_parts: &[&str]) {
self.symbol_tree.register_module_by_fqn_parts(fqn_parts);
}
pub fn find_usable_symbols_by_base_fqn(
&self,
fqn_parts: &[Rc<str>],
) -> Result<Vec<UsableSymbol>, SymbolLookupError> {
self.symbol_tree.find_all_by_base_fqn(fqn_parts)
}
fn current_scope(&self) -> &Scope { fn current_scope(&self) -> &Scope {
&self.scopes[self.current_scope_id] &self.scopes[self.current_scope_id]
} }
@ -202,49 +184,10 @@ impl SymbolTable {
&mut self, &mut self,
generic_type_symbol: GenericTypeSymbol, generic_type_symbol: GenericTypeSymbol,
) -> Result<Rc<RefCell<GenericTypeSymbol>>, SymbolInsertError> { ) -> Result<Rc<RefCell<GenericTypeSymbol>>, SymbolInsertError> {
if let Some(defined_symbol) = self if let Some(defined_symbol) = self.current_scope().find_type_symbol(generic_type_symbol.declared_name()) {
.current_scope()
.find_type_symbol(generic_type_symbol.declared_name())
{
Err(SymbolAlreadyDefined(defined_symbol.to_symbol())) Err(SymbolAlreadyDefined(defined_symbol.to_symbol()))
} else { } else {
let inserted = self let inserted = self.current_scope_mut().insert_generic_type_symbol(generic_type_symbol);
.current_scope_mut()
.insert_generic_type_symbol(generic_type_symbol);
Ok(inserted)
}
}
pub fn insert_parameter_symbol(
&mut self,
parameter_symbol: ParameterSymbol,
) -> Result<Rc<RefCell<ParameterSymbol>>, SymbolInsertError> {
if let Some(defined_symbol) = self
.current_scope()
.find_lv_symbol(parameter_symbol.declared_name())
{
Err(SymbolAlreadyDefined(defined_symbol.to_symbol()))
} else {
let inserted = self
.current_scope_mut()
.insert_parameter_symbol(parameter_symbol);
Ok(inserted)
}
}
pub fn insert_variable_symbol(
&mut self,
variable_symbol: VariableSymbol,
) -> Result<Rc<RefCell<VariableSymbol>>, SymbolInsertError> {
if let Some(defined_symbol) = self
.current_scope()
.find_lv_symbol(variable_symbol.declared_name())
{
Err(SymbolAlreadyDefined(defined_symbol.to_symbol()))
} else {
let inserted = self
.current_scope_mut()
.insert_variable_symbol(variable_symbol);
Ok(inserted) Ok(inserted)
} }
} }
@ -266,34 +209,6 @@ impl SymbolTable {
pub fn lookup_type_by_fqn(&self, fqn_parts: &[&str]) -> Result<TypeSymbol, SymbolLookupError> { pub fn lookup_type_by_fqn(&self, fqn_parts: &[&str]) -> Result<TypeSymbol, SymbolLookupError> {
todo!() todo!()
} }
pub fn lookup_function_symbol(&self, declared_name: &str, scope_id: usize) -> Result<Rc<RefCell<FunctionSymbol>>, SymbolLookupError> {
let mut current_scope: Option<&Scope> = self.scopes.get(scope_id);
while let Some(scope) = current_scope.take() {
if let Some(function_symbol) = scope.find_function_symbol(declared_name) {
return Ok(function_symbol.clone());
} else {
current_scope = scope
.parent()
.and_then(|parent_id| self.scopes.get(parent_id));
}
}
Err(SymbolLookupError::NoDefinition)
}
pub fn lookup_lv_symbol(&self, declared_name: &str) -> Result<LVSymbol, SymbolLookupError> {
let mut current_scope: Option<&Scope> = Some(self.current_scope());
while let Some(scope) = current_scope.take() {
if let Some(lv_symbol) = scope.find_lv_symbol(declared_name) {
return Ok(lv_symbol)
} else {
current_scope = scope
.parent()
.and_then(|parent_id| self.scopes.get(parent_id));
}
}
Err(SymbolLookupError::NoDefinition)
}
} }
impl Display for SymbolTable { impl Display for SymbolTable {

View File

@ -3,7 +3,6 @@ use crate::name_analysis::symbol::class_symbol::ClassSymbol;
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::generic_type_symbol::GenericTypeSymbol;
use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol; use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
use crate::name_analysis::symbol::lv_symbol::LVSymbol;
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::parameter_symbol::ParameterSymbol;
@ -27,9 +26,9 @@ pub struct Scope {
class_symbols: HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>>, class_symbols: HashMap<Rc<str>, Rc<RefCell<ClassSymbol>>>,
generic_symbols: HashMap<Rc<str>, Rc<RefCell<GenericTypeSymbol>>>, generic_symbols: HashMap<Rc<str>, Rc<RefCell<GenericTypeSymbol>>>,
function_symbols: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>, function_symbols: HashMap<Rc<str>, Rc<RefCell<FunctionSymbol>>>,
parameter_symbols: HashMap<Rc<str>, Rc<RefCell<ParameterSymbol>>>, parameter_symbols: HashMap<Rc<str>, ParameterSymbol>,
variable_symbols: HashMap<Rc<str>, Rc<RefCell<VariableSymbol>>>, variable_symbols: HashMap<Rc<str>, VariableSymbol>,
class_member_symbols: HashMap<Rc<str>, Rc<RefCell<ClassMemberSymbol>>>, class_member_symbols: HashMap<Rc<str>, ClassMemberSymbol>,
debug_name: String, debug_name: String,
} }
@ -127,30 +126,11 @@ impl Scope {
self.class_symbols.get(declared_name) self.class_symbols.get(declared_name)
} }
pub fn insert_generic_type_symbol( pub fn insert_generic_type_symbol(&mut self, symbol: GenericTypeSymbol) -> Rc<RefCell<GenericTypeSymbol>> {
&mut self,
symbol: GenericTypeSymbol,
) -> Rc<RefCell<GenericTypeSymbol>> {
let key = symbol.declared_name_owned(); let key = symbol.declared_name_owned();
insert_symbol!(self.generic_symbols, symbol, key) insert_symbol!(self.generic_symbols, symbol, key)
} }
pub fn insert_parameter_symbol(
&mut self,
symbol: ParameterSymbol,
) -> Rc<RefCell<ParameterSymbol>> {
let key = symbol.declared_name_owned();
insert_symbol!(self.parameter_symbols, symbol, key)
}
pub fn insert_variable_symbol(
&mut self,
symbol: VariableSymbol,
) -> Rc<RefCell<VariableSymbol>> {
let key = symbol.declared_name_owned();
insert_symbol!(self.variable_symbols, symbol, key)
}
pub fn find_module_level_symbol(&self, declared_name: &str) -> Option<ModuleLevelSymbol> { pub fn find_module_level_symbol(&self, declared_name: &str) -> Option<ModuleLevelSymbol> {
self.module_symbols self.module_symbols
.get(declared_name) .get(declared_name)
@ -188,26 +168,6 @@ impl Scope {
}) })
} }
pub fn find_lv_symbol(&self, declared_name: &str) -> Option<LVSymbol> {
self.class_member_symbols
.get(declared_name)
.map(|class_member_symbol| LVSymbol::ClassMember(class_member_symbol.clone()))
.or_else(|| {
self.parameter_symbols
.get(declared_name)
.map(|parameter_symbol| LVSymbol::Parameter(parameter_symbol.clone()))
})
.or_else(|| {
self.variable_symbols
.get(declared_name)
.map(|variable_symbol| LVSymbol::Variable(variable_symbol.clone()))
})
}
pub fn find_function_symbol(&self, declared_name: &str) -> Option<&Rc<RefCell<FunctionSymbol>>> {
self.function_symbols.get(declared_name)
}
pub fn debug_name(&self) -> &str { pub fn debug_name(&self) -> &str {
&self.debug_name &self.debug_name
} }

View File

@ -2,8 +2,6 @@ use crate::name_analysis::symbol::class_symbol::ClassSymbol;
use crate::name_analysis::symbol::function_symbol::FunctionSymbol; use crate::name_analysis::symbol::function_symbol::FunctionSymbol;
use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol; use crate::name_analysis::symbol::interface_symbol::InterfaceSymbol;
use crate::name_analysis::symbol::module_symbol::ModuleSymbol; use crate::name_analysis::symbol::module_symbol::ModuleSymbol;
use crate::name_analysis::symbol::usable_symbol::UsableSymbol;
use crate::name_analysis::symbol_table::SymbolLookupError;
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
@ -26,35 +24,35 @@ impl SymbolTree {
} }
} }
pub fn find_class(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<ClassSymbol>>> { pub fn find_class(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<ClassSymbol>>> {
match fqn_parts.len() { match fqn_parts.len() {
0 => None, 0 => None,
1 => self.classes.get(&fqn_parts[0]).cloned(), 1 => self.classes.get(fqn_parts[0]).cloned(),
_ => self _ => self
.children .children
.get(&fqn_parts[0]) .get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_class(&fqn_parts[1..])), .and_then(|child_tree| child_tree.find_class(&fqn_parts[1..])),
} }
} }
pub fn find_interface(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<InterfaceSymbol>>> { pub fn find_interface(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<InterfaceSymbol>>> {
match fqn_parts.len() { match fqn_parts.len() {
0 => None, 0 => None,
1 => self.interfaces.get(&fqn_parts[0]).cloned(), 1 => self.interfaces.get(fqn_parts[0]).cloned(),
_ => self _ => self
.children .children
.get(&fqn_parts[0]) .get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_interface(&fqn_parts[1..])), .and_then(|child_tree| child_tree.find_interface(&fqn_parts[1..])),
} }
} }
pub fn find_function(&self, fqn_parts: &[Rc<str>]) -> Option<Rc<RefCell<FunctionSymbol>>> { pub fn find_function(&self, fqn_parts: &[&str]) -> Option<Rc<RefCell<FunctionSymbol>>> {
match fqn_parts.len() { match fqn_parts.len() {
0 => None, 0 => None,
1 => self.functions.get(&fqn_parts[0]).cloned(), 1 => self.functions.get(fqn_parts[0]).cloned(),
_ => self _ => self
.children .children
.get(&fqn_parts[0]) .get(fqn_parts[0])
.and_then(|child_tree| child_tree.find_function(&fqn_parts[1..])), .and_then(|child_tree| child_tree.find_function(&fqn_parts[1..])),
} }
} }
@ -63,15 +61,6 @@ impl SymbolTree {
self.recurse_register_module(&module_symbol.borrow().fqn_parts()); self.recurse_register_module(&module_symbol.borrow().fqn_parts());
} }
pub fn register_module_by_fqn_parts(&mut self, fqn_parts: &[&str]) {
self.recurse_register_module(
&fqn_parts
.iter()
.map(|part| Rc::from(*part))
.collect::<Vec<Rc<str>>>(),
);
}
fn recurse_register_module(&mut self, fqn_parts: &[Rc<str>]) { fn recurse_register_module(&mut self, fqn_parts: &[Rc<str>]) {
if fqn_parts.len() == 0 { if fqn_parts.len() == 0 {
panic!("Unable to register module fqn with no parts.") panic!("Unable to register module fqn with no parts.")
@ -96,13 +85,9 @@ impl SymbolTree {
self.recurse_register_function(function_symbol, &fqn_parts); self.recurse_register_function(function_symbol, &fqn_parts);
} }
fn recurse_register_function( fn recurse_register_function(&mut self, function_symbol: Rc<RefCell<FunctionSymbol>>, fqn_parts: &[Rc<str>]) {
&mut self,
function_symbol: Rc<RefCell<FunctionSymbol>>,
fqn_parts: &[Rc<str>],
) {
if fqn_parts.len() == 0 { if fqn_parts.len() == 0 {
panic!("Unable to register function fqn with no parts."); panic!("Unable to register function fqn with no parts.")
} }
if fqn_parts.len() == 1 { if fqn_parts.len() == 1 {
self.functions.insert(fqn_parts[0].clone(), function_symbol); self.functions.insert(fqn_parts[0].clone(), function_symbol);
@ -116,32 +101,4 @@ impl SymbolTree {
} }
} }
pub fn find_all_by_base_fqn(
&self,
fqn_parts: &[Rc<str>],
) -> Result<Vec<UsableSymbol>, SymbolLookupError> {
match fqn_parts.len() {
0 => {
let mut all_symbols: Vec<UsableSymbol> = vec![];
for interface_symbol in self.interfaces.values() {
all_symbols.push(UsableSymbol::Interface(interface_symbol.clone()));
}
for class_symbol in self.classes.values() {
all_symbols.push(UsableSymbol::Class(class_symbol.clone()));
}
for function_symbol in self.functions.values() {
all_symbols.push(UsableSymbol::Function(function_symbol.clone()));
}
Ok(all_symbols)
}
_ => {
if self.children.contains_key(fqn_parts[0].as_ref()) {
let child = self.children.get(fqn_parts[0].as_ref()).unwrap();
child.find_all_by_base_fqn(fqn_parts)
} else {
Err(SymbolLookupError::NoSuchNamespace)
}
}
}
}
} }

View File

@ -45,19 +45,11 @@ pub fn handle_lookup_error(
match err { match err {
SymbolLookupError::NoDefinition => { SymbolLookupError::NoDefinition => {
let diagnostic = Diagnostic::error() let diagnostic = Diagnostic::error()
.with_message(format!("No such symbol '{}' in scope.", error_symbol_name)) .with_message(format!("No such symbol '{}' in scope.", error_symbol_name,))
.with_label( .with_label(
Label::primary(error_file_id, error_range).with_message("Symbol used here."), Label::primary(error_file_id, error_range).with_message("Symbol used here."),
); );
diagnostics.push(diagnostic); diagnostics.push(diagnostic);
},
SymbolLookupError::NoSuchNamespace => {
let diagnostic = Diagnostic::error()
.with_message(format!("No such namespace '{}' found", error_symbol_name))
.with_label(
Label::primary(error_file_id, error_range).with_message("Namespace used here.")
);
diagnostics.push(diagnostic);
} }
} }
} }

View File

@ -281,10 +281,6 @@ StarUseStatement:
- range: - range:
special: special:
kind: range kind: range
fields:
- symbol:
kind: StarUseSymbol
wrap: rc_ref_cell
UseStatementPrefix: UseStatementPrefix:
struct: struct:
children: children:
@ -609,9 +605,6 @@ FunctionEqualsBody:
struct: struct:
children: children:
- expression - expression
fields:
- scope_id:
kind: usize
FunctionAliasBody: FunctionAliasBody:
struct: struct:
children: children:
@ -619,12 +612,6 @@ FunctionAliasBody:
skip: skip:
rule: Alias rule: Alias
- identifier - identifier
fields:
- scope_id:
kind: usize
- resolved_function_symbol:
kind: FunctionSymbol
wrap: rc_ref_cell
FunctionBlockBody: FunctionBlockBody:
struct: struct:
children: children:
@ -634,9 +621,6 @@ FunctionBlockBody:
- end_kw: - end_kw:
skip: skip:
rule: End rule: End
fields:
- scope_id:
kind: usize
# Class constructs # Class constructs
ClassConstructor: ClassConstructor:
@ -693,10 +677,6 @@ VariableDeclaration:
- expression: - expression:
member: member:
optional: true optional: true
fields:
- variable_symbol:
kind: VariableSymbol
wrap: rc_ref_cell
AssignmentStatement: AssignmentStatement:
struct: struct:
children: children:
@ -802,9 +782,10 @@ VariableUse:
struct: struct:
children: children:
- identifier - identifier
fields: derive:
- lv_symbol: - PartialEq
kind: LVSymbol - Eq
- Hash
# Expressions # Expressions
Expression: Expression:

View File

@ -7,16 +7,11 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
symbol_table.register_module(&["std"]);
symbol_table.register_module(&["std", "core"]);
symbol_table.set_current_fqn(&vec!["std", "core"]); symbol_table.set_current_fqn(&vec!["std", "core"]);
let println_msg_symbol = ParameterSymbol::new( let println_msg_symbol = ParameterSymbol::new("msg", None, Some(
"msg", TypeSymbol::Primitive(PrimitiveTypeSymbol::Any)
None, ));
Some(TypeSymbol::Primitive(PrimitiveTypeSymbol::Any)),
);
let println_symbol = FunctionSymbol::with_parameters_and_return_type( let println_symbol = FunctionSymbol::with_parameters_and_return_type(
&symbol_table.resolve_fqn(Rc::from("println")), &symbol_table.resolve_fqn(Rc::from("println")),