swamp_program_analyzer/
lib.rs1use source_map_cache::SourceMap;
6use swamp_analyzer::Analyzer;
7use swamp_analyzer::prelude::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::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: &SymbolTable,
34 modules: &mut Modules,
35 core_symbol_table: &SymbolTableRef,
36 source_map: &SourceMap,
37 module_path: &[String],
38 ast_module: &ParsedAstModule,
39) -> Result<(SymbolTable, Vec<Error>, Option<InternalMainExpression>), LoaderErr> {
40 let debug_string = format!("analyze module {module_path:?}");
42 let _analyze_timer = ScopedTimer::new(&debug_string);
43
44 let mut analyzer = Analyzer::new(
45 state,
46 modules,
47 core_symbol_table.clone(),
48 source_map,
49 module_path,
50 ast_module.file_id,
51 );
52
53 analyzer.shared.lookup_table = default_lookup_symbol_table.clone();
54
55 let statements = {
56 for ast_def in ast_module.ast_module.definitions() {
57 analyzer.analyze_definition(ast_def);
59 }
60
61 if let Some(expr) = ast_module.ast_module.expression() {
62 let internal_main = analyzer.analyze_main_expression(expr);
63 Some(internal_main)
64 } else {
65 None
66 }
67 };
68
69 Ok((
70 analyzer.shared.definition_table,
71 analyzer.shared.state.errors().clone(),
72 statements,
73 ))
74}
75
76pub fn analyze_modules_in_order(
81 state: &mut ProgramState,
82 default_lookup_symbol_table: &SymbolTable,
83 modules: &mut Modules,
84 core_symbol_table: &SymbolTableRef,
85 source_map: &SourceMap,
86 module_paths_in_order: &[Vec<String>],
87 parsed_modules: &DependencyParser,
88) -> Result<(), LoaderErr> {
89 debug!(?module_paths_in_order, "analyzing modules in order");
90 for module_path in module_paths_in_order {
91 if *module_path == ["core"] || *module_path == ["std"] {
92 continue;
93 }
94 if let Some(parse_module) = parsed_modules.get_parsed_module(module_path) {
95 let (analyzed_symbol_table, errors, maybe_expression) = analyze_module(
99 state,
100 default_lookup_symbol_table,
101 modules,
102 core_symbol_table,
103 source_map,
104 module_path,
105 parse_module,
106 )?;
107 let analyzed_module = Module::new(analyzed_symbol_table, errors, maybe_expression);
108 modules.add(analyzed_module.into());
109 } else {
110 panic!("could not load")
111 }
112 }
113 Ok(())
114}
115
116pub fn compile_and_analyze_all_modules(
121 module_path: &[String],
122 resolved_program: &mut Program,
123 source_map: &mut SourceMap,
124 core_symbol_table: &SymbolTableRef,
125) -> Result<(), LoaderErr> {
126 let mut dependency_parser = DependencyParser::new();
127
128 let module_paths_in_order =
129 parse_local_modules_and_get_order(module_path, &mut dependency_parser, source_map).unwrap(); analyze_modules_in_order(
132 &mut resolved_program.state,
133 &resolved_program.default_symbol_table,
134 &mut resolved_program.modules,
135 core_symbol_table,
136 source_map,
137 &module_paths_in_order,
138 &dependency_parser,
139 )?;
140
141 Ok(())
142}