aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r--crates/ra_hir/src/expr.rs408
1 files changed, 6 insertions, 402 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 53da7f0bf..dd2bae9b4 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,29 +6,18 @@ pub(crate) mod validation;
6 6
7use std::{ops::Index, sync::Arc}; 7use std::{ops::Index, sync::Arc};
8 8
9use hir_def::{ 9use ra_arena::{map::ArenaMap, Arena};
10 path::GenericArgs,
11 type_ref::{Mutability, TypeRef},
12};
13use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
14use ra_syntax::{ast, AstPtr}; 10use ra_syntax::{ast, AstPtr};
15use rustc_hash::FxHashMap; 11use rustc_hash::FxHashMap;
16 12
17use crate::{ 13use crate::{db::HirDatabase, DefWithBody, Either, HasSource, Resolver, Source};
18 db::HirDatabase,
19 ty::primitive::{UncertainFloatTy, UncertainIntTy},
20 DefWithBody, Either, HasSource, Name, Path, Resolver, Source,
21};
22 14
23pub use self::scope::ExprScopes; 15pub use self::scope::ExprScopes;
24 16
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 17pub use hir_def::expr::{
26pub struct ExprId(RawId); 18 ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal, LogicOp, MatchArm,
27impl_arena_id!(ExprId); 19 Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, UnaryOp,
28 20};
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
30pub struct PatId(RawId);
31impl_arena_id!(PatId);
32 21
33/// The body of an item (function, const etc.). 22/// The body of an item (function, const etc.).
34#[derive(Debug, Eq, PartialEq)] 23#[derive(Debug, Eq, PartialEq)]
@@ -187,388 +176,3 @@ impl BodySourceMap {
187 self.field_map[&(expr, field)] 176 self.field_map[&(expr, field)]
188 } 177 }
189} 178}
190
191#[derive(Debug, Clone, Eq, PartialEq)]
192pub enum Literal {
193 String(String),
194 ByteString(Vec<u8>),
195 Char(char),
196 Bool(bool),
197 Int(u64, UncertainIntTy),
198 Float(u64, UncertainFloatTy), // FIXME: f64 is not Eq
199}
200
201#[derive(Debug, Clone, Eq, PartialEq)]
202pub enum Expr {
203 /// This is produced if syntax tree does not have a required expression piece.
204 Missing,
205 Path(Path),
206 If {
207 condition: ExprId,
208 then_branch: ExprId,
209 else_branch: Option<ExprId>,
210 },
211 Block {
212 statements: Vec<Statement>,
213 tail: Option<ExprId>,
214 },
215 Loop {
216 body: ExprId,
217 },
218 While {
219 condition: ExprId,
220 body: ExprId,
221 },
222 For {
223 iterable: ExprId,
224 pat: PatId,
225 body: ExprId,
226 },
227 Call {
228 callee: ExprId,
229 args: Vec<ExprId>,
230 },
231 MethodCall {
232 receiver: ExprId,
233 method_name: Name,
234 args: Vec<ExprId>,
235 generic_args: Option<GenericArgs>,
236 },
237 Match {
238 expr: ExprId,
239 arms: Vec<MatchArm>,
240 },
241 Continue,
242 Break {
243 expr: Option<ExprId>,
244 },
245 Return {
246 expr: Option<ExprId>,
247 },
248 RecordLit {
249 path: Option<Path>,
250 fields: Vec<RecordLitField>,
251 spread: Option<ExprId>,
252 },
253 Field {
254 expr: ExprId,
255 name: Name,
256 },
257 Await {
258 expr: ExprId,
259 },
260 Try {
261 expr: ExprId,
262 },
263 TryBlock {
264 body: ExprId,
265 },
266 Cast {
267 expr: ExprId,
268 type_ref: TypeRef,
269 },
270 Ref {
271 expr: ExprId,
272 mutability: Mutability,
273 },
274 Box {
275 expr: ExprId,
276 },
277 UnaryOp {
278 expr: ExprId,
279 op: UnaryOp,
280 },
281 BinaryOp {
282 lhs: ExprId,
283 rhs: ExprId,
284 op: Option<BinaryOp>,
285 },
286 Index {
287 base: ExprId,
288 index: ExprId,
289 },
290 Lambda {
291 args: Vec<PatId>,
292 arg_types: Vec<Option<TypeRef>>,
293 body: ExprId,
294 },
295 Tuple {
296 exprs: Vec<ExprId>,
297 },
298 Array(Array),
299 Literal(Literal),
300}
301
302#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
303pub enum BinaryOp {
304 LogicOp(LogicOp),
305 ArithOp(ArithOp),
306 CmpOp(CmpOp),
307 Assignment { op: Option<ArithOp> },
308}
309
310#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
311pub enum LogicOp {
312 And,
313 Or,
314}
315
316#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
317pub enum CmpOp {
318 Eq { negated: bool },
319 Ord { ordering: Ordering, strict: bool },
320}
321
322#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
323pub enum Ordering {
324 Less,
325 Greater,
326}
327
328#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
329pub enum ArithOp {
330 Add,
331 Mul,
332 Sub,
333 Div,
334 Rem,
335 Shl,
336 Shr,
337 BitXor,
338 BitOr,
339 BitAnd,
340}
341
342pub use ra_syntax::ast::PrefixOp as UnaryOp;
343#[derive(Debug, Clone, Eq, PartialEq)]
344pub enum Array {
345 ElementList(Vec<ExprId>),
346 Repeat { initializer: ExprId, repeat: ExprId },
347}
348
349#[derive(Debug, Clone, Eq, PartialEq)]
350pub struct MatchArm {
351 pub pats: Vec<PatId>,
352 pub guard: Option<ExprId>,
353 pub expr: ExprId,
354}
355
356#[derive(Debug, Clone, Eq, PartialEq)]
357pub struct RecordLitField {
358 pub name: Name,
359 pub expr: ExprId,
360}
361
362#[derive(Debug, Clone, Eq, PartialEq)]
363pub enum Statement {
364 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> },
365 Expr(ExprId),
366}
367
368impl Expr {
369 pub fn walk_child_exprs(&self, mut f: impl FnMut(ExprId)) {
370 match self {
371 Expr::Missing => {}
372 Expr::Path(_) => {}
373 Expr::If { condition, then_branch, else_branch } => {
374 f(*condition);
375 f(*then_branch);
376 if let Some(else_branch) = else_branch {
377 f(*else_branch);
378 }
379 }
380 Expr::Block { statements, tail } => {
381 for stmt in statements {
382 match stmt {
383 Statement::Let { initializer, .. } => {
384 if let Some(expr) = initializer {
385 f(*expr);
386 }
387 }
388 Statement::Expr(e) => f(*e),
389 }
390 }
391 if let Some(expr) = tail {
392 f(*expr);
393 }
394 }
395 Expr::TryBlock { body } => f(*body),
396 Expr::Loop { body } => f(*body),
397 Expr::While { condition, body } => {
398 f(*condition);
399 f(*body);
400 }
401 Expr::For { iterable, body, .. } => {
402 f(*iterable);
403 f(*body);
404 }
405 Expr::Call { callee, args } => {
406 f(*callee);
407 for arg in args {
408 f(*arg);
409 }
410 }
411 Expr::MethodCall { receiver, args, .. } => {
412 f(*receiver);
413 for arg in args {
414 f(*arg);
415 }
416 }
417 Expr::Match { expr, arms } => {
418 f(*expr);
419 for arm in arms {
420 f(arm.expr);
421 }
422 }
423 Expr::Continue => {}
424 Expr::Break { expr } | Expr::Return { expr } => {
425 if let Some(expr) = expr {
426 f(*expr);
427 }
428 }
429 Expr::RecordLit { fields, spread, .. } => {
430 for field in fields {
431 f(field.expr);
432 }
433 if let Some(expr) = spread {
434 f(*expr);
435 }
436 }
437 Expr::Lambda { body, .. } => {
438 f(*body);
439 }
440 Expr::BinaryOp { lhs, rhs, .. } => {
441 f(*lhs);
442 f(*rhs);
443 }
444 Expr::Index { base, index } => {
445 f(*base);
446 f(*index);
447 }
448 Expr::Field { expr, .. }
449 | Expr::Await { expr }
450 | Expr::Try { expr }
451 | Expr::Cast { expr, .. }
452 | Expr::Ref { expr, .. }
453 | Expr::UnaryOp { expr, .. }
454 | Expr::Box { expr } => {
455 f(*expr);
456 }
457 Expr::Tuple { exprs } => {
458 for expr in exprs {
459 f(*expr);
460 }
461 }
462 Expr::Array(a) => match a {
463 Array::ElementList(exprs) => {
464 for expr in exprs {
465 f(*expr);
466 }
467 }
468 Array::Repeat { initializer, repeat } => {
469 f(*initializer);
470 f(*repeat)
471 }
472 },
473 Expr::Literal(_) => {}
474 }
475 }
476}
477
478/// Explicit binding annotations given in the HIR for a binding. Note
479/// that this is not the final binding *mode* that we infer after type
480/// inference.
481#[derive(Clone, PartialEq, Eq, Debug, Copy)]
482pub enum BindingAnnotation {
483 /// No binding annotation given: this means that the final binding mode
484 /// will depend on whether we have skipped through a `&` reference
485 /// when matching. For example, the `x` in `Some(x)` will have binding
486 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
487 /// ultimately be inferred to be by-reference.
488 Unannotated,
489
490 /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
491 Mutable,
492
493 /// Annotated as `ref`, like `ref x`
494 Ref,
495
496 /// Annotated as `ref mut x`.
497 RefMut,
498}
499
500impl BindingAnnotation {
501 fn new(is_mutable: bool, is_ref: bool) -> Self {
502 match (is_mutable, is_ref) {
503 (true, true) => BindingAnnotation::RefMut,
504 (false, true) => BindingAnnotation::Ref,
505 (true, false) => BindingAnnotation::Mutable,
506 (false, false) => BindingAnnotation::Unannotated,
507 }
508 }
509}
510
511#[derive(Debug, Clone, Eq, PartialEq)]
512pub struct RecordFieldPat {
513 pub(crate) name: Name,
514 pub(crate) pat: PatId,
515}
516
517/// Close relative to rustc's hir::PatKind
518#[derive(Debug, Clone, Eq, PartialEq)]
519pub enum Pat {
520 Missing,
521 Wild,
522 Tuple(Vec<PatId>),
523 Record {
524 path: Option<Path>,
525 args: Vec<RecordFieldPat>,
526 // FIXME: 'ellipsis' option
527 },
528 Range {
529 start: ExprId,
530 end: ExprId,
531 },
532 Slice {
533 prefix: Vec<PatId>,
534 rest: Option<PatId>,
535 suffix: Vec<PatId>,
536 },
537 Path(Path),
538 Lit(ExprId),
539 Bind {
540 mode: BindingAnnotation,
541 name: Name,
542 subpat: Option<PatId>,
543 },
544 TupleStruct {
545 path: Option<Path>,
546 args: Vec<PatId>,
547 },
548 Ref {
549 pat: PatId,
550 mutability: Mutability,
551 },
552}
553
554impl Pat {
555 pub fn walk_child_pats(&self, mut f: impl FnMut(PatId)) {
556 match self {
557 Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) | Pat::Wild | Pat::Missing => {}
558 Pat::Bind { subpat, .. } => {
559 subpat.iter().copied().for_each(f);
560 }
561 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
562 args.iter().copied().for_each(f);
563 }
564 Pat::Ref { pat, .. } => f(*pat),
565 Pat::Slice { prefix, rest, suffix } => {
566 let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
567 total_iter.copied().for_each(f);
568 }
569 Pat::Record { args, .. } => {
570 args.iter().map(|f| f.pat).for_each(f);
571 }
572 }
573 }
574}