blob: d76a82761d46875f9d131a4329ebea277192ca54 [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::*;
Alex Crichton954046c2017-05-30 21:49:42 -070092 use proc_macro2::TokenTree;
93 use synom::{IResult, Synom};
94 use synom::tokens::*;
David Tolnay3cb23a92016-10-07 23:02:21 -070095
Alex Crichton954046c2017-05-30 21:49:42 -070096 impl Synom for ConstExpr {
97 fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
98 do_parse! {
99 input,
100 mut e: alt!(
101 map!(syn!(ConstUnary), |e: ConstUnary| e.into())
102 |
103 map!(syn!(Lit), |e: Lit| e.into())
104 |
105 map!(syn!(Path), |e: Path| e.into())
106 |
107 map!(syn!(ConstParen), |e: ConstParen| e.into())
108 // Cannot handle ConstExpr::Other here because for example
109 // `[u32; n!()]` would end up successfully parsing `n` as
110 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
111 // are required to handle Other. See ty::parsing::array_len and
112 // data::parsing::discriminant.
113 ) >>
114 many0!(alt!(
115 tap!(args: and_call => {
116 let (args, paren) = args;
117 e = ConstCall {
118 func: Box::new(e),
119 args: args,
120 paren_token: paren,
121 }.into();
122 })
123 |
124 tap!(more: and_binary => {
125 let (op, other) = more;
126 e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
127 })
128 |
129 tap!(ty: and_cast => {
130 let (ty, token) = ty;
131 e = ConstCast {
132 expr: Box::new(e),
133 ty: Box::new(ty),
134 as_token: token,
135 }.into();
136 })
137 |
138 tap!(i: and_index => {
139 let (i, bracket) = i;
140 e = ConstIndex {
141 expr: Box::new(e),
142 index: Box::new(i),
143 bracket_token: bracket,
144 }.into();
145 })
146 )) >>
147 (e)
148 }
149 }
150 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700151
Alex Crichton954046c2017-05-30 21:49:42 -0700152 named!(and_call -> (Delimited<ConstExpr, tokens::Comma>, tokens::Paren),
153 parens!(call!(Delimited::parse_terminated)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700154
Alex Crichton954046c2017-05-30 21:49:42 -0700155 named!(and_binary -> (BinOp, ConstExpr),
156 tuple!(call!(BinOp::parse_binop), syn!(ConstExpr)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700157
Alex Crichton954046c2017-05-30 21:49:42 -0700158 impl Synom for ConstUnary {
159 fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
160 do_parse! {
161 input,
162 operator: syn!(UnOp) >>
163 operand: syn!(ConstExpr) >>
164 (ConstUnary { op: operator, expr: Box::new(operand) })
165 }
166 }
167 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700168
Alex Crichton954046c2017-05-30 21:49:42 -0700169 named!(and_index -> (ConstExpr, tokens::Bracket),
170 brackets!(syn!(ConstExpr)));
David Tolnay3cb23a92016-10-07 23:02:21 -0700171
Alex Crichton954046c2017-05-30 21:49:42 -0700172 impl Synom for ConstParen {
173 fn parse(input: &[TokenTree]) -> IResult<&[TokenTree], Self> {
174 do_parse! {
175 input,
176 parens: parens!(syn!(ConstExpr)) >>
177 (ConstParen {
178 expr: Box::new(parens.0),
179 paren_token: parens.1,
180 })
181 }
182 }
183 }
David Tolnayf43ba802016-10-30 10:20:47 -0700184
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700185 named!(and_cast -> (Ty, tokens::As), do_parse!(
Alex Crichton954046c2017-05-30 21:49:42 -0700186 as_tok: syn!(As) >>
187 ty: syn!(Ty) >>
188 (ty, as_tok)
David Tolnay3cb23a92016-10-07 23:02:21 -0700189 ));
190}
191
192#[cfg(feature = "printing")]
193mod printing {
194 use super::*;
195 use quote::{Tokens, ToTokens};
196
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 impl ToTokens for ConstCall {
David Tolnay3cb23a92016-10-07 23:02:21 -0700198 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700199 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700200 self.paren_token.surround(tokens, |tokens| {
201 self.args.to_tokens(tokens);
202 })
Alex Crichton62a0a592017-05-22 13:58:53 -0700203 }
204 }
205
206 impl ToTokens for ConstBinary {
207 fn to_tokens(&self, tokens: &mut Tokens) {
208 self.left.to_tokens(tokens);
209 self.op.to_tokens(tokens);
210 self.right.to_tokens(tokens);
211 }
212 }
213
214 impl ToTokens for ConstUnary {
215 fn to_tokens(&self, tokens: &mut Tokens) {
216 self.op.to_tokens(tokens);
217 self.expr.to_tokens(tokens);
218 }
219 }
220
221 impl ToTokens for ConstCast {
222 fn to_tokens(&self, tokens: &mut Tokens) {
223 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700224 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -0700225 self.ty.to_tokens(tokens);
226 }
227 }
228
229 impl ToTokens for ConstIndex {
230 fn to_tokens(&self, tokens: &mut Tokens) {
231 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700232 self.bracket_token.surround(tokens, |tokens| {
233 self.index.to_tokens(tokens);
234 })
Alex Crichton62a0a592017-05-22 13:58:53 -0700235 }
236 }
237
238 impl ToTokens for ConstParen {
239 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700240 self.paren_token.surround(tokens, |tokens| {
241 self.expr.to_tokens(tokens);
242 })
David Tolnay3cb23a92016-10-07 23:02:21 -0700243 }
244 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700245
246 #[cfg(not(feature = "full"))]
247 impl ToTokens for Other {
248 fn to_tokens(&self, _tokens: &mut Tokens) {
249 unreachable!()
250 }
251 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700252}