swamp_program_analyzer/
lib.rs1use source_map_cache::SourceMap;
6use swamp_analyzer::prelude::Program;
7use swamp_analyzer::{Analyzer, AnalyzerOptions};
8use swamp_dep_loader::{DependencyParser, ParsedAstModule, parse_local_modules_and_get_order};
9use swamp_modules::prelude::*;
10use swamp_modules::symtbl::SymbolTableRef;
11use swamp_semantic::prelude::Error;
12use swamp_semantic::{InternalMainExpression, ProgramState, SemanticError};
13use time_dilation::ScopedTimer;
14use tracing::debug;
15
16#[derive(Debug)]
17pub enum LoaderErr {
18 CouldNotLoad,
19 SemanticError(SemanticError),
20 AnalyzerError(Error),
21}
22
23impl From<Error> for LoaderErr {
24 fn from(value: Error) -> Self {
25 Self::AnalyzerError(value)
26 }
27}
28
29pub fn analyze_module(
32 state: &mut ProgramState,
33 default_lookup_symbol_table: &DefinitionTable,
34 modules: &mut Modules,
35 core_symbol_table: &SymbolTableRef,
36 source_map: &SourceMap,
37 module_path: &[String],
38 ast_module: &ParsedAstModule,
39 options: AnalyzerOptions,
40) -> Result<(DefinitionTable, Vec<Error>, Option<InternalMainExpression>), LoaderErr> {
41 let debug_string = format!("analyze module {module_path:?}");
43 let _analyze_timer = ScopedTimer::new(&debug_string);
44
45 let mut analyzer = Analyzer::new(
46 state,
47 modules,
48 core_symbol_table.clone(),
49 source_map,
50 module_path,
51 ast_module.file_id,
52 options,
53 );
54
55 analyzer.shared.lookup_table = default_lookup_symbol_table.clone();
56
57 let statements = {
58 for ast_def in ast_module.ast_module.definitions() {
59 analyzer.analyze_definition(ast_def);
61 }
62
63 if let Some(expr) = ast_module.ast_module.expression() {
64 let internal_main = analyzer.analyze_main_expression(expr);
65 Some(internal_main)
66 } else {
67 None
68 }
69 };
70
71 Ok((
72 analyzer.shared.definition_table,
73 analyzer.shared.state.errors().clone(),
74 statements,
75 ))
76}
77
78pub fn analyze_modules_in_order(
83 state: &mut ProgramState,
84 default_lookup_symbol_table: &DefinitionTable,
85 modules: &mut Modules,
86 core_symbol_table: &SymbolTableRef,
87 source_map: &SourceMap,
88 module_paths_in_order: &[Vec<String>],
89 parsed_modules: &DependencyParser,
90 options: AnalyzerOptions,
91) -> Result<(), LoaderErr> {
92 debug!(?module_paths_in_order, "analyzing modules in order");
93 for module_path in module_paths_in_order {
94 if *module_path == ["core"] || *module_path == ["std"] {
95 continue;
96 }
97 if let Some(parse_module) = parsed_modules.get_parsed_module(module_path) {
98 let (analyzed_symbol_table, errors, maybe_expression) = analyze_module(
102 state,
103 default_lookup_symbol_table,
104 modules,
105 core_symbol_table,
106 source_map,
107 module_path,
108 parse_module,
109 options,
110 )?;
111
112 let analyzed_module = Module::new(
113 analyzed_symbol_table,
114 errors,
115 maybe_expression,
116 parse_module.file_id,
117 );
118 modules.add(analyzed_module.into());
119 } else {
120 panic!("could not load")
121 }
122 }
123 Ok(())
124}
125
126pub fn compile_and_analyze_all_modules(
131 module_path: &[String],
132 resolved_program: &mut Program,
133 source_map: &mut SourceMap,
134 core_symbol_table: &SymbolTableRef,
135 options: AnalyzerOptions,
136) -> Result<(), LoaderErr> {
137 let mut dependency_parser = DependencyParser::new();
138
139 let module_paths_in_order =
140 parse_local_modules_and_get_order(module_path, &mut dependency_parser, source_map).unwrap(); analyze_modules_in_order(
143 &mut resolved_program.state,
144 &resolved_program.default_symbol_table,
145 &mut resolved_program.modules,
146 core_symbol_table,
147 source_map,
148 &module_paths_in_order,
149 &dependency_parser,
150 options,
151 )?;
152
153 Ok(())
154}