swamp_program_analyzer/
lib.rs1use source_map_cache::SourceMap;
6use swamp_analyzer::Analyzer;
7use swamp_analyzer::prelude::{Error, Program};
8use swamp_dep_loader::{DependencyParser, ParsedAstModule, parse_local_modules_and_get_order};
9use swamp_modules::prelude::*;
10use swamp_modules::symtbl::SymbolTableRef;
11use swamp_semantic::{InternalMainExpression, ProgramState, SemanticError};
12use time_dilation::ScopedTimer;
13use tracing::{Level, debug, span};
14
15#[derive(Debug)]
16pub enum LoaderErr {
17 CouldNotLoad,
18 SemanticError(SemanticError),
19 AnalyzerError(Error),
20}
21
22impl From<Error> for LoaderErr {
23 fn from(value: Error) -> Self {
24 Self::AnalyzerError(value)
25 }
26}
27
28pub fn analyze_module(
31 state: &mut ProgramState,
32 default_lookup_symbol_table: &SymbolTable,
33 modules: &mut Modules,
34 core_symbol_table: &SymbolTableRef,
35 source_map: &SourceMap,
36 module_path: &[String],
37 ast_module: &ParsedAstModule,
38) -> Result<(SymbolTable, Option<InternalMainExpression>), LoaderErr> {
39 let debug_string = format!("analyze module {module_path:?}");
40 let _analyze_timer = ScopedTimer::new(&debug_string);
41
42 let mut resolver = Analyzer::new(
43 state,
44 modules,
45 core_symbol_table.clone(),
46 source_map,
47 module_path,
48 ast_module.file_id,
49 );
50
51 resolver.shared.lookup_table = default_lookup_symbol_table.clone();
52
53 let statements = {
54 for ast_def in ast_module.ast_module.definitions() {
55 resolver.analyze_definition(ast_def)?;
56 }
57
58 let maybe_resolved_expression = if let Some(expr) = ast_module.ast_module.expression() {
59 let internal_main = resolver.analyze_main_expression(expr)?;
60 Some(internal_main)
61 } else {
62 None
63 };
64 maybe_resolved_expression
65 };
66
67 Ok((resolver.shared.definition_table, statements))
68}
69
70pub fn analyze_modules_in_order(
75 state: &mut ProgramState,
76 default_lookup_symbol_table: &SymbolTable,
77 modules: &mut Modules,
78 core_symbol_table: &SymbolTableRef,
79 source_map: &SourceMap,
80 module_paths_in_order: &[Vec<String>],
81 parsed_modules: &DependencyParser,
82) -> Result<(), LoaderErr> {
83 debug!(?module_paths_in_order, "analyzing modules in order");
84 for module_path in module_paths_in_order {
85 if *module_path == ["core"] {
86 continue;
87 }
88 if let Some(parse_module) = parsed_modules.get_parsed_module(module_path) {
89 let process_span = span!(Level::TRACE, "analyze mod", path = ?module_path);
90 let _enter = process_span.enter();
91
92 let (analyzed_symbol_table, maybe_expression) = analyze_module(
93 state,
94 default_lookup_symbol_table,
95 modules,
96 core_symbol_table,
97 source_map,
98 module_path,
99 parse_module,
100 )?;
101 let analyzed_module = Module::new(analyzed_symbol_table, maybe_expression);
102 modules.add(analyzed_module.into());
103 } else {
104 panic!("could not load")
105 }
106 }
107 Ok(())
108}
109
110pub fn compile_and_analyze_all_modules(
115 module_path: &[String],
116 resolved_program: &mut Program,
117 source_map: &mut SourceMap,
118 core_symbol_table: &SymbolTableRef,
119) -> Result<(), LoaderErr> {
120 let mut dependency_parser = DependencyParser::new();
121
122 let module_paths_in_order =
123 parse_local_modules_and_get_order(module_path, &mut dependency_parser, source_map).unwrap(); analyze_modules_in_order(
126 &mut resolved_program.state,
127 &resolved_program.default_symbol_table,
128 &mut resolved_program.modules,
129 core_symbol_table,
130 source_map,
131 &module_paths_in_order,
132 &dependency_parser,
133 )?;
134
135 Ok(())
136}