From dbfaad8ec6203b46c0a252c6089d71ee27fc5ab4 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Tue, 9 Jan 2024 19:15:13 +0100 Subject: [PATCH] Remove useless abstraction --- enderpy/src/main.rs | 13 +--- lsp/src/main.rs | 4 +- typechecker/src/build.rs | 81 ++++++++++---------- typechecker/src/lib.rs | 1 - typechecker/src/nodes.rs | 36 ++++++++- typechecker/src/semantic_analyzer.rs | 2 +- typechecker/src/state.rs | 48 ------------ typechecker/src/symbol_table.rs | 11 +-- typechecker/src/type_check/checker.rs | 10 ++- typechecker/src/type_check/type_evaluator.rs | 24 +++--- 10 files changed, 105 insertions(+), 125 deletions(-) delete mode 100644 typechecker/src/state.rs diff --git a/enderpy/src/main.rs b/enderpy/src/main.rs index 1250cef7..2a63aaf3 100644 --- a/enderpy/src/main.rs +++ b/enderpy/src/main.rs @@ -46,7 +46,7 @@ fn symbols(path: &Path) -> Result<()> { manager.build(); let module = manager.get_state(path.to_path_buf()).unwrap(); - println!("{}", module.file.module_name()); + println!("{}", module.module_name()); println!("{}", module.get_symbol_table()); Ok(()) @@ -110,14 +110,9 @@ fn check(path: &Path) -> Result<()> { let mut build_manager = BuildManager::new(vec![initial_source], settings); build_manager.type_check(); - for file_result in build_manager.get_result() { - for err in file_result.diagnostics { - println!( - "{:#?}: line {}: {}", - file_result.file.path(), - err.range.start.line, - err.body - ); + for (path, errors) in build_manager.diagnostics { + for err in errors { + println!("{:#?}: line {}: {}", path, err.range.start.line, err.body); } } diff --git a/lsp/src/main.rs b/lsp/src/main.rs index b1b3571c..229df173 100644 --- a/lsp/src/main.rs +++ b/lsp/src/main.rs @@ -44,8 +44,8 @@ impl Backend { let mut diagnostics = Vec::new(); info!("path: {path:?}"); - if let Some(state) = manager.get_state(path) { - for err in state.diagnostics.iter() { + if let Some(errors) = manager.diagnostics.get(&path) { + for err in errors { diagnostics.push(from(err.clone())); } } diff --git a/typechecker/src/build.rs b/typechecker/src/build.rs index 47dfdcb5..ee0eb808 100755 --- a/typechecker/src/build.rs +++ b/typechecker/src/build.rs @@ -14,16 +14,17 @@ use crate::{ module_descriptor::ImportModuleDescriptor, resolver, }, settings::Settings, - state::State, type_check::checker::TypeChecker, }; #[derive(Debug)] pub struct BuildManager { pub errors: Vec, - pub modules: HashMap, + pub modules: HashMap, build_sources: Vec, options: Settings, + // Map of file name to list of diagnostics + pub diagnostics: HashMap>, } #[allow(unused)] impl BuildManager { @@ -50,17 +51,18 @@ impl BuildManager { build_sources: sources, modules, options, + diagnostics: HashMap::new(), } } - pub fn get_result(&self) -> Vec { + pub fn get_result(&self) -> Vec { self.modules.values().cloned().collect() } - pub fn get_state(&self, path: PathBuf) -> Option<&State> { + pub fn get_state(&self, path: PathBuf) -> Option<&EnderpyFile> { for state in self.modules.values() { - info!("state: {:#?}", state.file.path()); - if state.file.path() == path { + info!("state: {:#?}", state.path()); + if state.path() == path { return Some(state); } } @@ -76,8 +78,8 @@ impl BuildManager { fn populate_modules(&mut self) { for build_source in self.build_sources.iter() { let build_source: BuildSource = build_source.clone(); - let state = State::new(build_source.into()); - self.modules.insert(state.file.module_name(), state); + let state: EnderpyFile = build_source.into(); + self.modules.insert(state.module_name(), state); } let (new_files, imports) = match self.options.follow_imports { crate::settings::FollowImports::All => { @@ -88,11 +90,11 @@ impl BuildManager { } }; for build_source in new_files { - let module = self.create_module(build_source); - self.modules.insert(module.file.module_name(), module); + let file: EnderpyFile = build_source.into(); + self.modules.insert(file.module_name(), file); } for module in self.modules.values_mut() { - info!("file: {:#?}", module.file.module_name()); + info!("file: {:#?}", module.module_name()); module.populate_symbol_table(&imports); } } @@ -108,8 +110,8 @@ impl BuildManager { } for state in self.modules.iter_mut() { - if !state.1.file.errors.is_empty() { - for err in state.1.file.errors.iter() { + if !state.1.errors.is_empty() { + for err in state.1.errors.iter() { match err { ParsingError::InvalidSyntax { msg, @@ -121,24 +123,27 @@ impl BuildManager { body: msg.to_string(), suggestion: Some(advice.to_string()), range: crate::diagnostic::Range { - start: state.1.file.get_position(span.0), - end: state.1.file.get_position(span.1), - }, - }); - state.1.diagnostics.push(Diagnostic { - body: msg.to_string(), - suggestion: Some(advice.to_string()), - range: crate::diagnostic::Range { - start: state.1.file.get_position(span.0), - end: state.1.file.get_position(span.1), + start: state.1.get_position(span.0), + end: state.1.get_position(span.1), }, }); + self.diagnostics + .entry(state.1.path()) + .or_default() + .push(Diagnostic { + body: msg.to_string(), + suggestion: Some(advice.to_string()), + range: crate::diagnostic::Range { + start: state.1.get_position(span.0), + end: state.1.get_position(span.1), + }, + }); } } } } let mut checker = TypeChecker::new(state.1, &self.options, all_symbol_tables.clone()); - for stmt in &state.1.file.body { + for stmt in &state.1.body { checker.type_check(stmt); } for error in checker.errors { @@ -146,18 +151,21 @@ impl BuildManager { body: error.msg.to_string(), suggestion: Some("".into()), range: crate::diagnostic::Range { - start: state.1.file.get_position(error.span.0), - end: state.1.file.get_position(error.span.1), - }, - }); - state.1.diagnostics.push(Diagnostic { - body: error.msg.to_string(), - suggestion: Some("".into()), - range: crate::diagnostic::Range { - start: state.1.file.get_position(error.span.0), - end: state.1.file.get_position(error.span.1), + start: state.1.get_position(error.span.0), + end: state.1.get_position(error.span.1), }, }); + self.diagnostics + .entry(state.1.path()) + .or_default() + .push(Diagnostic { + body: error.msg.to_string(), + suggestion: Some("".into()), + range: crate::diagnostic::Range { + start: state.1.get_position(error.span.0), + end: state.1.get_position(error.span.1), + }, + }); } } } @@ -320,11 +328,6 @@ impl BuildManager { (imported_sources, import_results) } - // TODO: refactor to implement From/to trait - fn create_module(&self, build_source: BuildSource) -> State { - State::new(EnderpyFile::from(build_source)) - } - fn resolve_file_imports( &self, file: EnderpyFile, diff --git a/typechecker/src/lib.rs b/typechecker/src/lib.rs index 135b9d34..831d5ddf 100644 --- a/typechecker/src/lib.rs +++ b/typechecker/src/lib.rs @@ -3,7 +3,6 @@ mod ast_visitor_generic; mod nodes; mod ruff_python_import_resolver; mod semanal_utils; -mod state; mod symbol_table; mod type_check; diff --git a/typechecker/src/nodes.rs b/typechecker/src/nodes.rs index 278f40d5..6774f4b3 100755 --- a/typechecker/src/nodes.rs +++ b/typechecker/src/nodes.rs @@ -5,13 +5,22 @@ // here, so this has the minimum amount of nodes needed to // get the type checker working. But can be expanded. -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf}; use enderpy_python_parser as parser; use enderpy_python_parser::ast::{Import, ImportFrom, Statement}; use parser::{error::ParsingError, Parser}; -use crate::{ast_visitor::TraversalVisitor, build_source::BuildSource, diagnostic::Position}; +use crate::{ + ast_visitor::TraversalVisitor, + build_source::BuildSource, + diagnostic::Position, + ruff_python_import_resolver::{ + import_result::ImportResult, module_descriptor::ImportModuleDescriptor, + }, + semantic_analyzer::SemanticAnalyzer, + symbol_table::SymbolTable, +}; #[derive(Clone, Debug)] pub enum ImportKinds { @@ -31,6 +40,7 @@ pub struct EnderpyFile { pub build_source: BuildSource, // Parser Errors pub errors: Vec, + pub symbol_table: SymbolTable, } impl EnderpyFile { @@ -63,6 +73,25 @@ impl EnderpyFile { character: (pos - line_start - 1) as u32, } } + + /// entry point to fill up the symbol table from the global definitions + pub fn populate_symbol_table( + &mut self, + imports: &HashMap, + ) { + let mut sem_anal = SemanticAnalyzer::new(self.clone(), imports.clone()); + for stmt in &self.body { + sem_anal.visit_stmt(stmt) + } + // TODO: Hacky way to add the global scope to all scopes in symbol table after + // finishing + sem_anal.globals.exit_scope(); + self.symbol_table = sem_anal.globals; + } + + pub fn get_symbol_table(&self) -> SymbolTable { + self.symbol_table.clone() + } } impl From for EnderpyFile { @@ -72,6 +101,8 @@ impl From for EnderpyFile { build_source.path.as_path().to_str().unwrap().to_owned(), ); let tree = parser.parse(); + let symbol_table = + SymbolTable::global(build_source.module.clone(), build_source.path.clone()); let mut file = EnderpyFile { defs: vec![], @@ -79,6 +110,7 @@ impl From for EnderpyFile { body: vec![], build_source, errors: parser.errors, + symbol_table, }; for stmt in &tree.body { diff --git a/typechecker/src/semantic_analyzer.rs b/typechecker/src/semantic_analyzer.rs index 7eef79fc..caeea53e 100644 --- a/typechecker/src/semantic_analyzer.rs +++ b/typechecker/src/semantic_analyzer.rs @@ -39,7 +39,7 @@ pub struct SemanticAnalyzer { impl SemanticAnalyzer { pub fn new(file: EnderpyFile, imports: HashMap) -> Self { log::debug!("Creating semantic analyzer for {}", file.module_name()); - let globals = SymbolTable::global(file.clone()); + let globals = SymbolTable::global(file.module_name(), file.path()); let is_pyi = file.path().ends_with(".pyi"); SemanticAnalyzer { globals, diff --git a/typechecker/src/state.rs b/typechecker/src/state.rs deleted file mode 100644 index 833d10d7..00000000 --- a/typechecker/src/state.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::collections::HashMap; - -use crate::{ - ast_visitor::TraversalVisitor, - diagnostic::Diagnostic, - nodes::EnderpyFile, - ruff_python_import_resolver::{ - import_result::ImportResult, module_descriptor::ImportModuleDescriptor, - }, - semantic_analyzer::SemanticAnalyzer, - symbol_table::SymbolTable, -}; - -#[derive(Debug, Clone)] -pub struct State { - pub file: EnderpyFile, - symbol_table: SymbolTable, - pub diagnostics: Vec, -} - -impl State { - pub fn new(file: EnderpyFile) -> Self { - let symbol_table = SymbolTable::global(file.clone()); - Self { - file, - symbol_table, - diagnostics: Vec::new(), - } - } - /// entry point to fill up the symbol table from the global definitions - pub fn populate_symbol_table( - &mut self, - imports: &HashMap, - ) { - let mut sem_anal = SemanticAnalyzer::new(self.file.clone(), imports.clone()); - for stmt in &self.file.body { - sem_anal.visit_stmt(stmt) - } - // TODO: Hacky way to add the global scope to all scopes in symbol table after - // finishing - sem_anal.globals.exit_scope(); - self.symbol_table = sem_anal.globals; - } - - pub fn get_symbol_table(&self) -> SymbolTable { - self.symbol_table.clone() - } -} diff --git a/typechecker/src/symbol_table.rs b/typechecker/src/symbol_table.rs index fb20aa8f..b29e0fa7 100644 --- a/typechecker/src/symbol_table.rs +++ b/typechecker/src/symbol_table.rs @@ -2,10 +2,7 @@ use std::{collections::HashMap, fmt::Display, path::PathBuf}; use enderpy_python_parser::ast::{self, Node}; -use crate::{ - nodes::EnderpyFile, ruff_python_import_resolver::import_result::ImportResult, - type_check::builtins, -}; +use crate::{ruff_python_import_resolver::import_result::ImportResult, type_check::builtins}; #[derive(Debug, Clone)] pub struct SymbolTable { @@ -225,7 +222,7 @@ pub enum SymbolScope { } impl SymbolTable { - pub fn global(enderpy_file: EnderpyFile) -> Self { + pub fn global(module_name: String, file_path: PathBuf) -> Self { let mut builtin_scope = SymbolTableScope { id: get_id(), symbol_table_type: SymbolTableType::BUILTIN, @@ -317,8 +314,8 @@ impl SymbolTable { scopes: vec![builtin_scope, global_scope], all_scopes: vec![], _locals: HashMap::new(), - module_name: enderpy_file.module_name(), - file_path: enderpy_file.path(), + module_name, + file_path, } } diff --git a/typechecker/src/type_check/checker.rs b/typechecker/src/type_check/checker.rs index bc0354f4..4607b865 100644 --- a/typechecker/src/type_check/checker.rs +++ b/typechecker/src/type_check/checker.rs @@ -4,8 +4,8 @@ use enderpy_python_parser::ast::{self, *}; use super::{type_evaluator::TypeEvaluator, types::PythonType}; use crate::{ - ast_visitor::TraversalVisitor, diagnostic::CharacterSpan, settings::Settings, state::State, - symbol_table::SymbolTable, + ast_visitor::TraversalVisitor, diagnostic::CharacterSpan, nodes::EnderpyFile, + settings::Settings, symbol_table::SymbolTable, }; pub struct TypeChecker<'a> { @@ -22,7 +22,11 @@ pub struct TypeCheckError { #[allow(unused)] impl<'a> TypeChecker<'a> { - pub fn new(module: &'a State, options: &'a Settings, symbol_tables: Vec) -> Self { + pub fn new( + module: &'a EnderpyFile, + options: &'a Settings, + symbol_tables: Vec, + ) -> Self { let symbol_table = module.get_symbol_table(); TypeChecker { errors: vec![], diff --git a/typechecker/src/type_check/type_evaluator.rs b/typechecker/src/type_check/type_evaluator.rs index f684b973..121bb1c1 100755 --- a/typechecker/src/type_check/type_evaluator.rs +++ b/typechecker/src/type_check/type_evaluator.rs @@ -18,7 +18,6 @@ use crate::{ ast_visitor::TraversalVisitor, ast_visitor_generic::TraversalVisitorImmutGeneric, nodes::EnderpyFile, - state::State, symbol_table::{self, Class, Declaration, LookupSymbolRequest, SymbolTable, SymbolTableNode}, type_check::types::ClassType, }; @@ -830,8 +829,12 @@ impl TypeEvaluator { None => panic!("Alias {:?} has no symbol name", a.import_node), }; - let symbol_table_with_alias_def = - self.get_symbol_table_of(a.import_result.resolved_paths.last().unwrap()); + let resolved_path = match a.import_result.resolved_paths.last() { + Some(path) => path, + None => panic!("Alias {:?} has no resolved path available are", a), + }; + + let symbol_table_with_alias_def = self.get_symbol_table_of(resolved_path); return symbol_table_with_alias_def?.lookup_in_scope(LookupSymbolRequest { name: class_name.clone(), position: None, @@ -1125,25 +1128,20 @@ impl TraversalVisitorImmutGeneric for TypeEvaluator { struct DumpTypes { pub type_eval: TypeEvaluator, pub types: HashMap, - pub state: State, + pub enderpy_file: EnderpyFile, } impl DumpTypes { pub fn new(enderpy_file: EnderpyFile, type_eval: TypeEvaluator) -> Self { - let mut state = State::new(enderpy_file); - // TODO: this line runs on every test and it needs to add all of stdlib to - // symbol table. This is not efficient and needs to be refactored - state.populate_symbol_table(&HashMap::new()); - let symbol_table = state.get_symbol_table(); Self { types: HashMap::new(), type_eval, - state, + enderpy_file, } } pub fn enderpy_file(&self) -> &EnderpyFile { - &self.state.file + &self.enderpy_file } /// This function is called on every expression in the ast @@ -1304,7 +1302,7 @@ mod tests { all_symbol_tables.push(module.get_symbol_table()); } - let module = manager.get_state("test-file".into()).unwrap(); + let module = manager.get_state("test-file".into()).unwrap().clone(); let symbol_table = module.get_symbol_table(); let type_eval = TypeEvaluator { @@ -1312,7 +1310,7 @@ mod tests { imported_symbol_tables: all_symbol_tables, }; - let mut type_eval_visitor = DumpTypes::new(module.file.clone(), type_eval); + let mut type_eval_visitor = DumpTypes::new(module.clone(), type_eval); type_eval_visitor.visit_module(); let result = type_eval_visitor.types;