swamp_program_analyzer/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use 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
28/// # Errors
29///
30pub 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
70/// # Errors
71///
72/// # Panics
73///
74pub 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
110/// # Errors
111///
112/// # Panics
113///
114pub 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(); // TODO: FIX THIS
124
125    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}