swamp_modules/
modules.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/semantic
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use crate::symtbl::{DefinitionTable, FuncDef, ModuleDefinitionKind};
6use seq_map::SeqMap;
7use source_map_node::FileId;
8use std::fmt::{Debug, Formatter};
9use std::rc::Rc;
10use swamp_semantic::prelude::Error;
11use swamp_semantic::{
12    Expression, ExpressionKind, InternalFunctionDefinition, InternalFunctionId,
13    InternalMainExpression,
14};
15
16#[derive(Debug)]
17pub struct Modules {
18    modules: SeqMap<Vec<String>, ModuleRef>,
19    file_id_to_module: SeqMap<FileId, ModuleRef>,
20}
21
22impl Default for Modules {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl Modules {
29    #[must_use]
30    pub fn get_internal_function(
31        &self,
32        id: InternalFunctionId,
33    ) -> Option<&InternalFunctionDefinition> {
34        for (_name, module) in &self.modules {
35            for (_name, module_def) in &module.definition_table.definitions {
36                if let ModuleDefinitionKind::FunctionDefinition(function_def) = &module_def.kind
37                    && let FuncDef::Internal(func_def) = function_def
38                    && func_def.program_unique_id == id
39                {
40                    return Some(func_def);
41                }
42            }
43        }
44        None
45    }
46}
47
48pub struct Module {
49    pub main_expression: Option<InternalMainExpression>,
50    pub definition_table: DefinitionTable,
51    pub lookup_table: DefinitionTable,
52    pub file_id: FileId,
53    pub errors: Vec<Error>,
54}
55
56impl Debug for Module {
57    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
58        if let Some(internal_main) = &self.main_expression {
59            pretty_print(f, &internal_main.expression, 0)?;
60        }
61
62        Ok(())
63    }
64}
65
66/// # Errors
67///
68pub fn pretty_print(
69    f: &mut Formatter<'_>,
70    resolved_expression: &Expression,
71    tabs: usize,
72) -> std::fmt::Result {
73    if let ExpressionKind::Block(expressions) = &resolved_expression.kind {
74        for internal_expr in expressions {
75            pretty_print(f, internal_expr, tabs + 1)?;
76        }
77        Ok(())
78    } else {
79        let tab_str = "..".repeat(tabs);
80        writeln!(
81            f,
82            "{}{},{:?}",
83            tab_str, resolved_expression.ty, resolved_expression.kind
84        )
85    }
86}
87
88pub type ModuleRef = Rc<Module>;
89
90impl Module {
91    #[must_use]
92    pub const fn new(
93        symbol_table: DefinitionTable,
94        lookup_table: DefinitionTable, // Lookup table is not really used except for special things, like lsp
95        errors: Vec<Error>,
96        expression: Option<InternalMainExpression>,
97        file_id: FileId,
98    ) -> Self {
99        Self {
100            definition_table: symbol_table,
101            lookup_table,
102            file_id,
103            main_expression: expression,
104            errors,
105        }
106    }
107}
108
109impl Modules {
110    #[must_use]
111    pub fn new() -> Self {
112        Self {
113            modules: SeqMap::new(),
114            file_id_to_module: SeqMap::new(),
115        }
116    }
117
118    #[must_use]
119    pub const fn modules(&self) -> &SeqMap<Vec<String>, ModuleRef> {
120        &self.modules
121    }
122
123    #[must_use]
124    pub fn contains_key(&self, module_path: &[String]) -> bool {
125        self.modules.contains_key(&module_path.to_vec())
126    }
127
128    pub fn add(&mut self, module: ModuleRef) {
129        let path = module.definition_table.module_path();
130
131        self.modules
132            .insert(path, module.clone())
133            .expect("could not insert");
134        let _file_id_result = self
135            .file_id_to_module
136            .insert(module.file_id, module.clone());
137    }
138
139    pub fn link_module(&mut self, module_path: &[String], referred_module: ModuleRef) {
140        self.modules
141            .insert(module_path.to_vec(), referred_module.clone())
142            .expect("could not insert");
143        self.file_id_to_module
144            .insert(referred_module.file_id, referred_module)
145            .expect("could not insert");
146    }
147
148    #[must_use]
149    pub fn get(&self, module_path: &[String]) -> Option<&ModuleRef> {
150        self.modules.get(&module_path.to_vec())
151    }
152
153    #[must_use]
154    pub fn get_from_file_id(&self, file_id: FileId) -> Option<&ModuleRef> {
155        self.file_id_to_module.get(&file_id)
156    }
157}