blob: 1688dbf96f54ebc35c83202b6cf0250feb7cdd5c [file] [log] [blame]
David Tolnay3cb23a92016-10-07 23:02:21 -07001use super::*;
2
3#[derive(Debug, Clone, Eq, PartialEq)]
4pub 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>),
10 /// A binary operation (For example: `a + b`, `a * b`)
11 Binary(BinOp, Box<ConstExpr>, Box<ConstExpr>),
12 /// A unary operation (For example: `!x`, `*x`)
13 Unary(UnOp, Box<ConstExpr>),
14 /// A literal (For example: `1`, `"foo"`)
15 Lit(Lit),
16 /// A cast (`foo as f64`)
17 Cast(Box<ConstExpr>, Box<Ty>),
18 /// Variable reference, possibly containing `::` and/or type
19 /// parameters, e.g. foo::bar::<baz>.
20 Path(Path),
David Tolnay67588752016-10-30 12:23:10 -070021 /// An indexing operation (`foo[2]`)
22 Index(Box<ConstExpr>, Box<ConstExpr>),
David Tolnayf43ba802016-10-30 10:20:47 -070023 /// No-op: used solely so we can pretty-print faithfully
24 Paren(Box<ConstExpr>),
David Tolnay3cb23a92016-10-07 23:02:21 -070025}
26
27#[cfg(feature = "parsing")]
28pub mod parsing {
29 use super::*;
30 use {BinOp, Ty};
31 use lit::parsing::lit;
32 use op::parsing::{binop, unop};
33 use ty::parsing::{path, ty};
34
35 named!(pub const_expr -> ConstExpr, do_parse!(
36 mut e: alt!(
David Tolnay3cb23a92016-10-07 23:02:21 -070037 expr_unary
38 |
David Tolnayf43ba802016-10-30 10:20:47 -070039 expr_lit
40 |
41 expr_path
42 |
43 expr_paren
David Tolnay3cb23a92016-10-07 23:02:21 -070044 ) >>
45 many0!(alt!(
46 tap!(args: and_call => {
47 e = ConstExpr::Call(Box::new(e), args);
48 })
49 |
50 tap!(more: and_binary => {
51 let (op, other) = more;
52 e = ConstExpr::Binary(op, Box::new(e), Box::new(other));
53 })
54 |
55 tap!(ty: and_cast => {
56 e = ConstExpr::Cast(Box::new(e), Box::new(ty));
57 })
David Tolnay67588752016-10-30 12:23:10 -070058 |
59 tap!(i: and_index => {
60 e = ConstExpr::Index(Box::new(e), Box::new(i));
61 })
David Tolnay3cb23a92016-10-07 23:02:21 -070062 )) >>
63 (e)
64 ));
65
66 named!(and_call -> Vec<ConstExpr>, do_parse!(
67 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -070068 args: terminated_list!(punct!(","), const_expr) >>
David Tolnay3cb23a92016-10-07 23:02:21 -070069 punct!(")") >>
70 (args)
71 ));
72
73 named!(and_binary -> (BinOp, ConstExpr), tuple!(binop, const_expr));
74
75 named!(expr_unary -> ConstExpr, do_parse!(
76 operator: unop >>
77 operand: const_expr >>
78 (ConstExpr::Unary(operator, Box::new(operand)))
79 ));
80
81 named!(expr_lit -> ConstExpr, map!(lit, ConstExpr::Lit));
82
David Tolnayf43ba802016-10-30 10:20:47 -070083 named!(expr_path -> ConstExpr, map!(path, ConstExpr::Path));
84
David Tolnay67588752016-10-30 12:23:10 -070085 named!(and_index -> ConstExpr, delimited!(punct!("["), const_expr, punct!("]")));
86
David Tolnayf43ba802016-10-30 10:20:47 -070087 named!(expr_paren -> ConstExpr, do_parse!(
88 punct!("(") >>
89 e: const_expr >>
90 punct!(")") >>
91 (ConstExpr::Paren(Box::new(e)))
92 ));
93
David Tolnay3cb23a92016-10-07 23:02:21 -070094 named!(and_cast -> Ty, do_parse!(
95 keyword!("as") >>
96 ty: ty >>
97 (ty)
98 ));
99}
100
101#[cfg(feature = "printing")]
102mod printing {
103 use super::*;
104 use quote::{Tokens, ToTokens};
105
106 impl ToTokens for ConstExpr {
107 fn to_tokens(&self, tokens: &mut Tokens) {
108 match *self {
109 ConstExpr::Call(ref func, ref args) => {
110 func.to_tokens(tokens);
111 tokens.append("(");
112 tokens.append_separated(args, ",");
113 tokens.append(")");
114 }
115 ConstExpr::Binary(op, ref left, ref right) => {
116 left.to_tokens(tokens);
117 op.to_tokens(tokens);
118 right.to_tokens(tokens);
119 }
120 ConstExpr::Unary(op, ref expr) => {
121 op.to_tokens(tokens);
122 expr.to_tokens(tokens);
123 }
124 ConstExpr::Lit(ref lit) => lit.to_tokens(tokens),
125 ConstExpr::Cast(ref expr, ref ty) => {
126 expr.to_tokens(tokens);
127 tokens.append("as");
128 ty.to_tokens(tokens);
129 }
130 ConstExpr::Path(ref path) => path.to_tokens(tokens),
David Tolnay67588752016-10-30 12:23:10 -0700131 ConstExpr::Index(ref expr, ref index) => {
132 expr.to_tokens(tokens);
133 tokens.append("[");
134 index.to_tokens(tokens);
135 tokens.append("]");
136 }
David Tolnayf43ba802016-10-30 10:20:47 -0700137 ConstExpr::Paren(ref expr) => {
138 tokens.append("(");
139 expr.to_tokens(tokens);
140 tokens.append(")");
141 }
David Tolnay3cb23a92016-10-07 23:02:21 -0700142 }
143 }
144 }
145}