nu_protocol/engine/
state_delta.rs

1use crate::{
2    Module, Span,
3    ast::Block,
4    engine::{
5        CachedFile, Command, EngineState, OverlayFrame, ScopeFrame, Variable, VirtualPath,
6        description::Doccomments,
7    },
8};
9use std::sync::Arc;
10
11#[cfg(feature = "plugin")]
12use crate::{PluginRegistryItem, RegisteredPlugin};
13
14/// A delta (or change set) between the current global state and a possible future global state. Deltas
15/// can be applied to the global state to update it to contain both previous state and the state held
16/// within the delta.
17#[derive(Clone)]
18pub struct StateDelta {
19    pub(super) files: Vec<CachedFile>,
20    pub(super) virtual_paths: Vec<(String, VirtualPath)>,
21    pub(super) vars: Vec<Variable>,          // indexed by VarId
22    pub(super) decls: Vec<Box<dyn Command>>, // indexed by DeclId
23    pub blocks: Vec<Arc<Block>>,             // indexed by BlockId
24    pub(super) modules: Vec<Arc<Module>>,    // indexed by ModuleId
25    pub spans: Vec<Span>,                    // indexed by SpanId
26    pub(super) doccomments: Doccomments,
27    pub scope: Vec<ScopeFrame>,
28    #[cfg(feature = "plugin")]
29    pub(super) plugins: Vec<Arc<dyn RegisteredPlugin>>,
30    #[cfg(feature = "plugin")]
31    pub(super) plugin_registry_items: Vec<PluginRegistryItem>,
32}
33
34impl StateDelta {
35    pub fn new(engine_state: &EngineState) -> Self {
36        let last_overlay = engine_state.last_overlay(&[]);
37        let scope_frame = ScopeFrame::with_empty_overlay(
38            engine_state.last_overlay_name(&[]).to_owned(),
39            last_overlay.origin,
40            last_overlay.prefixed,
41        );
42
43        StateDelta {
44            files: vec![],
45            virtual_paths: vec![],
46            vars: vec![],
47            decls: vec![],
48            blocks: vec![],
49            modules: vec![],
50            spans: vec![],
51            scope: vec![scope_frame],
52            doccomments: Doccomments::new(),
53            #[cfg(feature = "plugin")]
54            plugins: vec![],
55            #[cfg(feature = "plugin")]
56            plugin_registry_items: vec![],
57        }
58    }
59
60    pub fn num_files(&self) -> usize {
61        self.files.len()
62    }
63
64    pub fn num_virtual_paths(&self) -> usize {
65        self.virtual_paths.len()
66    }
67
68    pub fn num_vars(&self) -> usize {
69        self.vars.len()
70    }
71
72    pub fn num_decls(&self) -> usize {
73        self.decls.len()
74    }
75
76    pub fn num_blocks(&self) -> usize {
77        self.blocks.len()
78    }
79
80    pub fn num_modules(&self) -> usize {
81        self.modules.len()
82    }
83
84    pub fn last_scope_frame_mut(&mut self) -> &mut ScopeFrame {
85        self.scope
86            .last_mut()
87            .expect("internal error: missing required scope frame")
88    }
89
90    pub fn last_scope_frame(&self) -> &ScopeFrame {
91        self.scope
92            .last()
93            .expect("internal error: missing required scope frame")
94    }
95
96    pub fn last_overlay_mut(&mut self) -> Option<&mut OverlayFrame> {
97        let last_scope = self
98            .scope
99            .last_mut()
100            .expect("internal error: missing required scope frame");
101
102        if let Some(last_overlay_id) = last_scope.active_overlays.last() {
103            Some(
104                &mut last_scope
105                    .overlays
106                    .get_mut(last_overlay_id.get())
107                    .expect("internal error: missing required overlay")
108                    .1,
109            )
110        } else {
111            None
112        }
113    }
114
115    pub fn last_overlay(&self) -> Option<&OverlayFrame> {
116        let last_scope = self
117            .scope
118            .last()
119            .expect("internal error: missing required scope frame");
120
121        if let Some(last_overlay_id) = last_scope.active_overlays.last() {
122            Some(
123                &last_scope
124                    .overlays
125                    .get(last_overlay_id.get())
126                    .expect("internal error: missing required overlay")
127                    .1,
128            )
129        } else {
130            None
131        }
132    }
133
134    pub fn enter_scope(&mut self) {
135        self.scope.push(ScopeFrame::new());
136    }
137
138    pub fn exit_scope(&mut self) {
139        self.scope.pop();
140    }
141
142    pub fn get_file_contents(&self) -> &[CachedFile] {
143        &self.files
144    }
145}