dpscript/dpscript/ast/
mod.rs

1mod node;
2
3pub use node::*;
4
5use crate::{module_indexer_add, ModuleExport, Result};
6use serde::Serialize;
7use std::collections::BTreeMap;
8
9#[derive(Debug, Clone, Serialize)]
10pub struct AST {
11    pub nodes: Vec<Node>,
12    pub indexed: bool,
13    pub cached: bool,
14
15    // We want these sorted for niceties, so we use a BTreeMap
16    #[serde(skip)]
17    pub modules: Option<BTreeMap<String, Module>>,
18
19    #[serde(skip)]
20    pub top_level: Option<BTreeMap<String, Vec<TopLevelNode>>>,
21
22    #[serde(skip)]
23    pub imports: Option<BTreeMap<String, Vec<Import>>>,
24
25    #[serde(skip)]
26    pub funcs: Option<BTreeMap<String, Vec<Function>>>,
27
28    #[serde(skip)]
29    pub vars: Option<BTreeMap<String, Vec<Variable>>>,
30
31    #[serde(skip)]
32    pub blocks: Option<BTreeMap<String, Vec<Block>>>,
33
34    #[serde(skip)]
35    pub enums: Option<BTreeMap<String, Vec<Enum>>>,
36
37    #[serde(skip)]
38    pub objectives: Option<BTreeMap<String, Vec<Objective>>>,
39
40    #[serde(skip)]
41    pub exports: Option<BTreeMap<String, Vec<Export>>>,
42
43    #[serde(skip)]
44    pub export_nodes: Option<BTreeMap<String, Vec<ModuleExport>>>, // just a cache :) this is updated elsewhere
45}
46
47impl AST {
48    pub fn merge(&mut self, other: AST) -> &mut Self {
49        self.nodes.extend(other.nodes);
50        self
51    }
52
53    pub fn collect_modules(&self) -> BTreeMap<String, Module> {
54        let mut modules: BTreeMap<String, Module> = BTreeMap::new();
55
56        for node in &self.nodes {
57            if let Node::Module(module) = node {
58                let name = module.name();
59
60                if let Some(it) = modules.get_mut(&name) {
61                    it.body.extend(module.no_submodules());
62                } else {
63                    modules.insert(name.clone(), module.with_no_submodules());
64                }
65
66                for (name, item) in module.collect_submodules(name) {
67                    if let Some(it) = modules.get_mut(&name) {
68                        it.body.extend(item.body);
69                    } else {
70                        modules.insert(name, item);
71                    }
72                }
73            }
74        }
75
76        modules
77    }
78
79    pub fn index(&mut self) -> Result<&mut Self> {
80        if self.indexed {
81            return Ok(self);
82        }
83
84        let mut modules = self.collect_modules();
85
86        for (_, module) in &mut modules {
87            module.index_top_level_nodes()?;
88        }
89
90        self.modules = Some(modules.clone());
91
92        let mut top_level: BTreeMap<String, Vec<TopLevelNode>> = BTreeMap::new();
93        let mut imports: BTreeMap<String, Vec<Import>> = BTreeMap::new();
94        let mut funcs: BTreeMap<String, Vec<Function>> = BTreeMap::new();
95        let mut vars: BTreeMap<String, Vec<Variable>> = BTreeMap::new();
96        let mut blocks: BTreeMap<String, Vec<Block>> = BTreeMap::new();
97        let mut enums: BTreeMap<String, Vec<Enum>> = BTreeMap::new();
98        let mut objectives: BTreeMap<String, Vec<Objective>> = BTreeMap::new();
99        let mut exports: BTreeMap<String, Vec<Export>> = BTreeMap::new();
100
101        for (name, module) in modules {
102            module_indexer_add!(top_level += (name, module));
103            module_indexer_add!(imports += (name, module));
104            module_indexer_add!(funcs += (name, module));
105            module_indexer_add!(vars += (name, module));
106            module_indexer_add!(blocks += (name, module));
107            module_indexer_add!(enums += (name, module));
108            module_indexer_add!(objectives += (name, module));
109            module_indexer_add!(exports += (name, module));
110        }
111
112        self.top_level = Some(top_level);
113        self.imports = Some(imports);
114        self.funcs = Some(funcs);
115        self.vars = Some(vars);
116        self.blocks = Some(blocks);
117        self.enums = Some(enums);
118        self.objectives = Some(objectives);
119        self.exports = Some(exports);
120        self.indexed = true;
121
122        Ok(self)
123    }
124}