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::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(String),
57
58    /// A lookup into an object by name or position.
59    /// Currently, this includes only tuple field lookups, primarily by name.
60    Indirection {
61        base: Box<Expr>,
62        field: IndirectionKind,
63    },
64    #[cfg_attr(
65        feature = "serde_yaml",
66        serde(with = "serde_yaml::with::singleton_map"),
67        schemars(with = "Literal")
68    )]
69    Literal(Literal),
70    Pipeline(Pipeline),
71
72    Tuple(Vec<Expr>),
73    Array(Vec<Expr>),
74    Range(Range),
75    Binary(BinaryExpr),
76    Unary(UnaryExpr),
77    FuncCall(FuncCall),
78    Func(Box<Func>),
79    SString(Vec<InterpolateItem>),
80    FString(Vec<InterpolateItem>),
81    Case(Vec<SwitchCase>),
82
83    /// placeholder for values provided after query is compiled
84    Param(String),
85
86    /// When used instead of function body, the function will be translated to a RQ operator.
87    /// Contains ident of the RQ operator.
88    Internal(String),
89}
90
91impl ExprKind {
92    pub fn into_expr(self, span: Span) -> Expr {
93        Expr {
94            span: Some(span),
95            kind: self,
96            alias: None,
97            doc_comment: None,
98        }
99    }
100}
101
102#[derive(Debug, EnumAsInner, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
103pub enum IndirectionKind {
104    Name(String),
105    Position(i64),
106    Star,
107}
108
109/// Expression with two operands and an operator, such as `1 + 2`.
110#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
111pub struct BinaryExpr {
112    pub left: Box<Expr>,
113    pub op: BinOp,
114    pub right: Box<Expr>,
115}
116
117/// Expression with one operand and an operator, such as `-1`.
118#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
119pub struct UnaryExpr {
120    pub op: UnOp,
121    pub expr: Box<Expr>,
122}
123
124/// Function call.
125#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
126pub struct FuncCall {
127    pub name: Box<Expr>,
128    pub args: Vec<Expr>,
129    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
130    pub named_args: HashMap<String, Expr>,
131}
132
133/// Function called with possibly missing positional arguments.
134/// May also contain environment that is needed to evaluate the body.
135#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
136pub struct Func {
137    /// Type requirement for the function body expression.
138    pub return_ty: Option<Ty>,
139
140    /// Expression containing parameter (and environment) references.
141    pub body: Box<Expr>,
142
143    /// Positional function parameters.
144    pub params: Vec<FuncParam>,
145
146    /// Named function parameters.
147    pub named_params: Vec<FuncParam>,
148
149    /// Generic type arguments within this function.
150    pub generic_type_params: Vec<GenericTypeParam>,
151}
152
153#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
154pub struct FuncParam {
155    pub name: String,
156
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub ty: Option<Ty>,
159
160    pub default_value: Option<Box<Expr>>,
161}
162
163#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
164pub struct GenericTypeParam {
165    /// Assigned name of this generic type argument.
166    pub name: String,
167
168    pub domain: Vec<Ty>,
169}
170
171/// A value and a series of functions that are to be applied to that value one after another.
172#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
173pub struct Pipeline {
174    pub exprs: Vec<Expr>,
175}
176
177pub type Range = generic::Range<Box<Expr>>;
178pub type InterpolateItem = generic::InterpolateItem<Expr>;
179pub type SwitchCase = generic::SwitchCase<Box<Expr>>;
180
181impl From<Literal> for ExprKind {
182    fn from(value: Literal) -> Self {
183        ExprKind::Literal(value)
184    }
185}
186
187impl From<Func> for ExprKind {
188    fn from(value: Func) -> Self {
189        ExprKind::Func(Box::new(value))
190    }
191}