blob: 2267b50ed9282adb491aaa12bef6e19dca3f3872 [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
2
Alex Crichton62a0a592017-05-22 13:58:53 -07003ast_enum_of_structs! {
4 pub enum ConstExpr {
5 /// A function call
6 pub Call(ConstCall {
7 /// The function being called
8 pub func: Box<ConstExpr>,
Clar Charrd22b5702017-03-10 15:24:56 -05009
Alex Crichton62a0a592017-05-22 13:58:53 -070010 /// The arguments to the function being called
11 pub args: Vec<ConstExpr>,
12 }),
Clar Charrd22b5702017-03-10 15:24:56 -050013
Alex Crichton62a0a592017-05-22 13:58:53 -070014 /// A binary operation (For example: `a + b`, `a * b`)
15 pub Binary(ConstBinary {
16 /// The binary operation this represents
17 pub op: BinOp,
Clar Charrd22b5702017-03-10 15:24:56 -050018
Alex Crichton62a0a592017-05-22 13:58:53 -070019 /// The left-hand-side of the constant binary op
20 pub left: Box<ConstExpr>,
Clar Charrd22b5702017-03-10 15:24:56 -050021
Alex Crichton62a0a592017-05-22 13:58:53 -070022 /// The right-hand-side of the constant binary op
23 pub right: Box<ConstExpr>,
24 }),
Clar Charrd22b5702017-03-10 15:24:56 -050025
Alex Crichton62a0a592017-05-22 13:58:53 -070026 /// A unary operation (For example: `!x`, `*x`)
27 pub Unary(ConstUnary {
28 /// Operation being performed
29 pub op: UnOp,
Clar Charrd22b5702017-03-10 15:24:56 -050030
Alex Crichton62a0a592017-05-22 13:58:53 -070031 /// Expression acted on
32 pub expr: Box<ConstExpr>,
33 }),
Clar Charrd22b5702017-03-10 15:24:56 -050034
Alex Crichton62a0a592017-05-22 13:58:53 -070035 /// A literal (For example: `1`, `"foo"`)
36 pub Lit(Lit),
Clar Charrd22b5702017-03-10 15:24:56 -050037
Alex Crichton62a0a592017-05-22 13:58:53 -070038 /// A cast (`foo as f64`)
39 pub Cast(ConstCast {
40 /// Value being casted
41 pub expr: Box<ConstExpr>,
42
43 /// Type casted to
44 pub ty: Box<Ty>,
45 }),
46
47 /// Variable reference, possibly containing `::` and/or type
48 /// parameters, e.g. foo::bar::<baz>.
49 pub Path(Path),
50
51 /// An indexing operation (`foo[2]`)
52 pub Index(ConstIndex {
53 /// Value that is being indexed
54 pub expr: Box<ConstExpr>,
55
56 /// Index expression
57 pub index: Box<ConstExpr>,
58 }),
59
60 /// No-op: used solely so we can pretty-print faithfully
61 pub Paren(ConstParen {
62 /// Expression that's parenthesized
63 pub expr: Box<ConstExpr>,
64 }),
65
66 /// If compiling with full support for expression syntax, any expression is
67 /// allowed
68 pub Other(Other),
69 }
David Tolnay3cb23a92016-10-07 23:02:21 -070070}
71
David Tolnayfe2cc9a2016-10-30 12:47:36 -070072#[cfg(not(feature = "full"))]
David Tolnay9bf4af82017-01-07 11:17:46 -080073#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayfe2cc9a2016-10-30 12:47:36 -070074pub struct Other {
75 _private: (),
76}
77
78#[cfg(feature = "full")]
79pub type Other = Expr;
80
David Tolnay3cb23a92016-10-07 23:02:21 -070081#[cfg(feature = "parsing")]
82pub mod parsing {
83 use super::*;
84 use {BinOp, Ty};
85 use lit::parsing::lit;
86 use op::parsing::{binop, unop};
87 use ty::parsing::{path, ty};
88
89 named!(pub const_expr -> ConstExpr, do_parse!(
90 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070091 expr_unary
92 |
David Tolnayf43ba802016-10-30 10:20:47 -070093 expr_lit
94 |
95 expr_path
96 |
97 expr_paren
David Tolnay514f1292017-02-27 12:30:57 -080098 // Cannot handle ConstExpr::Other here because for example
99 // `[u32; n!()]` would end up successfully parsing `n` as
100 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
101 // are required to handle Other. See ty::parsing::array_len and
102 // data::parsing::discriminant.
David Tolnay3cb23a92016-10-07 23:02:21 -0700103 ) >>
104 many0!(alt!(
105 tap!(args: and_call => {
Alex Crichton62a0a592017-05-22 13:58:53 -0700106 e = ConstCall { func: Box::new(e), args: args }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700107 })
108 |
109 tap!(more: and_binary => {
110 let (op, other) = more;
Alex Crichton62a0a592017-05-22 13:58:53 -0700111 e = ConstBinary { op: op, left: Box::new(e), right: Box::new(other) }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700112 })
113 |
114 tap!(ty: and_cast => {
Alex Crichton62a0a592017-05-22 13:58:53 -0700115 e = ConstCast { expr: Box::new(e), ty: Box::new(ty) }.into();
David Tolnay3cb23a92016-10-07 23:02:21 -0700116 })
David Tolnay67588752016-10-30 12:23:10 -0700117 |
118 tap!(i: and_index => {
Alex Crichton62a0a592017-05-22 13:58:53 -0700119 e = ConstIndex { expr: Box::new(e), index: Box::new(i) }.into();
David Tolnay67588752016-10-30 12:23:10 -0700120 })
David Tolnay3cb23a92016-10-07 23:02:21 -0700121 )) >>
122 (e)
123 ));
124
125 named!(and_call -> Vec<ConstExpr>, do_parse!(
126 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700127 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700128 punct!(")") >>
129 (args)
130 ));
131
132 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
133
134 named!(expr_unary -> ConstExpr, do_parse!(
135 operator: unop >>
136 operand: const_expr >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700137 (ConstUnary { op: operator, expr: Box::new(operand) }.into())
David Tolnay3cb23a92016-10-07 23:02:21 -0700138 ));
139
140 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
141
David Tolnayf43ba802016-10-30 10:20:47 -0700142 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
143
David Tolnay67588752016-10-30 12:23:10 -0700144 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
145
David Tolnayf43ba802016-10-30 10:20:47 -0700146 named!(expr_paren -> ConstExpr, do_parse!(
147 punct!("(") >>
148 e: const_expr >>
149 punct!(")") >>
Alex Crichton62a0a592017-05-22 13:58:53 -0700150 (ConstParen { expr: Box::new(e) }.into())
David Tolnayf43ba802016-10-30 10:20:47 -0700151 ));
152
David Tolnay3cb23a92016-10-07 23:02:21 -0700153 named!(and_cast -> Ty, do_parse!(
154 keyword!("as") >>
155 ty: ty >>
156 (ty)
157 ));
158}
159
160#[cfg(feature = "printing")]
161mod printing {
162 use super::*;
163 use quote::{Tokens, ToTokens};
164
Alex Crichton62a0a592017-05-22 13:58:53 -0700165 impl ToTokens for ConstCall {
David Tolnay3cb23a92016-10-07 23:02:21 -0700166 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700167 self.func.to_tokens(tokens);
168 tokens.append("(");
169 tokens.append_separated(&self.args, ",");
170 tokens.append(")");
171 }
172 }
173
174 impl ToTokens for ConstBinary {
175 fn to_tokens(&self, tokens: &mut Tokens) {
176 self.left.to_tokens(tokens);
177 self.op.to_tokens(tokens);
178 self.right.to_tokens(tokens);
179 }
180 }
181
182 impl ToTokens for ConstUnary {
183 fn to_tokens(&self, tokens: &mut Tokens) {
184 self.op.to_tokens(tokens);
185 self.expr.to_tokens(tokens);
186 }
187 }
188
189 impl ToTokens for ConstCast {
190 fn to_tokens(&self, tokens: &mut Tokens) {
191 self.expr.to_tokens(tokens);
192 tokens.append("as");
193 self.ty.to_tokens(tokens);
194 }
195 }
196
197 impl ToTokens for ConstIndex {
198 fn to_tokens(&self, tokens: &mut Tokens) {
199 self.expr.to_tokens(tokens);
200 tokens.append("[");
201 self.index.to_tokens(tokens);
202 tokens.append("]");
203 }
204 }
205
206 impl ToTokens for ConstParen {
207 fn to_tokens(&self, tokens: &mut Tokens) {
208 tokens.append("(");
209 self.expr.to_tokens(tokens);
210 tokens.append(")");
David Tolnay3cb23a92016-10-07 23:02:21 -0700211 }
212 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700213
214 #[cfg(not(feature = "full"))]
215 impl ToTokens for Other {
216 fn to_tokens(&self, _tokens: &mut Tokens) {
217 unreachable!()
218 }
219 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700220}