vrl/compiler/expression/
block.rs1use 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 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 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}