vrl/compiler/expression/
block.rs

1use std::fmt;
2
3use crate::compiler::state::{TypeInfo, TypeState};
4use crate::compiler::{
5    Context, Expression, TypeDef,
6    expression::{Expr, Resolved},
7};
8use crate::value::Kind;
9
10#[derive(Debug, Clone, PartialEq)]
11pub struct Block {
12    inner: Vec<Expr>,
13
14    // false - This is just an inline block of code
15    // true - This is a block of code nested in a child scope
16    new_scope: bool,
17}
18
19impl Block {
20    #[must_use]
21    fn new(inner: Vec<Expr>, new_scope: bool) -> Self {
22        Self { inner, new_scope }
23    }
24
25    #[must_use]
26    pub fn new_scoped(inner: Vec<Expr>) -> Self {
27        Self::new(inner, true)
28    }
29
30    #[must_use]
31    pub fn new_inline(inner: Vec<Expr>) -> Self {
32        Self::new(inner, false)
33    }
34
35    #[must_use]
36    pub fn into_inner(self) -> Vec<Expr> {
37        self.inner
38    }
39
40    #[must_use]
41    pub fn exprs(&self) -> &Vec<Expr> {
42        &self.inner
43    }
44}
45
46impl Expression for Block {
47    fn resolve(&self, ctx: &mut Context) -> Resolved {
48        // Variables are checked at compile-time to ensure only variables
49        // in scope can be accessed here, so it doesn't need to be checked at runtime.
50        let (last, other) = self.inner.split_last().expect("at least one expression");
51
52        other
53            .iter()
54            .try_for_each(|expr| expr.resolve(ctx).map(|_| ()))?;
55
56        last.resolve(ctx)
57    }
58
59    fn type_info(&self, state: &TypeState) -> TypeInfo {
60        let parent_locals = state.local.clone();
61
62        let mut state = state.clone();
63        let mut result = TypeDef::null();
64        let mut fallible = false;
65        let mut returns = Kind::never();
66        let mut after_never_expression = false;
67
68        for expr in &self.inner {
69            result = expr.apply_type_info(&mut state);
70
71            if !after_never_expression && result.is_fallible() {
72                fallible = true;
73            }
74            if result.is_never() {
75                after_never_expression = true;
76            }
77            returns.merge_keep(result.returns().clone(), false);
78        }
79
80        if self.new_scope {
81            state.local = parent_locals.apply_child_scope(state.local);
82        }
83
84        TypeInfo::new(state, result.maybe_fallible(fallible).with_returns(returns))
85    }
86}
87
88impl fmt::Display for Block {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        f.write_str("{\n")?;
91
92        let mut iter = self.inner.iter().peekable();
93        while let Some(expr) = iter.next() {
94            f.write_str("\t")?;
95            expr.fmt(f)?;
96            if iter.peek().is_some() {
97                f.write_str("\n")?;
98            }
99        }
100
101        f.write_str("\n}")
102    }
103}