prqlc_parser/parser/pr/
expr.rs

1use std::collections::HashMap;
2
3use enum_as_inner::EnumAsInner;
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7use crate::lexer::lr::Literal;
8use crate::parser::pr::ops::{BinOp, UnOp};
9use crate::parser::pr::{Ident, Ty};
10use crate::span::Span;
11use crate::{generic, parser::SupportsDocComment};
12
13impl Expr {
14    pub fn new<K: Into<ExprKind>>(kind: K) -> Self {
15        Expr {
16            kind: kind.into(),
17            span: None,
18            alias: None,
19            doc_comment: None,
20        }
21    }
22}
23
24// The following code is tested by the tests_misc crate to match expr.rs in prqlc.
25
26/// Expr is anything that has a value and thus a type.
27/// Most of these can contain other [Expr] themselves; literals should be [ExprKind::Literal].
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
29pub struct Expr {
30    #[serde(flatten)]
31    pub kind: ExprKind,
32
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub span: Option<Span>,
35
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub alias: Option<String>,
38
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub doc_comment: Option<String>,
41}
42
43impl SupportsDocComment for Expr {
44    fn with_doc_comment(self, doc_comment: Option<String>) -> Self {
45        Self {
46            doc_comment,
47            ..self
48        }
49    }
50}
51
52#[derive(
53    Debug, EnumAsInner, PartialEq, Clone, Serialize, Deserialize, strum::AsRefStr, JsonSchema,
54)]
55pub enum ExprKind {
56    Ident(Ident),
57
58    #[cfg_attr(
59        feature = "serde_yaml",
60        serde(with = "serde_yaml::with::singleton_map"),
61        schemars(with = "Literal")
62    )]
63    Literal(Literal),
64    Pipeline(Pipeline),
65
66    Tuple(Vec<Expr>),
67    Array(Vec<Expr>),
68    Range(Range),
69    Binary(BinaryExpr),
70    Unary(UnaryExpr),
71    FuncCall(FuncCall),
72    Func(Box<Func>),
73    SString(Vec<InterpolateItem>),
74    FString(Vec<InterpolateItem>),
75    Case(Vec<SwitchCase>),
76
77    /// placeholder for values provided after query is compiled
78    Param(String),
79
80    /// When used instead of function body, the function will be translated to a RQ operator.
81    /// Contains ident of the RQ operator.
82    Internal(String),
83}
84
85impl ExprKind {
86    pub fn into_expr(self, span: Span) -> Expr {
87        Expr {
88            span: Some(span),
89            kind: self,
90            alias: None,
91            doc_comment: None,
92        }
93    }
94}
95
96#[derive(Debug, EnumAsInner, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
97pub enum IndirectionKind {
98    Name(String),
99    Position(i64),
100    Star,
101}
102
103/// Expression with two operands and an operator, such as `1 + 2`.
104#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
105pub struct BinaryExpr {
106    pub left: Box<Expr>,
107    pub op: BinOp,
108    pub right: Box<Expr>,
109}
110
111/// Expression with one operand and an operator, such as `-1`.
112#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
113pub struct UnaryExpr {
114    pub op: UnOp,
115    pub expr: Box<Expr>,
116}
117
118/// Function call.
119#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
120pub struct FuncCall {
121    pub name: Box<Expr>,
122    pub args: Vec<Expr>,
123    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
124    pub named_args: HashMap<String, Expr>,
125}
126
127/// Function called with possibly missing positional arguments.
128/// May also contain environment that is needed to evaluate the body.
129#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
130pub struct Func {
131    /// Type requirement for the function body expression.
132    pub return_ty: Option<Ty>,
133
134    /// Expression containing parameter (and environment) references.
135    pub body: Box<Expr>,
136
137    /// Positional function parameters.
138    pub params: Vec<FuncParam>,
139
140    /// Named function parameters.
141    pub named_params: Vec<FuncParam>,
142}
143
144#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
145pub struct FuncParam {
146    pub name: String,
147
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub ty: Option<Ty>,
150
151    pub default_value: Option<Box<Expr>>,
152}
153
154#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
155pub struct GenericTypeParam {
156    /// Assigned name of this generic type argument.
157    pub name: String,
158
159    pub domain: Vec<Ty>,
160}
161
162/// A value and a series of functions that are to be applied to that value one after another.
163#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
164pub struct Pipeline {
165    pub exprs: Vec<Expr>,
166}
167
168pub type Range = generic::Range<Box<Expr>>;
169pub type InterpolateItem = generic::InterpolateItem<Expr>;
170pub type SwitchCase = generic::SwitchCase<Box<Expr>>;
171
172impl From<Literal> for ExprKind {
173    fn from(value: Literal) -> Self {
174        ExprKind::Literal(value)
175    }
176}
177
178impl From<Func> for ExprKind {
179    fn from(value: Func) -> Self {
180        ExprKind::Func(Box::new(value))
181    }
182}