1use chrono::FixedOffset;
2use serde::{Deserialize, Serialize};
3
4use super::{
5 AttributeBlock, Call, CellPath, Expression, ExternalArgument, FullCellPath, Keyword,
6 MatchPattern, Operator, Range, Table, ValueWithUnit,
7};
8use crate::{
9 BlockId, ModuleId, OutDest, Signature, Span, VarId, ast::ImportPattern, engine::StateWorkingSet,
10};
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub enum Expr {
15 AttributeBlock(AttributeBlock),
16 Bool(bool),
17 Int(i64),
18 Float(f64),
19 Binary(Vec<u8>),
20 Range(Box<Range>),
21 Var(VarId),
22 VarDecl(VarId),
23 Call(Box<Call>),
24 ExternalCall(Box<Expression>, Box<[ExternalArgument]>), Operator(Operator),
26 RowCondition(BlockId),
27 UnaryNot(Box<Expression>),
28 BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), Collect(VarId, Box<Expression>),
30 Subexpression(BlockId),
31 Block(BlockId),
32 Closure(BlockId),
33 MatchBlock(Vec<(MatchPattern, Expression)>),
34 List(Vec<ListItem>),
35 Table(Table),
36 Record(Vec<RecordItem>),
37 Keyword(Box<Keyword>),
38 ValueWithUnit(Box<ValueWithUnit>),
39 DateTime(chrono::DateTime<FixedOffset>),
40 Filepath(String, bool),
42 Directory(String, bool),
44 GlobPattern(String, bool),
46 String(String),
47 RawString(String),
48 CellPath(CellPath),
49 FullCellPath(Box<FullCellPath>),
50 ImportPattern(Box<ImportPattern>),
51 Overlay(Option<ModuleId>),
52 Signature(Box<Signature>),
53 StringInterpolation(Vec<Expression>),
54 GlobInterpolation(Vec<Expression>, bool),
56 Nothing,
57 Garbage,
58}
59
60const _: () = assert!(std::mem::size_of::<Expr>() <= 40);
64
65impl Expr {
66 pub fn description(&self) -> &str {
71 match self {
72 Expr::AttributeBlock(_) => "an attribute block",
73 Expr::Bool(_) => "a boolean",
74 Expr::Int(_) => "an integer",
75 Expr::Float(_) => "a float",
76 Expr::Binary(_) => "a binary value",
77 Expr::Range(_) => "a range",
78 Expr::Var(_) => "a variable",
79 Expr::VarDecl(_) => "a variable declaration",
80 Expr::Call(_) => "a command call",
81 Expr::ExternalCall(_, _) => "an external command call",
82 Expr::Operator(_) => "an operator",
83 Expr::RowCondition(_) => "a row condition",
84 Expr::UnaryNot(_) => "a negation",
85 Expr::BinaryOp(_, _, _) => "a binary operation",
86 Expr::Collect(_, _) => "a collect expression",
87 Expr::Subexpression(_) => "a subexpression",
88 Expr::Block(_) => "a block",
89 Expr::Closure(_) => "a closure",
90 Expr::MatchBlock(_) => "a match block",
91 Expr::List(_) => "a list",
92 Expr::Table(_) => "a table",
93 Expr::Record(_) => "a record",
94 Expr::Keyword(_) => "a keyword",
95 Expr::ValueWithUnit(_) => "a value with unit",
96 Expr::DateTime(_) => "a datetime",
97 Expr::Filepath(_, _) => "a filepath",
98 Expr::Directory(_, _) => "a directory",
99 Expr::GlobPattern(_, _) => "a glob pattern",
100 Expr::String(_) => "a string",
101 Expr::RawString(_) => "a raw string",
102 Expr::CellPath(_) => "a cell path",
103 Expr::FullCellPath(_) => "a cell path expression",
104 Expr::ImportPattern(_) => "an import pattern",
105 Expr::Overlay(_) => "an overlay",
106 Expr::Signature(_) => "a signature",
107 Expr::StringInterpolation(_) => "a string interpolation",
108 Expr::GlobInterpolation(_, _) => "a glob interpolation",
109 Expr::Nothing => "a nothing",
110 Expr::Garbage => "a garbage expression",
111 }
112 }
113
114 pub fn pipe_redirection(
115 &self,
116 working_set: &StateWorkingSet,
117 ) -> (Option<OutDest>, Option<OutDest>) {
118 match self {
119 Expr::AttributeBlock(ab) => ab.item.expr.pipe_redirection(working_set),
120 Expr::Call(call) => working_set.get_decl(call.decl_id).pipe_redirection(),
121 Expr::Collect(_, _) => {
122 (None, None)
125 },
126 Expr::Subexpression(block_id) | Expr::Block(block_id) => working_set
127 .get_block(*block_id)
128 .pipe_redirection(working_set),
129 Expr::FullCellPath(cell_path) => cell_path.head.expr.pipe_redirection(working_set),
130 Expr::Bool(_)
131 | Expr::Int(_)
132 | Expr::Float(_)
133 | Expr::Binary(_)
134 | Expr::Range(_)
135 | Expr::Var(_)
136 | Expr::UnaryNot(_)
137 | Expr::BinaryOp(_, _, _)
138 | Expr::Closure(_) | Expr::List(_)
140 | Expr::Table(_)
141 | Expr::Record(_)
142 | Expr::ValueWithUnit(_)
143 | Expr::DateTime(_)
144 | Expr::String(_)
145 | Expr::RawString(_)
146 | Expr::CellPath(_)
147 | Expr::StringInterpolation(_)
148 | Expr::GlobInterpolation(_, _)
149 | Expr::Nothing => {
150 (None, None)
154 }
155 Expr::VarDecl(_)
156 | Expr::Operator(_)
157 | Expr::Filepath(_, _)
158 | Expr::Directory(_, _)
159 | Expr::GlobPattern(_, _)
160 | Expr::ImportPattern(_)
161 | Expr::Overlay(_)
162 | Expr::Signature(_)
163 | Expr::Garbage => {
164 (Some(OutDest::Null), None)
167 }
168 Expr::RowCondition(_) | Expr::MatchBlock(_) => {
169 (None, None)
172 }
173 Expr::ExternalCall(_, _) => {
174 (None, None)
176 }
177 Expr::Keyword(_) => {
178 (None, None)
180 }
181 }
182 }
183}
184
185#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
187pub enum RecordItem {
188 Pair(Expression, Expression),
190 Spread(Span, Expression),
192}
193
194#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
196pub enum ListItem {
197 Item(Expression),
199 Spread(Span, Expression),
201}
202
203impl ListItem {
204 pub fn expr(&self) -> &Expression {
205 let (ListItem::Item(expr) | ListItem::Spread(_, expr)) = self;
206 expr
207 }
208
209 pub fn expr_mut(&mut self) -> &mut Expression {
210 let (ListItem::Item(expr) | ListItem::Spread(_, expr)) = self;
211 expr
212 }
213}