blob: d3991b70c4d7229e5f6ffec9168be3cf2730fecb [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002use delimited::Delimited;
David Tolnay3cb23a92016-10-07 23:02:21 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_enum_of_structs! {
5 pub enum ConstExpr {
6 /// A function call
7 pub Call(ConstCall {
8 /// The function being called
9 pub func: Box<ConstExpr>,
Clar Charrd22b5702017-03-10 15:24:56 -050010
Alex Crichton62a0a592017-05-22 13:58:53 -070011 /// The arguments to the function being called
Alex Crichtonccbb45d2017-05-23 10:58:24 -070012 pub args: Delimited<ConstExpr, tokens::Comma>,
13
14 pub paren_token: tokens::Paren,
Alex Crichton62a0a592017-05-22 13:58:53 -070015 }),
Clar Charrd22b5702017-03-10 15:24:56 -050016
Alex Crichton62a0a592017-05-22 13:58:53 -070017 /// A binary operation (For example: `a + b`, `a * b`)
18 pub Binary(ConstBinary {
19 /// The binary operation this represents
20 pub op: BinOp,
Clar Charrd22b5702017-03-10 15:24:56 -050021
Alex Crichton62a0a592017-05-22 13:58:53 -070022 /// The left-hand-side of the constant binary op
23 pub left: Box<ConstExpr>,
Clar Charrd22b5702017-03-10 15:24:56 -050024
Alex Crichton62a0a592017-05-22 13:58:53 -070025 /// The right-hand-side of the constant binary op
26 pub right: Box<ConstExpr>,
27 }),
Clar Charrd22b5702017-03-10 15:24:56 -050028
Alex Crichton62a0a592017-05-22 13:58:53 -070029 /// A unary operation (For example: `!x`, `*x`)
30 pub Unary(ConstUnary {
31 /// Operation being performed
32 pub op: UnOp,
Clar Charrd22b5702017-03-10 15:24:56 -050033
Alex Crichton62a0a592017-05-22 13:58:53 -070034 /// Expression acted on
35 pub expr: Box<ConstExpr>,
36 }),
Clar Charrd22b5702017-03-10 15:24:56 -050037
Alex Crichton62a0a592017-05-22 13:58:53 -070038 /// A literal (For example: `1`, `"foo"`)
39 pub Lit(Lit),
Clar Charrd22b5702017-03-10 15:24:56 -050040
Alex Crichton62a0a592017-05-22 13:58:53 -070041 /// A cast (`foo as f64`)
42 pub Cast(ConstCast {
43 /// Value being casted
44 pub expr: Box<ConstExpr>,
45
46 /// Type casted to
47 pub ty: Box<Ty>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070048
49 pub as_token: tokens::As,
Alex Crichton62a0a592017-05-22 13:58:53 -070050 }),
51
52 /// Variable reference, possibly containing `::` and/or type
53 /// parameters, e.g. foo::bar::<baz>.
54 pub Path(Path),
55
56 /// An indexing operation (`foo[2]`)
57 pub Index(ConstIndex {
58 /// Value that is being indexed
59 pub expr: Box<ConstExpr>,
60
61 /// Index expression
62 pub index: Box<ConstExpr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070063
64 pub bracket_token: tokens::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -070065 }),
66
67 /// No-op: used solely so we can pretty-print faithfully
68 pub Paren(ConstParen {
69 /// Expression that's parenthesized
70 pub expr: Box<ConstExpr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 pub paren_token: tokens::Paren,
Alex Crichton62a0a592017-05-22 13:58:53 -070072 }),
73
74 /// If compiling with full support for expression syntax, any expression is
75 /// allowed
76 pub Other(Other),
77 }
David Tolnay3cb23a92016-10-07 23:02:21 -070078}
79
David Tolnayfe2cc9a2016-10-30 12:47:36 -070080#[cfg(not(feature = "full"))]
David Tolnay9bf4af82017-01-07 11:17:46 -080081#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayfe2cc9a2016-10-30 12:47:36 -070082pub struct Other {
83 _private: (),
84}
85
86#[cfg(feature = "full")]
87pub type Other = Expr;
88
David Tolnay3cb23a92016-10-07 23:02:21 -070089#[cfg(feature = "parsing")]
90pub mod parsing {
91 use super::*;
Michael Layzell92639a52017-06-01 00:07:44 -040092 use synom::Synom;
Alex Crichton954046c2017-05-30 21:49:42 -070093 use synom::tokens::*;
David Tolnay3cb23a92016-10-07 23:02:21 -070094
Alex Crichton954046c2017-05-30 21:49:42 -070095 impl Synom for ConstExpr {
Michael Layzell92639a52017-06-01 00:07:44 -040096 named!(parse -> Self, do_parse!(
97 mut e: alt!(
98 map!(syn!(ConstUnary), |e: ConstUnary| e.into())
99 |
100 map!(syn!(Lit), |e: Lit| e.into())
101 |
102 map!(syn!(Path), |e: Path| e.into())
103 |
104 map!(syn!(ConstParen), |e: ConstParen| e.into())
105 // Cannot handle ConstExpr::Other here because for example
106 // `[u32; n!()]` would end up successfully parsing `n` as
107 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
108 // are required to handle Other. See ty::parsing::array_len and
109 // data::parsing::discriminant.
110 ) >>
111 many0!(alt!(
112 tap!(args: and_call => {
113 let (args, paren) = args;
114 e = ConstCall {
115 func: Box::new(e),
116 args: args,
117 paren_token: paren,
118 }.into();
119 })
120 |
121 tap!(more: and_binary => {
122 let (op, other) = more;
123 e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
124 })
125 |
126 tap!(ty: and_cast => {
127 let (ty, token) = ty;
128 e = ConstCast {
129 expr: Box::new(e),
130 ty: Box::new(ty),
131 as_token: token,
132 }.into();
133 })
134 |
135 tap!(i: and_index => {
136 let (i, bracket) = i;
137 e = ConstIndex {
138 expr: Box::new(e),
139 index: Box::new(i),
140 bracket_token: bracket,
141 }.into();
142 })
143 )) >>
144 (e)
145 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700146 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700147
Alex Crichton954046c2017-05-30 21:49:42 -0700148 named!(and_call -> (Delimited<ConstExpr, tokens::Comma>, tokens::Paren),
149 parens!(call!(Delimited::parse_terminated)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700150
Alex Crichton954046c2017-05-30 21:49:42 -0700151 named!(and_binary -> (BinOp, ConstExpr),
152 tuple!(call!(BinOp::parse_binop), syn!(ConstExpr)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700153
Alex Crichton954046c2017-05-30 21:49:42 -0700154 impl Synom for ConstUnary {
Michael Layzell92639a52017-06-01 00:07:44 -0400155 named!(parse -> Self, do_parse!(
156 operator: syn!(UnOp) >>
157 operand: syn!(ConstExpr) >>
158 (ConstUnary { op: operator, expr: Box::new(operand) })
159 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700160 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700161
Alex Crichton954046c2017-05-30 21:49:42 -0700162 named!(and_index -> (ConstExpr, tokens::Bracket),
163 brackets!(syn!(ConstExpr)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700164
Alex Crichton954046c2017-05-30 21:49:42 -0700165 impl Synom for ConstParen {
Michael Layzell92639a52017-06-01 00:07:44 -0400166 named!(parse -> Self, do_parse!(
167 parens: parens!(syn!(ConstExpr)) >>
168 (ConstParen {
169 expr: Box::new(parens.0),
170 paren_token: parens.1,
171 })
172 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700173 }
David Tolnayf43ba802016-10-30 10:20:47 -0700174
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700175 named!(and_cast -> (Ty, tokens::As), do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -0700176 as_tok: syn!(As) >>
177 ty: syn!(Ty) >>
178 (ty, as_tok)
David Tolnay3cb23a92016-10-07 23:02:21 -0700179 ));
180}
181
182#[cfg(feature = "printing")]
183mod printing {
184 use super::*;
185 use quote::{Tokens, ToTokens};
186
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 impl ToTokens for ConstCall {
David Tolnay3cb23a92016-10-07 23:02:21 -0700188 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700189 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700190 self.paren_token.surround(tokens, |tokens| {
191 self.args.to_tokens(tokens);
192 })
Alex Crichton62a0a592017-05-22 13:58:53 -0700193 }
194 }
195
196 impl ToTokens for ConstBinary {
197 fn to_tokens(&self, tokens: &mut Tokens) {
198 self.left.to_tokens(tokens);
199 self.op.to_tokens(tokens);
200 self.right.to_tokens(tokens);
201 }
202 }
203
204 impl ToTokens for ConstUnary {
205 fn to_tokens(&self, tokens: &mut Tokens) {
206 self.op.to_tokens(tokens);
207 self.expr.to_tokens(tokens);
208 }
209 }
210
211 impl ToTokens for ConstCast {
212 fn to_tokens(&self, tokens: &mut Tokens) {
213 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700214 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -0700215 self.ty.to_tokens(tokens);
216 }
217 }
218
219 impl ToTokens for ConstIndex {
220 fn to_tokens(&self, tokens: &mut Tokens) {
221 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700222 self.bracket_token.surround(tokens, |tokens| {
223 self.index.to_tokens(tokens);
224 })
Alex Crichton62a0a592017-05-22 13:58:53 -0700225 }
226 }
227
228 impl ToTokens for ConstParen {
229 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700230 self.paren_token.surround(tokens, |tokens| {
231 self.expr.to_tokens(tokens);
232 })
David Tolnay3cb23a92016-10-07 23:02:21 -0700233 }
234 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700235
236 #[cfg(not(feature = "full"))]
237 impl ToTokens for Other {
238 fn to_tokens(&self, _tokens: &mut Tokens) {
239 unreachable!()
240 }
241 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700242}