]> git.lizzy.rs Git - rust.git/commitdiff
HIR: add inclusive ranges, desugar all ranges (remove ExprRange)
authorAlex Burka <aburka@seas.upenn.edu>
Wed, 13 Jan 2016 06:24:34 +0000 (01:24 -0500)
committerAlex Burka <aburka@seas.upenn.edu>
Sat, 27 Feb 2016 07:01:41 +0000 (02:01 -0500)
src/librustc_front/hir.rs
src/librustc_front/lowering.rs

index dbc1d71517b75b45c4de90abd2dedd2669fd31c4..cf9952248a850fd8bb07beb6e66e574dd9c0b570 100644 (file)
@@ -777,8 +777,6 @@ pub enum Expr_ {
     ExprTupField(P<Expr>, Spanned<usize>),
     /// An indexing operation (`foo[2]`)
     ExprIndex(P<Expr>, P<Expr>),
-    /// A range (`1..2`, `1..`, or `..2`)
-    ExprRange(Option<P<Expr>>, Option<P<Expr>>),
 
     /// Variable reference, possibly containing `::` and/or type
     /// parameters, e.g. foo::bar::<baz>.
index 0e7d9db37fdb8fd663b76ccd62bf1302cfda77cf..5e39a7c817ac7e7a1821ab66ac7b85a273da3b3a 100644 (file)
@@ -65,6 +65,7 @@
 
 use std::collections::BTreeMap;
 use std::collections::HashMap;
+use std::iter;
 use syntax::ast::*;
 use syntax::attr::{ThinAttributes, ThinAttributesExt};
 use syntax::ext::mtwt;
@@ -1213,9 +1214,74 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
             ExprKind::Index(ref el, ref er) => {
                 hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er))
             }
-            ExprKind::Range(ref e1, ref e2) => {
-                hir::ExprRange(e1.as_ref().map(|x| lower_expr(lctx, x)),
-                               e2.as_ref().map(|x| lower_expr(lctx, x)))
+            ExprKind::Range(ref e1, ref e2, lims) => {
+                fn make_struct(lctx: &LoweringContext,
+                               ast_expr: &Expr,
+                               path: &[&str],
+                               fields: &[(&str, &P<Expr>)]) -> P<hir::Expr> {
+                    let strs = std_path(lctx, &iter::once(&"ops")
+                                                    .chain(path)
+                                                    .map(|s| *s)
+                                                    .collect::<Vec<_>>());
+
+                    let structpath = path_global(ast_expr.span, strs);
+
+                    let hir_expr = if fields.len() == 0 {
+                        expr_path(lctx,
+                                  structpath,
+                                  ast_expr.attrs.clone())
+                    } else {
+                        expr_struct(lctx,
+                                    ast_expr.span,
+                                    structpath,
+                                    fields.into_iter().map(|&(s, e)| {
+                                        field(token::intern(s),
+                                              lower_expr(lctx, &**e),
+                                              ast_expr.span)
+                                    }).collect(),
+                                    None,
+                                    ast_expr.attrs.clone())
+                    };
+
+                    signal_block_expr(lctx,
+                                      hir_vec![],
+                                      hir_expr,
+                                      ast_expr.span,
+                                      hir::PushUnstableBlock,
+                                      None)
+                }
+
+                return cache_ids(lctx, e.id, |lctx| {
+                    use syntax::ast::RangeLimits::*;
+
+                    match (e1, e2, lims) {
+                        (&None,         &None,         HalfOpen) =>
+                            make_struct(lctx, e, &["RangeFull"],
+                                                 &[]),
+
+                        (&Some(ref e1), &None,         HalfOpen) =>
+                            make_struct(lctx, e, &["RangeFrom"],
+                                                 &[("start", e1)]),
+
+                        (&None,         &Some(ref e2), HalfOpen) =>
+                            make_struct(lctx, e, &["RangeTo"],
+                                                 &[("end", e2)]),
+
+                        (&Some(ref e1), &Some(ref e2), HalfOpen) =>
+                            make_struct(lctx, e, &["Range"],
+                                                 &[("start", e1), ("end", e2)]),
+
+                        (&None,         &Some(ref e2), Closed)   =>
+                            make_struct(lctx, e, &["RangeToInclusive"],
+                                                 &[("end", e2)]),
+
+                        (&Some(ref e1), &Some(ref e2), Closed)   =>
+                            make_struct(lctx, e, &["RangeInclusive", "NonEmpty"],
+                                                 &[("start", e1), ("end", e2)]),
+
+                        _ => panic!("impossible range in AST"),
+                    }
+                });
             }
             ExprKind::Path(ref qself, ref path) => {
                 let hir_qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
@@ -1632,6 +1698,17 @@ fn arm(pats: hir::HirVec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
     }
 }
 
+fn field(name: Name, expr: P<hir::Expr>, span: Span) -> hir::Field {
+    hir::Field {
+        name: Spanned {
+            node: name,
+            span: span,
+        },
+        span: span,
+        expr: expr,
+    }
+}
+
 fn expr_break(lctx: &LoweringContext, span: Span,
               attrs: ThinAttributes) -> P<hir::Expr> {
     expr(lctx, span, hir::ExprBreak(None), attrs)
@@ -1681,6 +1758,15 @@ fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: hir::HirVec<P<hir::Expr>>
     expr(lctx, sp, hir::ExprTup(exprs), attrs)
 }
 
+fn expr_struct(lctx: &LoweringContext,
+               sp: Span,
+               path: hir::Path,
+               fields: hir::HirVec<hir::Field>,
+               e: Option<P<hir::Expr>>,
+               attrs: ThinAttributes) -> P<hir::Expr> {
+    expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs)
+}
+
 fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_,
         attrs: ThinAttributes) -> P<hir::Expr> {
     P(hir::Expr {