Begin name-analysis testing.

This commit is contained in:
Jesse Brault 2025-05-16 11:21:44 -05:00
parent 4224055860
commit dda86f75e7
3 changed files with 118 additions and 9 deletions

View File

@ -1,6 +1,6 @@
use crate::name_analysis::symbol::Symbol;
use pest::Parser;
use std::range::Range;
use crate::name_analysis::symbol::Symbol;
pub mod build;
pub mod named;
@ -241,8 +241,8 @@ impl Default for Parameters {
#[derive(Debug)]
pub struct Parameter {
identifier: Identifier,
type_use: TypeUse,
pub identifier: Identifier,
pub type_use: TypeUse,
}
/* Return Type */

View File

@ -50,11 +50,50 @@ fn gather_function_definition(
.set_scope_id(symbol_table.current_scope_id());
symbol_table.push_scope(&format!("FunctionScope({})", resolved_name));
// TODO: params
gather_parameters(
&mut function.parameters,
symbol_table,
fqn_context,
diagnostics,
);
gather_function_body(&mut function.body, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope();
}
fn gather_parameters(
parameters: &mut Parameters,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut DiagnosticsContainer,
) {
for parameter in &mut parameters.0 {
gather_parameter(parameter, symbol_table, fqn_context, diagnostics);
}
}
fn gather_parameter(
parameter: &mut Parameter,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut DiagnosticsContainer,
) {
let parameter_name = parameter.identifier.name();
let insert_result = symbol_table.insert(
parameter_name.to_string(),
Symbol::Variable(VariableSymbol {
name: parameter_name.to_string(),
is_mutable: false,
}),
);
if let Err(msg) = insert_result {
diagnostics.add_error_at_identifier(&msg, &parameter.identifier);
}
parameter.identifier.set_scope_id(symbol_table.current_scope_id());
}
fn gather_function_body(
function_body: &mut FunctionBody,
symbol_table: &mut SymbolTable,
@ -63,7 +102,7 @@ fn gather_function_body(
) {
use crate::ast::FunctionBody::*;
match function_body {
Block(block) => gather_block_statement(block, symbol_table, fqn_context, diagnostics),
Block(block) => gather_block_statement_inner(block, symbol_table, fqn_context, diagnostics),
_ => todo!(),
}
}
@ -75,10 +114,22 @@ fn gather_block_statement(
diagnostics: &mut DiagnosticsContainer,
) {
symbol_table.push_scope("BlockStatementScope");
gather_block_statement(block, symbol_table, fqn_context, diagnostics);
symbol_table.pop_scope();
}
fn gather_block_statement_inner(
block: &mut BlockStatement,
symbol_table: &mut SymbolTable,
fqn_context: &mut FqnContext,
diagnostics: &mut DiagnosticsContainer,
) {
for statement in &mut block.statements {
gather_statement(statement, symbol_table, fqn_context, diagnostics);
}
symbol_table.pop_scope();
if let Some(expression) = &mut block.expression {
gather_expression(expression, symbol_table, diagnostics);
}
}
fn gather_statement(
@ -124,6 +175,10 @@ fn gather_variable_declaration(
variable_declaration
.identifier
.set_scope_id(symbol_table.current_scope_id());
if let Some(initializer) = &mut variable_declaration.initializer {
gather_expression(initializer, symbol_table, diagnostics);
}
}
fn gather_assign_statement(
@ -132,11 +187,15 @@ fn gather_assign_statement(
fqn_context: &mut FqnContext,
diagnostics: &mut DiagnosticsContainer,
) {
gather_expression(&mut assign_statement.lhs, symbol_table);
gather_expression(&mut assign_statement.rhs, symbol_table);
gather_expression(&mut assign_statement.lhs, symbol_table, diagnostics);
gather_expression(&mut assign_statement.rhs, symbol_table, diagnostics);
}
fn gather_expression(expression: &mut Expression, symbol_table: &mut SymbolTable) {
fn gather_expression(
expression: &mut Expression,
symbol_table: &mut SymbolTable,
diagnostics: &mut DiagnosticsContainer,
) {
use crate::ast::Expression::*;
match expression {
FullyQualifiedName(fully_qualified_name) => {

View File

@ -74,3 +74,53 @@ pub fn analyze_names(
diagnostics.into()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ast::build::build_ast;
use crate::parser::{DeimosParser, Rule};
use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term;
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use pest::Parser;
fn assert_no_diagnostics(src: &str) {
let parse_result = DeimosParser::parse(Rule::CompilationUnit, src);
if let Err(err) = &parse_result {
panic!("{:?}", err);
}
let compilation_unit_pair = parse_result.unwrap().next().unwrap();
let mut ast = build_ast(compilation_unit_pair);
let mut files = SimpleFiles::new();
let test_file_id = files.add("test.dm", src);
let mut symbol_table = SymbolTable::new();
let diagnostics = analyze_names(test_file_id, &mut ast, &mut symbol_table);
if !diagnostics.is_empty() {
let writer = StandardStream::stderr(ColorChoice::Always);
let config = term::Config::default();
for diagnostic in &diagnostics {
term::emit(&mut writer.lock(), &config, &files, &diagnostic).unwrap();
}
eprintln!("{}", symbol_table);
panic!("Diagnostics was not empty!");
}
}
#[test]
fn params_seen() {
assert_no_diagnostics(
r#"
fn main(args: Array<String>) {
let x = args;
}
"#,
)
}
}