swamp_script_eval_loader/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/script
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use swamp_script_analyzer::Analyzer;
6use swamp_script_analyzer::prelude::{Error, Program};
7use swamp_script_dep_loader::{
8    DependencyParser, ParsedAstModule, parse_local_modules_and_get_order,
9};
10use swamp_script_modules::prelude::*;
11use swamp_script_modules::symtbl::SymbolTableRef;
12use swamp_script_semantic::{InternalMainExpression, ProgramState, SemanticError};
13use swamp_script_source_map::SourceMap;
14use time_dilation::ScopedTimer;
15use tracing::{Level, debug, span};
16
17#[derive(Debug)]
18pub enum LoaderErr {
19    CouldNotLoad,
20    SemanticError(SemanticError),
21    AnalyzerError(Error),
22}
23
24impl From<Error> for LoaderErr {
25    fn from(value: Error) -> Self {
26        LoaderErr::AnalyzerError(value)
27    }
28}
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///
72pub fn analyze_modules_in_order(
73    state: &mut ProgramState,
74    default_lookup_symbol_table: &SymbolTable,
75    modules: &mut Modules,
76    core_symbol_table: SymbolTableRef,
77    source_map: &SourceMap,
78    module_paths_in_order: &[Vec<String>],
79    parsed_modules: &DependencyParser,
80) -> Result<(), LoaderErr> {
81    debug!(?module_paths_in_order, "analyzing modules in order");
82    for module_path in module_paths_in_order {
83        if *module_path == ["core"] {
84            continue;
85        }
86        if let Some(parse_module) = parsed_modules.get_parsed_module(module_path) {
87            let process_span = span!(Level::TRACE, "analyze mod", path = ?module_path);
88            let _enter = process_span.enter();
89
90            let (analyzed_symbol_table, maybe_expression) = analyze_module(
91                state,
92                default_lookup_symbol_table,
93                modules,
94                &core_symbol_table,
95                source_map,
96                module_path,
97                parse_module,
98            )?;
99            let analyzed_module = Module::new(analyzed_symbol_table, maybe_expression);
100            modules.add(analyzed_module.into());
101        } else {
102            panic!("could not load")
103        }
104    }
105    Ok(())
106}
107
108pub fn compile_and_analyze_all_modules(
109    module_path: &[String],
110    resolved_program: &mut Program,
111    source_map: &mut SourceMap,
112    core_symbol_table: SymbolTableRef,
113) -> Result<(), LoaderErr> {
114    let mut dependency_parser = DependencyParser::new();
115
116    let module_paths_in_order =
117        parse_local_modules_and_get_order(module_path.to_vec(), &mut dependency_parser, source_map)
118            .unwrap(); // TODO: FIX THIS
119
120    analyze_modules_in_order(
121        &mut resolved_program.state,
122        &resolved_program.default_symbol_table,
123        &mut resolved_program.modules,
124        core_symbol_table,
125        source_map,
126        &module_paths_in_order,
127        &dependency_parser,
128    )?;
129
130    Ok(())
131}