blob: ad0d325c40ce3de59da2bed4b487fdfbb807a0d1 [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
2
David Tolnay9bf4af82017-01-07 11:17:46 -08003#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnay3cb23a92016-10-07 23:02:21 -07004pub enum ConstExpr {
5 /// A function call
6 ///
7 /// The first field resolves to the function itself,
8 /// and the second field is the list of arguments
9 Call(Box<ConstExpr>, Vec<ConstExpr>),
Clar Charrd22b5702017-03-10 15:24:56 -050010
David Tolnay3cb23a92016-10-07 23:02:21 -070011 /// A binary operation (For example: `a + b`, `a * b`)
12 Binary(BinOp, Box<ConstExpr>, Box<ConstExpr>),
Clar Charrd22b5702017-03-10 15:24:56 -050013
David Tolnay3cb23a92016-10-07 23:02:21 -070014 /// A unary operation (For example: `!x`, `*x`)
15 Unary(UnOp, Box<ConstExpr>),
Clar Charrd22b5702017-03-10 15:24:56 -050016
David Tolnay3cb23a92016-10-07 23:02:21 -070017 /// A literal (For example: `1`, `"foo"`)
18 Lit(Lit),
Clar Charrd22b5702017-03-10 15:24:56 -050019
David Tolnay3cb23a92016-10-07 23:02:21 -070020 /// A cast (`foo as f64`)
21 Cast(Box<ConstExpr>, Box<Ty>),
Clar Charrd22b5702017-03-10 15:24:56 -050022
David Tolnay3cb23a92016-10-07 23:02:21 -070023 /// Variable reference, possibly containing `::` and/or type
24 /// parameters, e.g. foo::bar::<baz>.
25 Path(Path),
Clar Charrd22b5702017-03-10 15:24:56 -050026
David Tolnay67588752016-10-30 12:23:10 -070027 /// An indexing operation (`foo[2]`)
28 Index(Box<ConstExpr>, Box<ConstExpr>),
Clar Charrd22b5702017-03-10 15:24:56 -050029
David Tolnayf43ba802016-10-30 10:20:47 -070030 /// No-op: used solely so we can pretty-print faithfully
31 Paren(Box<ConstExpr>),
Clar Charrd22b5702017-03-10 15:24:56 -050032
David Tolnayfe2cc9a2016-10-30 12:47:36 -070033 /// If compiling with full support for expression syntax, any expression is
34 /// allowed
35 Other(Other),
David Tolnay3cb23a92016-10-07 23:02:21 -070036}
37
David Tolnayfe2cc9a2016-10-30 12:47:36 -070038#[cfg(not(feature = "full"))]
David Tolnay9bf4af82017-01-07 11:17:46 -080039#[derive(Debug, Clone, Eq, PartialEq, Hash)]
David Tolnayfe2cc9a2016-10-30 12:47:36 -070040pub struct Other {
41 _private: (),
42}
43
44#[cfg(feature = "full")]
45pub type Other = Expr;
46
David Tolnay3cb23a92016-10-07 23:02:21 -070047#[cfg(feature = "parsing")]
48pub mod parsing {
49 use super::*;
50 use {BinOp, Ty};
51 use lit::parsing::lit;
52 use op::parsing::{binop, unop};
53 use ty::parsing::{path, ty};
54
55 named!(pub const_expr -> ConstExpr, do_parse!(
56 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070057 expr_unary
58 |
David Tolnayf43ba802016-10-30 10:20:47 -070059 expr_lit
60 |
61 expr_path
62 |
63 expr_paren
David Tolnay514f1292017-02-27 12:30:57 -080064 // Cannot handle ConstExpr::Other here because for example
65 // `[u32; n!()]` would end up successfully parsing `n` as
66 // ConstExpr::Path and then fail to parse `!()`. Instead, callers
67 // are required to handle Other. See ty::parsing::array_len and
68 // data::parsing::discriminant.
David Tolnay3cb23a92016-10-07 23:02:21 -070069 ) >>
70 many0!(alt!(
71 tap!(args: and_call => {
72 e = ConstExpr::Call(Box::new(e), args);
73 })
74 |
75 tap!(more: and_binary => {
76 let (op, other) = more;
77 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
78 })
79 |
80 tap!(ty: and_cast => {
81 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
82 })
David Tolnay67588752016-10-30 12:23:10 -070083 |
84 tap!(i: and_index => {
85 e = ConstExpr::Index(Box::new(e), Box::new(i));
86 })
David Tolnay3cb23a92016-10-07 23:02:21 -070087 )) >>
88 (e)
89 ));
90
91 named!(and_call -> Vec<ConstExpr>, do_parse!(
92 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -070093 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -070094 punct!(")") >>
95 (args)
96 ));
97
98 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
99
100 named!(expr_unary -> ConstExpr, do_parse!(
101 operator: unop >>
102 operand: const_expr >>
103 (ConstExpr::Unary(operator, Box::new(operand)))
104 ));
105
106 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
107
David Tolnayf43ba802016-10-30 10:20:47 -0700108 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
109
David Tolnay67588752016-10-30 12:23:10 -0700110 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
111
David Tolnayf43ba802016-10-30 10:20:47 -0700112 named!(expr_paren -> ConstExpr, do_parse!(
113 punct!("(") >>
114 e: const_expr >>
115 punct!(")") >>
116 (ConstExpr::Paren(Box::new(e)))
117 ));
118
David Tolnay3cb23a92016-10-07 23:02:21 -0700119 named!(and_cast -> Ty, do_parse!(
120 keyword!("as") >>
121 ty: ty >>
122 (ty)
123 ));
124}
125
126#[cfg(feature = "printing")]
127mod printing {
128 use super::*;
129 use quote::{Tokens, ToTokens};
130
131 impl ToTokens for ConstExpr {
132 fn to_tokens(&self, tokens: &mut Tokens) {
133 match *self {
134 ConstExpr::Call(ref func, ref args) => {
135 func.to_tokens(tokens);
136 tokens.append("(");
137 tokens.append_separated(args, ",");
138 tokens.append(")");
139 }
140 ConstExpr::Binary(op, ref left, ref right) => {
141 left.to_tokens(tokens);
142 op.to_tokens(tokens);
143 right.to_tokens(tokens);
144 }
145 ConstExpr::Unary(op, ref expr) => {
146 op.to_tokens(tokens);
147 expr.to_tokens(tokens);
148 }
149 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
150 ConstExpr::Cast(ref expr, ref ty) => {
151 expr.to_tokens(tokens);
152 tokens.append("as");
153 ty.to_tokens(tokens);
154 }
155 ConstExpr::Path(ref path) => path.to_tokens(tokens),
David Tolnay67588752016-10-30 12:23:10 -0700156 ConstExpr::Index(ref expr, ref index) => {
157 expr.to_tokens(tokens);
158 tokens.append("[");
159 index.to_tokens(tokens);
160 tokens.append("]");
161 }
David Tolnayf43ba802016-10-30 10:20:47 -0700162 ConstExpr::Paren(ref expr) => {
163 tokens.append("(");
164 expr.to_tokens(tokens);
165 tokens.append(")");
166 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700167 ConstExpr::Other(ref other) => {
168 other.to_tokens(tokens);
169 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700170 }
171 }
172 }
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700173
174 #[cfg(not(feature = "full"))]
175 impl ToTokens for Other {
176 fn to_tokens(&self, _tokens: &mut Tokens) {
177 unreachable!()
178 }
179 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700180}