From 8a357e1d87971574817a033e5467785402d5fcfb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Sat, 13 Dec 2014 18:41:02 +1300 Subject: [PATCH] Add syntax for ranges --- src/librustc/middle/cfg/construct.rs | 4 +++ src/librustc/middle/expr_use_visitor.rs | 4 +++ src/librustc/middle/liveness.rs | 10 ++++++ src/librustc/middle/mem_categorization.rs | 3 ++ src/librustc/middle/ty.rs | 3 ++ src/librustc_back/svh.rs | 2 ++ src/librustc_trans/trans/debuginfo.rs | 5 +++ src/librustc_typeck/check/mod.rs | 4 +++ src/libsyntax/ast.rs | 1 + src/libsyntax/fold.rs | 4 +++ src/libsyntax/parse/parser.rs | 40 ++++++++++++++++++----- src/libsyntax/print/pprust.rs | 7 ++++ src/libsyntax/visit.rs | 4 +++ 13 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 2d50757782d..fe8e90bc32c 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -439,6 +439,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { start.iter().chain(end.iter()).map(|x| &**x)) } + ast::ExprRange(..) => { + self.tcx.sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprUnary(_, ref e) if self.is_method_call(expr) => { self.call(expr, pred, &**e, None::.iter()) } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 7e31ae04ae0..6a2bb2fc5a3 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -465,6 +465,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { assert!(overloaded); } + ast::ExprRange(..) => { + self.tcx().sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprCall(ref callee, ref args) => { // callee(args) self.walk_callee(expr, &**callee); self.consume_exprs(args); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 798daf8d541..fe2d7d47cb9 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -486,6 +486,9 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { ast::ExprWhileLet(..) => { ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } ast::ExprForLoop(ref pat, _, _, _) => { pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| { debug!("adding local variable {} from for loop with bm {}", @@ -1197,6 +1200,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&**e1, succ) } + ast::ExprRange(..) => { + self.ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } + ast::ExprBox(None, ref e) | ast::ExprAddrOf(_, ref e) | ast::ExprCast(ref e, _) | @@ -1498,6 +1505,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { ast::ExprWhileLet(..) => { this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + this.ir.tcx.sess.span_bug(expr.span, "non-desugared range"); + } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 006515ea0a0..e605471fc06 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -559,6 +559,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { ast::ExprWhileLet(..) => { self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + self.tcx().sess.span_bug(expr.span, "non-desugared range"); + } } } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 22fdea8afb5..4c5d3cb5c74 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4273,6 +4273,9 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind { ast::ExprWhileLet(..) => { tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet"); } + ast::ExprRange(..) => { + tcx.sess.span_bug(expr.span, "non-desugared range"); + } ast::ExprLit(ref lit) if lit_is_str(&**lit) => { RvalueDpsExpr diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index d40c9ee8af6..c68e9055269 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -247,6 +247,7 @@ mod svh_visitor { SawExprAssignOp(ast::BinOp), SawExprIndex, SawExprSlice, + SawExprRange, SawExprPath, SawExprAddrOf(ast::Mutability), SawExprRet, @@ -280,6 +281,7 @@ mod svh_visitor { ExprTupField(_, id) => SawExprTupField(id.node), ExprIndex(..) => SawExprIndex, ExprSlice(..) => SawExprSlice, + ExprRange(..) => SawExprRange, ExprPath(..) => SawExprPath, ExprAddrOf(m, _) => SawExprAddrOf(m), ExprBreak(id) => SawExprBreak(id.map(content)), diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 6226aace8a8..f402f1d7c31 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3494,6 +3494,11 @@ fn populate_scope_map(cx: &CrateContext, end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map)); } + ast::ExprRange(..) => { + cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \ + Found unexpanded range."); + } + ast::ExprVec(ref init_expressions) | ast::ExprTup(ref init_expressions) => { for ie in init_expressions.iter() { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3139a17f998..02811861551 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4278,6 +4278,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } } } + ast::ExprRange(..) => { + tcx.sess.span_bug(expr.span, "non-desugared range"); + } + } debug!("type of expr({}) {} is...", expr.id, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9d4bf77d4a5..0c8c17b080b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -724,6 +724,7 @@ pub enum Expr_ { ExprTupField(P, Spanned), ExprIndex(P, P), ExprSlice(P, Option>, Option>, Mutability), + ExprRange(P, Option>), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar:: diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 86df5883864..0803de1bb53 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1390,6 +1390,10 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> e2.map(|x| folder.fold_expr(x)), m) } + ExprRange(e1, e2) => { + ExprRange(folder.fold_expr(e1), + e2.map(|x| folder.fold_expr(x))) + } ExprPath(pth) => ExprPath(folder.fold_path(pth)), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 197970317d2..94b61ba56d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -26,7 +26,7 @@ use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; -use ast::{ExprLit, ExprLoop, ExprMac}; +use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; @@ -95,7 +95,8 @@ bitflags! { const UNRESTRICTED = 0b0000, const RESTRICTION_STMT_EXPR = 0b0001, const RESTRICTION_NO_BAR_OP = 0b0010, - const RESTRICTION_NO_STRUCT_LITERAL = 0b0100 + const RESTRICTION_NO_STRUCT_LITERAL = 0b0100, + const RESTRICTION_NO_DOTS = 0b1000, } } @@ -1547,7 +1548,7 @@ impl<'a> Parser<'a> { // Parse the `; e` in `[ int; e ]` // where `e` is a const expression - let t = match self.maybe_parse_fixed_vstore() { + let t = match self.maybe_parse_fixed_length_of_vec() { None => TyVec(t), Some(suffix) => TyFixedLengthVec(t, suffix) }; @@ -1707,12 +1708,12 @@ impl<'a> Parser<'a> { } } - pub fn maybe_parse_fixed_vstore(&mut self) -> Option> { + pub fn maybe_parse_fixed_length_of_vec(&mut self) -> Option> { if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { self.bump(); self.bump(); - Some(self.parse_expr()) + Some(self.parse_expr_res(RESTRICTION_NO_DOTS)) } else if self.check(&token::Semi) { self.bump(); Some(self.parse_expr()) @@ -2130,7 +2131,8 @@ impl<'a> Parser<'a> { ExprIndex(expr, idx) } - pub fn mk_slice(&mut self, expr: P, + pub fn mk_slice(&mut self, + expr: P, start: Option>, end: Option>, mutbl: Mutability) @@ -2138,6 +2140,13 @@ impl<'a> Parser<'a> { ExprSlice(expr, start, end, mutbl) } + pub fn mk_range(&mut self, + start: P, + end: Option>) + -> ast::Expr_ { + ExprRange(start, end) + } + pub fn mk_field(&mut self, expr: P, ident: ast::SpannedIdent) -> ast::Expr_ { ExprField(expr, ident) } @@ -2615,7 +2624,7 @@ impl<'a> Parser<'a> { } // e[e] | e[e..] | e[e..e] _ => { - let ix = self.parse_expr(); + let ix = self.parse_expr_res(RESTRICTION_NO_DOTS); match self.token { // e[e..] | e[e..e] token::DotDot => { @@ -2628,7 +2637,7 @@ impl<'a> Parser<'a> { } // e[e..e] _ => { - let e2 = self.parse_expr(); + let e2 = self.parse_expr_res(RESTRICTION_NO_DOTS); self.commit_expr_expecting(&*e2, token::CloseDelim(token::Bracket)); Some(e2) @@ -2654,6 +2663,21 @@ impl<'a> Parser<'a> { } } + // A range expression, either `expr..expr` or `expr..`. + token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => { + self.bump(); + + let opt_end = if self.token.can_begin_expr() { + let end = self.parse_expr_res(RESTRICTION_NO_DOTS); + Some(end) + } else { + None + }; + + let hi = self.span.hi; + let range = self.mk_range(e, opt_end); + return self.mk_expr(lo, hi, range); + } _ => return e } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 21410395a90..3d53bd8aadf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1759,6 +1759,13 @@ impl<'a> State<'a> { } try!(word(&mut self.s, "]")); } + ast::ExprRange(ref start, ref end) => { + try!(self.print_expr(&**start)); + try!(word(&mut self.s, "..")); + if let &Some(ref e) = end { + try!(self.print_expr(&**e)); + } + } ast::ExprPath(ref path) => try!(self.print_path(path, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9938feb171e..4cc93467a7c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -871,6 +871,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } + ExprRange(ref start, ref end) => { + visitor.visit_expr(&**start); + walk_expr_opt(visitor, end) + } ExprPath(ref path) => { visitor.visit_path(path, expression.id) }