blob: 1a2818c7d41f9dac5660e6c26ce3132b3e1bf155 [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::*;
92 use {BinOp, Ty};
93 use lit::parsing::lit;
94 use op::parsing::{binop, unop};
95 use ty::parsing::{path, ty};
96
97 named!(pub const_expr -> ConstExpr, do_parse!(
98 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070099 expr_unary
100 |
David Tolnayf43ba802016-10-30 10:20:47 -0700101 expr_lit
102 |
103 expr_path
104 |
105 expr_paren
David Tolnay514f1292017-02-27 12:30:57 -0800106 // Cannot handle ConstExpr::Other here because for example
107 // `[u32; n!()]` would end up successfully parsing `n` as
108 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
109 // are required to handle Other. See ty::parsing::array_len and
110 // data::parsing::discriminant.
David Tolnay3cb23a92016-10-07 23:02:21 -0700111 ) >>
112 many0!(alt!(
113 tap!(args: and_call => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700114 let (args, paren) = args;
115 e = ConstCall {
116 func: Box::new(e),
117 args: args,
118 paren_token: paren,
119 }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700120 })
121 |
122 tap!(more: and_binary => {
123 let (op, other) = more;
Alex Crichton62a0a592017-05-22 13:58:53 -0700124 e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700125 })
126 |
127 tap!(ty: and_cast => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700128 let (ty, token) = ty;
129 e = ConstCast {
130 expr: Box::new(e),
131 ty: Box::new(ty),
132 as_token: token,
133 }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700134 })
David Tolnay67588752016-10-30 12:23:10 -0700135 |
136 tap!(i: and_index => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700137 let (i, bracket) = i;
138 e = ConstIndex {
139 expr: Box::new(e),
140 index: Box::new(i),
141 bracket_token: bracket,
142 }.into();
David Tolnay67588752016-10-30 12:23:10 -0700143 })
David Tolnay3cb23a92016-10-07 23:02:21 -0700144 )) >>
145 (e)
146 ));
147
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700148 named!(and_call -> (Delimited<ConstExpr, tokens::Comma>, tokens::Paren), do_parse!(
David Tolnay3cb23a92016-10-07 23:02:21 -0700149 punct!("(") >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700150 args: terminated_list!(map!(punct!(","), |_| tokens::Comma::default()),
151 const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700152 punct!(")") >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700153 (args, tokens::Paren::default())
David Tolnay3cb23a92016-10-07 23:02:21 -0700154 ));
155
156 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
157
158 named!(expr_unary -> ConstExpr, do_parse!(
159 operator: unop >>
160 operand: const_expr >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700161 (ConstUnary { op: operator, expr: Box::new(operand) }.into())
David Tolnay3cb23a92016-10-07 23:02:21 -0700162 ));
163
164 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
165
David Tolnayf43ba802016-10-30 10:20:47 -0700166 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
167
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700168 named!(and_index -> (ConstExpr, tokens::Bracket), do_parse!(
169 punct!("[") >>
170 expr: const_expr >>
171 punct!("]") >>
172 (expr, tokens::Bracket::default())
173 ));
David Tolnay67588752016-10-30 12:23:10 -0700174
David Tolnayf43ba802016-10-30 10:20:47 -0700175 named!(expr_paren -> ConstExpr, do_parse!(
176 punct!("(") >>
177 e: const_expr >>
178 punct!(")") >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700179 (ConstParen {
180 expr: Box::new(e),
181 paren_token: tokens::Paren::default(),
182 }.into())
David Tolnayf43ba802016-10-30 10:20:47 -0700183 ));
184
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700185 named!(and_cast -> (Ty, tokens::As), do_parse!(
David Tolnay3cb23a92016-10-07 23:02:21 -0700186 keyword!("as") >>
187 ty: ty >>
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700188 (ty, tokens::As::default())
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}