nu_protocol/ast/
block.rs

1use super::Pipeline;
2use crate::{OutDest, Signature, Span, Type, VarId, engine::StateWorkingSet, ir::IrBlock};
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Block {
7    pub signature: Box<Signature>,
8    pub pipelines: Vec<Pipeline>,
9    pub captures: Vec<(VarId, Span)>,
10    pub redirect_env: bool,
11    /// The block compiled to IR instructions. Not available for subexpressions.
12    pub ir_block: Option<IrBlock>,
13    pub span: Option<Span>, // None option encodes no span to avoid using test_span()
14}
15
16impl Block {
17    pub fn len(&self) -> usize {
18        self.pipelines.len()
19    }
20
21    pub fn is_empty(&self) -> bool {
22        self.pipelines.is_empty()
23    }
24
25    pub fn pipe_redirection(
26        &self,
27        working_set: &StateWorkingSet,
28    ) -> (Option<OutDest>, Option<OutDest>) {
29        if let Some(first) = self.pipelines.first() {
30            first.pipe_redirection(working_set)
31        } else {
32            (None, None)
33        }
34    }
35}
36
37impl Default for Block {
38    fn default() -> Self {
39        Self::new()
40    }
41}
42
43impl Block {
44    pub fn new() -> Self {
45        Self {
46            signature: Box::new(Signature::new("")),
47            pipelines: vec![],
48            captures: vec![],
49            redirect_env: false,
50            ir_block: None,
51            span: None,
52        }
53    }
54
55    pub fn new_with_capacity(capacity: usize) -> Self {
56        Self {
57            signature: Box::new(Signature::new("")),
58            pipelines: Vec::with_capacity(capacity),
59            captures: vec![],
60            redirect_env: false,
61            ir_block: None,
62            span: None,
63        }
64    }
65
66    pub fn output_type(&self) -> Type {
67        if let Some(last) = self.pipelines.last() {
68            if let Some(last) = last.elements.last() {
69                if last.redirection.is_some() {
70                    Type::Any
71                } else {
72                    last.expr.ty.clone()
73                }
74            } else {
75                Type::Nothing
76            }
77        } else {
78            Type::Nothing
79        }
80    }
81
82    /// Replace any `$in` variables in the initial element of pipelines within the block
83    pub fn replace_in_variable(
84        &mut self,
85        working_set: &mut StateWorkingSet<'_>,
86        new_var_id: VarId,
87    ) {
88        for pipeline in self.pipelines.iter_mut() {
89            if let Some(element) = pipeline.elements.first_mut() {
90                element.replace_in_variable(working_set, new_var_id);
91            }
92        }
93    }
94}
95
96impl<T> From<T> for Block
97where
98    T: Iterator<Item = Pipeline>,
99{
100    fn from(pipelines: T) -> Self {
101        Self {
102            signature: Box::new(Signature::new("")),
103            pipelines: pipelines.collect(),
104            captures: vec![],
105            redirect_env: false,
106            ir_block: None,
107            span: None,
108        }
109    }
110}