Skip to main content

factorio_ir/
module.rs

1use crate::{block::Block, locale::LocaleFile, scope::Scope, stage::Stage, statement::Statement};
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct Symbol {
5    pub scope: Scope,
6    pub statement: Statement,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ModuleImport {
11    /// Dotted module path inside the Factorio mod (e.g. `shared.player`).
12    pub module: String,
13    pub local: String,
14    pub items: Vec<ImportedItem>,
15    /// When set, `require` targets this Factorio mod instead of the consuming mod.
16    pub factorio_mod: Option<String>,
17    /// Path prefix inside the Factorio mod (`Some("lua")`, `Some("")`, ...).
18    /// When [`Self::factorio_mod`] is `None`, codegen always uses `lua`.
19    pub module_root: Option<String>,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct ImportedItem {
24    pub name: String,
25    pub local: String,
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct Module {
30    pub name: String,
31    pub stage: Stage,
32    pub body: Block,
33    pub symbols: Vec<Symbol>,
34    pub imports: Vec<ModuleImport>,
35    pub submodules: Vec<String>,
36    /// Locale `.cfg` data declared via `locale!` in this module.
37    pub locales: Vec<LocaleFile>,
38}
39
40impl Module {
41    #[must_use]
42    pub fn imported_item_local(&self, type_name: &str) -> Option<&str> {
43        self.imports
44            .iter()
45            .flat_map(|import| import.items.iter())
46            .find_map(|item| {
47                if item.name == type_name {
48                    Some(item.local.as_str())
49                } else {
50                    None
51                }
52            })
53    }
54
55    #[must_use]
56    pub fn is_imported_type_extension(&self, struct_decl: &crate::structure::Struct) -> bool {
57        struct_decl.fields.is_empty() && self.imported_item_local(&struct_decl.name).is_some()
58    }
59}