blob: 312027f2ce2651859053b42a033ab16091e1821a [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
2
3#[derive(Debug, Clone, Eq, PartialEq)]
4pub enum Expr {
5 /// A `box x` expression.
6 Box(Box<Expr>),
David Tolnayf4bbbd92016-09-23 14:41:55 -07007 /// An array (`[a, b, c, d]`)
8 Vec(Vec<Expr>),
9 /// A function call
10 ///
11 /// The first field resolves to the function itself,
12 /// and the second field is the list of arguments
13 Call(Box<Expr>, Vec<Expr>),
14 /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
15 ///
16 /// The `Ident` is the identifier for the method name.
17 /// The vector of `Ty`s are the ascripted type parameters for the method
18 /// (within the angle brackets).
19 ///
20 /// The first element of the vector of `Expr`s is the expression that evaluates
21 /// to the object on which the method is being called on (the receiver),
22 /// and the remaining elements are the rest of the arguments.
23 ///
24 /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
25 /// `ExprKind::MethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
26 MethodCall(Ident, Vec<Ty>, Vec<Expr>),
27 /// A tuple (`(a, b, c, d)`)
28 Tup(Vec<Expr>),
29 /// A binary operation (For example: `a + b`, `a * b`)
30 Binary(BinOp, Box<Expr>, Box<Expr>),
31 /// A unary operation (For example: `!x`, `*x`)
32 Unary(UnOp, Box<Expr>),
33 /// A literal (For example: `1`, `"foo"`)
34 Lit(Lit),
35 /// A cast (`foo as f64`)
36 Cast(Box<Expr>, Box<Ty>),
37 Type(Box<Expr>, Box<Ty>),
38 /// An `if` block, with an optional else block
39 ///
40 /// `if expr { block } else { expr }`
41 If(Box<Expr>, Box<Block>, Option<Box<Expr>>),
42 /// An `if let` expression with an optional else block
43 ///
44 /// `if let pat = expr { block } else { expr }`
45 ///
46 /// This is desugared to a `match` expression.
47 IfLet(Box<Pat>, Box<Expr>, Box<Block>, Option<Box<Expr>>),
48 /// A while loop, with an optional label
49 ///
50 /// `'label: while expr { block }`
51 While(Box<Expr>, Box<Block>, Option<Ident>),
52 /// A while-let loop, with an optional label
53 ///
54 /// `'label: while let pat = expr { block }`
55 ///
56 /// This is desugared to a combination of `loop` and `match` expressions.
57 WhileLet(Box<Pat>, Box<Expr>, Box<Block>, Option<Ident>),
58 /// A for loop, with an optional label
59 ///
60 /// `'label: for pat in expr { block }`
61 ///
62 /// This is desugared to a combination of `loop` and `match` expressions.
63 ForLoop(Box<Pat>, Box<Expr>, Box<Block>, Option<Ident>),
64 /// Conditionless loop (can be exited with break, continue, or return)
65 ///
66 /// `'label: loop { block }`
67 Loop(Box<Block>, Option<Ident>),
68 /// A `match` block.
69 Match(Box<Expr>, Vec<Arm>),
70 /// A closure (for example, `move |a, b, c| {a + b + c}`)
71 Closure(CaptureBy, Box<FnDecl>, Box<Block>),
72 /// A block (`{ ... }`)
73 Block(Box<Block>),
74
75 /// An assignment (`a = foo()`)
76 Assign(Box<Expr>, Box<Expr>),
77 /// An assignment with an operator
78 ///
79 /// For example, `a += 1`.
80 AssignOp(BinOp, Box<Expr>, Box<Expr>),
81 /// Access of a named struct field (`obj.foo`)
82 Field(Box<Expr>, Ident),
83 /// Access of an unnamed field of a struct or tuple-struct
84 ///
85 /// For example, `foo.0`.
86 TupField(Box<Expr>, usize),
87 /// An indexing operation (`foo[2]`)
88 Index(Box<Expr>, Box<Expr>),
89 /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
90 Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),
91
92 /// Variable reference, possibly containing `::` and/or type
93 /// parameters, e.g. foo::bar::<baz>.
94 ///
95 /// Optionally "qualified",
96 /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
97 Path(Option<QSelf>, Path),
98
99 /// A referencing operation (`&a` or `&mut a`)
100 AddrOf(Mutability, Box<Expr>),
101 /// A `break`, with an optional label to break
102 Break(Option<Ident>),
103 /// A `continue`, with an optional label
104 Continue(Option<Ident>),
105 /// A `return`, with an optional value to be returned
106 Ret(Option<Box<Expr>>),
107
108 /// A macro invocation; pre-expansion
109 Mac(Mac),
110
111 /// A struct literal expression.
112 ///
113 /// For example, `Foo {x: 1, y: 2}`, or
114 /// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
115 Struct(Path, Vec<Field>, Option<Box<Expr>>),
116
117 /// An array literal constructed from one repeated element.
118 ///
119 /// For example, `[1; 5]`. The first expression is the element
120 /// to be repeated; the second is the number of times to repeat it.
121 Repeat(Box<Expr>, Box<Expr>),
122
123 /// No-op: used solely so we can pretty-print faithfully
124 Paren(Box<Expr>),
125
126 /// `expr?`
127 Try(Box<Expr>),
128}
129
130/// A Block (`{ .. }`).
131///
132/// E.g. `{ .. }` as in `fn foo() { .. }`
133#[derive(Debug, Clone, Eq, PartialEq)]
134pub struct Block {
135 /// Statements in a block
136 pub stmts: Vec<Stmt>,
137 /// Distinguishes between `unsafe { ... }` and `{ ... }`
138 pub rules: BlockCheckMode,
139}
140
141#[derive(Debug, Copy, Clone, Eq, PartialEq)]
142pub enum BlockCheckMode {
143 Default,
144 Unsafe,
145}
146
147#[derive(Debug, Clone, Eq, PartialEq)]
148pub enum Stmt {
149 /// A local (let) binding.
150 Local(Box<Local>),
151
152 /// An item definition.
153 Item(Box<Item>),
154
155 /// Expr without trailing semi-colon.
156 Expr(Box<Expr>),
157
158 Semi(Box<Expr>),
159
160 Mac(Box<(Mac, MacStmtStyle, Vec<Attribute>)>),
161}
162
163#[derive(Debug, Copy, Clone, Eq, PartialEq)]
164pub enum MacStmtStyle {
165 /// The macro statement had a trailing semicolon, e.g. `foo! { ... };`
166 /// `foo!(...);`, `foo![...];`
167 Semicolon,
168 /// The macro statement had braces; e.g. foo! { ... }
169 Braces,
170 /// The macro statement had parentheses or brackets and no semicolon; e.g.
171 /// `foo!(...)`. All of these will end up being converted into macro
172 /// expressions.
173 NoBraces,
174}
175
176/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`
177#[derive(Debug, Clone, Eq, PartialEq)]
178pub struct Local {
179 pub pat: Box<Pat>,
180 pub ty: Option<Box<Ty>>,
181 /// Initializer expression to set the value, if any
182 pub init: Option<Box<Expr>>,
183 pub attrs: Vec<Attribute>,
184}
185
186#[derive(Debug, Copy, Clone, Eq, PartialEq)]
187pub enum BinOp {
188 /// The `+` operator (addition)
189 Add,
190 /// The `-` operator (subtraction)
191 Sub,
192 /// The `*` operator (multiplication)
193 Mul,
194 /// The `/` operator (division)
195 Div,
196 /// The `%` operator (modulus)
197 Rem,
198 /// The `&&` operator (logical and)
199 And,
200 /// The `||` operator (logical or)
201 Or,
202 /// The `^` operator (bitwise xor)
203 BitXor,
204 /// The `&` operator (bitwise and)
205 BitAnd,
206 /// The `|` operator (bitwise or)
207 BitOr,
208 /// The `<<` operator (shift left)
209 Shl,
210 /// The `>>` operator (shift right)
211 Shr,
212 /// The `==` operator (equality)
213 Eq,
214 /// The `<` operator (less than)
215 Lt,
216 /// The `<=` operator (less than or equal to)
217 Le,
218 /// The `!=` operator (not equal to)
219 Ne,
220 /// The `>=` operator (greater than or equal to)
221 Ge,
222 /// The `>` operator (greater than)
223 Gt,
224}
225
226#[derive(Debug, Copy, Clone, Eq, PartialEq)]
227pub enum UnOp {
228 /// The `*` operator for dereferencing
229 Deref,
230 /// The `!` operator for logical inversion
231 Not,
232 /// The `-` operator for negation
233 Neg,
234}
235
236#[derive(Debug, Clone, Eq, PartialEq)]
237pub enum Pat {
238 /// Represents a wildcard pattern (`_`)
239 Wild,
240
241 /// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
242 /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
243 /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
244 /// during name resolution.
245 Ident(BindingMode, Ident, Option<Box<Pat>>),
246
247 /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
248 /// The `bool` is `true` in the presence of a `..`.
249 Struct(Path, Vec<FieldPat>, bool),
250
251 /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
252 /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
253 /// 0 <= position <= subpats.len()
254 TupleStruct(Path, Vec<Pat>, Option<usize>),
255
256 /// A possibly qualified path pattern.
257 /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants
258 /// or associated constants. Quailfied path patterns `<A>::B::C`/`<A as Trait>::B::C` can
259 /// only legally refer to associated constants.
260 Path(Option<QSelf>, Path),
261
262 /// A tuple pattern `(a, b)`.
263 /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
264 /// 0 <= position <= subpats.len()
265 Tuple(Vec<Pat>, Option<usize>),
266 /// A `box` pattern
267 Box(Box<Pat>),
268 /// A reference pattern, e.g. `&mut (a, b)`
269 Ref(Box<Pat>, Mutability),
270 /// A literal
271 Lit(Box<Expr>),
272 /// A range pattern, e.g. `1...2`
273 Range(Box<Expr>, Box<Expr>),
274 /// `[a, b, ..i, y, z]` is represented as:
275 /// `PatKind::Vec(box [a, b], Some(i), box [y, z])`
276 Vec(Vec<Pat>, Option<Box<Pat>>, Vec<Pat>),
277 /// A macro pattern; pre-expansion
278 Mac(Mac),
279}
280
David Tolnay771ecf42016-09-23 19:26:37 -0700281/// An arm of a 'match'.
282///
283/// E.g. `0...10 => { println!("match!") }` as in
284///
285/// ```rust,ignore
286/// match n {
287/// 0...10 => { println!("match!") },
288/// // ..
289/// }
290/// ```
David Tolnayf4bbbd92016-09-23 14:41:55 -0700291#[derive(Debug, Clone, Eq, PartialEq)]
292pub struct Arm {
293 pub attrs: Vec<Attribute>,
294 pub pats: Vec<Pat>,
295 pub guard: Option<Box<Expr>>,
296 pub body: Box<Expr>,
297}
298
299/// A capture clause
300#[derive(Debug, Copy, Clone, Eq, PartialEq)]
301pub enum CaptureBy {
302 Value,
303 Ref,
304}
305
306/// Limit types of a range (inclusive or exclusive)
307#[derive(Debug, Copy, Clone, Eq, PartialEq)]
308pub enum RangeLimits {
309 /// Inclusive at the beginning, exclusive at the end
310 HalfOpen,
311 /// Inclusive at the beginning and end
312 Closed,
313}
314
315/// A single field in a struct pattern
316///
317/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
318/// are treated the same as` x: x, y: ref y, z: ref mut z`,
David Tolnayaed77b02016-09-23 20:50:31 -0700319/// except `is_shorthand` is true
David Tolnayf4bbbd92016-09-23 14:41:55 -0700320#[derive(Debug, Clone, Eq, PartialEq)]
321pub struct FieldPat {
322 /// The identifier for the field
323 pub ident: Ident,
324 /// The pattern the field is destructured to
325 pub pat: Box<Pat>,
326 pub is_shorthand: bool,
327}
328
329#[derive(Debug, Copy, Clone, Eq, PartialEq)]
330pub enum BindingMode {
331 ByRef(Mutability),
332 ByValue(Mutability),
333}
334
David Tolnayb9c8e322016-09-23 20:48:37 -0700335#[cfg(feature = "parsing")]
336pub mod parsing {
337 use super::*;
David Tolnayfa0edf22016-09-23 22:58:24 -0700338 use {Ident, Ty};
339 use ident::parsing::ident;
340 use lit::parsing::lit;
David Tolnayb9c8e322016-09-23 20:48:37 -0700341 use nom::multispace;
David Tolnayfa0edf22016-09-23 22:58:24 -0700342 use ty::parsing::ty;
David Tolnayb9c8e322016-09-23 20:48:37 -0700343
David Tolnayfa0edf22016-09-23 22:58:24 -0700344 named!(pub expr -> Expr, do_parse!(
345 mut e: alt!(
346 boxed
347 |
348 vec
349 |
350 tup
351 |
352 unary
353 |
354 map!(lit, Expr::Lit)
355 ) >>
356 many0!(alt!(
357 tap!(c: call => {
358 e = Expr::Call(Box::new(e), c);
359 })
360 |
361 tap!(c: method_call => {
362 let (method, ascript, mut args) = c;
363 args.insert(0, e);
364 e = Expr::MethodCall(method, ascript, args);
365 })
366 |
367 tap!(b: binary => {
368 let (op, other) = b;
369 e = Expr::Binary(op, Box::new(e), Box::new(other));
370 })
371 )) >>
372 (e)
David Tolnayb9c8e322016-09-23 20:48:37 -0700373 ));
374
David Tolnayfa0edf22016-09-23 22:58:24 -0700375 named!(boxed -> Expr, do_parse!(
David Tolnayb9c8e322016-09-23 20:48:37 -0700376 punct!("box") >>
377 multispace >>
378 inner: expr >>
379 (Expr::Box(Box::new(inner)))
380 ));
David Tolnayfa0edf22016-09-23 22:58:24 -0700381
382 named!(vec -> Expr, do_parse!(
383 punct!("[") >>
384 elems: separated_list!(punct!(","), expr) >>
385 punct!("]") >>
386 (Expr::Vec(elems))
387 ));
388
389 named!(call -> Vec<Expr>, do_parse!(
390 punct!("(") >>
391 args: separated_list!(punct!(","), expr) >>
392 punct!(")") >>
393 (args)
394 ));
395
396 named!(method_call -> (Ident, Vec<Ty>, Vec<Expr>), do_parse!(
397 punct!(".") >>
398 method: ident >>
399 ascript: opt_vec!(delimited!(
400 punct!("<"),
401 separated_list!(punct!(","), ty),
402 punct!(">")
403 )) >>
404 punct!("(") >>
405 args: separated_list!(punct!(","), expr) >>
406 punct!(")") >>
407 (method, ascript, args)
408 ));
409
410 named!(tup -> Expr, do_parse!(
411 punct!("(") >>
412 elems: separated_list!(punct!(","), expr) >>
413 punct!(")") >>
414 (Expr::Tup(elems))
415 ));
416
417 named!(binary -> (BinOp, Expr), tuple!(
418 alt!(
419 punct!("&&") => { |_| BinOp::And }
420 |
421 punct!("||") => { |_| BinOp::Or }
422 |
423 punct!("<<") => { |_| BinOp::Shl }
424 |
425 punct!(">>") => { |_| BinOp::Shr }
426 |
427 punct!("==") => { |_| BinOp::Eq }
428 |
429 punct!("<=") => { |_| BinOp::Le }
430 |
431 punct!("!=") => { |_| BinOp::Ne }
432 |
433 punct!(">=") => { |_| BinOp::Ge }
434 |
435 punct!("+") => { |_| BinOp::Add }
436 |
437 punct!("-") => { |_| BinOp::Sub }
438 |
439 punct!("*") => { |_| BinOp::Mul }
440 |
441 punct!("/") => { |_| BinOp::Div }
442 |
443 punct!("%") => { |_| BinOp::Rem }
444 |
445 punct!("^") => { |_| BinOp::BitXor }
446 |
447 punct!("&") => { |_| BinOp::BitAnd }
448 |
449 punct!("|") => { |_| BinOp::BitOr }
450 |
451 punct!("<") => { |_| BinOp::Lt }
452 |
453 punct!(">") => { |_| BinOp::Gt }
454 ),
455 expr
456 ));
457
458 named!(unary -> Expr, do_parse!(
459 operator: alt!(
460 punct!("*") => { |_| UnOp::Deref }
461 |
462 punct!("!") => { |_| UnOp::Not }
463 |
464 punct!("-") => { |_| UnOp::Neg }
465 ) >>
466 operand: expr >>
467 (Expr::Unary(operator, Box::new(operand)))
468 ));
David Tolnayb9c8e322016-09-23 20:48:37 -0700469}
470
David Tolnayf4bbbd92016-09-23 14:41:55 -0700471#[cfg(feature = "printing")]
472mod printing {
473 use super::*;
474 use quote::{Tokens, ToTokens};
475
476 impl ToTokens for Expr {
477 fn to_tokens(&self, tokens: &mut Tokens) {
478 match *self {
479 Expr::Lit(ref lit) => lit.to_tokens(tokens),
480 _ => unimplemented!(),
481 }
482 }
483 }
484}