use chrono::FixedOffset;
use serde::{Deserialize, Serialize};
use super::{
AttributeBlock, Call, CellPath, Expression, ExternalArgument, FullCellPath, Keyword,
MatchPattern, Operator, Range, Table, ValueWithUnit,
};
use crate::{
BlockId, ModuleId, OutDest, Signature, Span, VarId, ast::ImportPattern, engine::StateWorkingSet,
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expr {
AttributeBlock(AttributeBlock),
Bool(bool),
Int(i64),
Float(f64),
Binary(Vec<u8>),
Range(Box<Range>),
Var(VarId),
VarDecl(VarId),
Call(Box<Call>),
ExternalCall(Box<Expression>, Box<[ExternalArgument]>), Operator(Operator),
RowCondition(BlockId),
UnaryNot(Box<Expression>),
BinaryOp(Box<Expression>, Box<Expression>, Box<Expression>), Collect(VarId, Box<Expression>),
Subexpression(BlockId),
Block(BlockId),
Closure(BlockId),
MatchBlock(Vec<(MatchPattern, Expression)>),
List(Vec<ListItem>),
Table(Table),
Record(Vec<RecordItem>),
Keyword(Box<Keyword>),
ValueWithUnit(Box<ValueWithUnit>),
DateTime(chrono::DateTime<FixedOffset>),
Filepath(String, bool),
Directory(String, bool),
GlobPattern(String, bool),
String(String),
RawString(String),
CellPath(CellPath),
FullCellPath(Box<FullCellPath>),
ImportPattern(Box<ImportPattern>),
Overlay(Option<ModuleId>),
Signature(Box<Signature>),
StringInterpolation(Vec<Expression>),
GlobInterpolation(Vec<Expression>, bool),
Nothing,
Garbage,
}
const _: () = assert!(std::mem::size_of::<Expr>() <= 40);
impl Expr {
pub fn description(&self) -> &str {
match self {
Expr::AttributeBlock(_) => "an attribute block",
Expr::Bool(_) => "a boolean",
Expr::Int(_) => "an integer",
Expr::Float(_) => "a float",
Expr::Binary(_) => "a binary value",
Expr::Range(_) => "a range",
Expr::Var(_) => "a variable",
Expr::VarDecl(_) => "a variable declaration",
Expr::Call(_) => "a command call",
Expr::ExternalCall(_, _) => "an external command call",
Expr::Operator(_) => "an operator",
Expr::RowCondition(_) => "a row condition",
Expr::UnaryNot(_) => "a negation",
Expr::BinaryOp(_, _, _) => "a binary operation",
Expr::Collect(_, _) => "a collect expression",
Expr::Subexpression(_) => "a subexpression",
Expr::Block(_) => "a block",
Expr::Closure(_) => "a closure",
Expr::MatchBlock(_) => "a match block",
Expr::List(_) => "a list",
Expr::Table(_) => "a table",
Expr::Record(_) => "a record",
Expr::Keyword(_) => "a keyword",
Expr::ValueWithUnit(_) => "a value with unit",
Expr::DateTime(_) => "a datetime",
Expr::Filepath(_, _) => "a filepath",
Expr::Directory(_, _) => "a directory",
Expr::GlobPattern(_, _) => "a glob pattern",
Expr::String(_) => "a string",
Expr::RawString(_) => "a raw string",
Expr::CellPath(_) => "a cell path",
Expr::FullCellPath(_) => "a cell path expression",
Expr::ImportPattern(_) => "an import pattern",
Expr::Overlay(_) => "an overlay",
Expr::Signature(_) => "a signature",
Expr::StringInterpolation(_) => "a string interpolation",
Expr::GlobInterpolation(_, _) => "a glob interpolation",
Expr::Nothing => "a nothing",
Expr::Garbage => "a garbage expression",
}
}
pub fn pipe_redirection(
&self,
working_set: &StateWorkingSet,
) -> (Option<OutDest>, Option<OutDest>) {
match self {
Expr::AttributeBlock(ab) => ab.item.expr.pipe_redirection(working_set),
Expr::Call(call) => working_set.get_decl(call.decl_id).pipe_redirection(),
Expr::Collect(_, _) => {
(None, None)
},
Expr::Subexpression(block_id) | Expr::Block(block_id) => working_set
.get_block(*block_id)
.pipe_redirection(working_set),
Expr::FullCellPath(cell_path) => cell_path.head.expr.pipe_redirection(working_set),
Expr::Bool(_)
| Expr::Int(_)
| Expr::Float(_)
| Expr::Binary(_)
| Expr::Range(_)
| Expr::Var(_)
| Expr::UnaryNot(_)
| Expr::BinaryOp(_, _, _)
| Expr::Closure(_) | Expr::List(_)
| Expr::Table(_)
| Expr::Record(_)
| Expr::ValueWithUnit(_)
| Expr::DateTime(_)
| Expr::String(_)
| Expr::RawString(_)
| Expr::CellPath(_)
| Expr::StringInterpolation(_)
| Expr::GlobInterpolation(_, _)
| Expr::Nothing => {
(None, None)
}
Expr::VarDecl(_)
| Expr::Operator(_)
| Expr::Filepath(_, _)
| Expr::Directory(_, _)
| Expr::GlobPattern(_, _)
| Expr::ImportPattern(_)
| Expr::Overlay(_)
| Expr::Signature(_)
| Expr::Garbage => {
(Some(OutDest::Null), None)
}
Expr::RowCondition(_) | Expr::MatchBlock(_) => {
(None, None)
}
Expr::ExternalCall(_, _) => {
(None, None)
}
Expr::Keyword(_) => {
(None, None)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum RecordItem {
Pair(Expression, Expression),
Spread(Span, Expression),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ListItem {
Item(Expression),
Spread(Span, Expression),
}
impl ListItem {
pub fn expr(&self) -> &Expression {
let (ListItem::Item(expr) | ListItem::Spread(_, expr)) = self;
expr
}
pub fn expr_mut(&mut self) -> &mut Expression {
let (ListItem::Item(expr) | ListItem::Spread(_, expr)) = self;
expr
}
}