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::prelude::{Error, Program};
6use swamp_script_analyzer::{Analyzer, AutoUseModules, TypeContext, TypeContextScope};
7use swamp_script_dep_loader::{
8    DepLoaderError, DependencyParser, ParsedAstModule, parse_local_modules_and_get_order,
9};
10use swamp_script_semantic::modules::Module;
11use swamp_script_semantic::prelude::Modules;
12use swamp_script_semantic::symtbl::SymbolTable;
13use swamp_script_semantic::{Expression, ProgramState};
14use swamp_script_source_map::SourceMap;
15
16#[derive(Debug)]
17pub enum EvalLoaderError {
18    DepLoaderError(DepLoaderError),
19    AnalyzerError(Error),
20}
21
22impl From<DepLoaderError> for EvalLoaderError {
23    fn from(err: DepLoaderError) -> Self {
24        Self::DepLoaderError(err)
25    }
26}
27
28impl From<Error> for EvalLoaderError {
29    fn from(err: Error) -> Self {
30        Self::AnalyzerError(err)
31    }
32}
33
34pub fn analyze_module(
35    state: &mut ProgramState,
36    auto_use_modules: &AutoUseModules,
37    modules: &mut Modules,
38    source_map: &SourceMap,
39    ast_module: &ParsedAstModule,
40) -> Result<(SymbolTable, Option<Expression>), Error> {
41    let mut resolver = Analyzer::new(state, modules, source_map, ast_module.file_id);
42    if !auto_use_modules.modules.is_empty() {
43        let target = &mut resolver.shared.lookup_table;
44        for symbol_table in &auto_use_modules.modules {
45            for (name, symbol) in symbol_table.symbols() {
46                target.add_symbol(name, symbol.clone())?;
47            }
48        }
49    }
50
51    let outside_context = TypeContext::new(None, None, TypeContextScope::ArgumentOrOutsideFunction);
52    let statements = {
53        for ast_def in ast_module.ast_module.definitions() {
54            resolver.analyze_definition(ast_def)?;
55        }
56
57        let maybe_resolved_expression = if let Some(expr) = ast_module.ast_module.expression() {
58            Some(resolver.analyze_expression(expr, &outside_context)?)
59        } else {
60            None
61        };
62        maybe_resolved_expression
63    };
64
65    Ok((resolver.shared.definition_table, statements))
66}
67
68pub fn analyze_modules_in_order(
69    state: &mut ProgramState,
70    auto_use: &AutoUseModules,
71    modules: &mut Modules,
72    source_map: &SourceMap,
73    module_paths_in_order: &[Vec<String>],
74    parsed_modules: &DependencyParser,
75) -> Result<(), Error> {
76    for module_path in module_paths_in_order {
77        if let Some(parse_module) = parsed_modules.get_parsed_module(module_path) {
78            let (analyzed_symbol_table, maybe_expression) =
79                analyze_module(state, auto_use, modules, source_map, parse_module)?;
80            let analyzed_module = Module::new(module_path, analyzed_symbol_table, maybe_expression);
81            modules.add(analyzed_module.into());
82        } else {
83            panic!("could not load")
84        }
85    }
86    Ok(())
87}
88
89pub fn compile_and_analyze_all_modules(
90    module_path: &[String],
91    resolved_program: &mut Program,
92    source_map: &mut SourceMap,
93) -> Result<(), EvalLoaderError> {
94    let mut dependency_parser = DependencyParser::new();
95
96    let module_paths_in_order = parse_local_modules_and_get_order(
97        module_path.to_vec(),
98        &mut dependency_parser,
99        source_map,
100    )?;
101
102    analyze_modules_in_order(
103        &mut resolved_program.state,
104        &resolved_program.auto_use_modules,
105        &mut resolved_program.modules,
106        source_map,
107        &module_paths_in_order,
108        &dependency_parser,
109    )?;
110
111    Ok(())
112}