1
Fork 0

Add syntax for ranges

This commit is contained in:
Nick Cameron 2014-12-13 18:41:02 +13:00
parent 53c5fcb99f
commit 8a357e1d87
13 changed files with 83 additions and 8 deletions

View file

@ -439,6 +439,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
start.iter().chain(end.iter()).map(|x| &**x)) 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) => { ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
self.call(expr, pred, &**e, None::<ast::Expr>.iter()) self.call(expr, pred, &**e, None::<ast::Expr>.iter())
} }

View file

@ -465,6 +465,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
assert!(overloaded); assert!(overloaded);
} }
ast::ExprRange(..) => {
self.tcx().sess.span_bug(expr.span, "non-desugared range");
}
ast::ExprCall(ref callee, ref args) => { // callee(args) ast::ExprCall(ref callee, ref args) => { // callee(args)
self.walk_callee(expr, &**callee); self.walk_callee(expr, &**callee);
self.consume_exprs(args); self.consume_exprs(args);

View file

@ -486,6 +486,9 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
ir.tcx.sess.span_bug(expr.span, "non-desugared 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, _, _, _) => { ast::ExprForLoop(ref pat, _, _, _) => {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| { pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from for loop with bm {}", 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) 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::ExprBox(None, ref e) |
ast::ExprAddrOf(_, ref e) | ast::ExprAddrOf(_, ref e) |
ast::ExprCast(ref e, _) | ast::ExprCast(ref e, _) |
@ -1498,6 +1505,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
this.ir.tcx.sess.span_bug(expr.span, "non-desugared 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");
}
} }
} }

View file

@ -559,6 +559,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet"); self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
} }
ast::ExprRange(..) => {
self.tcx().sess.span_bug(expr.span, "non-desugared range");
}
} }
} }

View file

@ -4273,6 +4273,9 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprWhileLet(..) => { ast::ExprWhileLet(..) => {
tcx.sess.span_bug(expr.span, "non-desugared 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) => { ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
RvalueDpsExpr RvalueDpsExpr

View file

@ -247,6 +247,7 @@ mod svh_visitor {
SawExprAssignOp(ast::BinOp), SawExprAssignOp(ast::BinOp),
SawExprIndex, SawExprIndex,
SawExprSlice, SawExprSlice,
SawExprRange,
SawExprPath, SawExprPath,
SawExprAddrOf(ast::Mutability), SawExprAddrOf(ast::Mutability),
SawExprRet, SawExprRet,
@ -280,6 +281,7 @@ mod svh_visitor {
ExprTupField(_, id) => SawExprTupField(id.node), ExprTupField(_, id) => SawExprTupField(id.node),
ExprIndex(..) => SawExprIndex, ExprIndex(..) => SawExprIndex,
ExprSlice(..) => SawExprSlice, ExprSlice(..) => SawExprSlice,
ExprRange(..) => SawExprRange,
ExprPath(..) => SawExprPath, ExprPath(..) => SawExprPath,
ExprAddrOf(m, _) => SawExprAddrOf(m), ExprAddrOf(m, _) => SawExprAddrOf(m),
ExprBreak(id) => SawExprBreak(id.map(content)), ExprBreak(id) => SawExprBreak(id.map(content)),

View file

@ -3494,6 +3494,11 @@ fn populate_scope_map(cx: &CrateContext,
end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map)); 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::ExprVec(ref init_expressions) |
ast::ExprTup(ref init_expressions) => { ast::ExprTup(ref init_expressions) => {
for ie in init_expressions.iter() { for ie in init_expressions.iter() {

View file

@ -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, debug!("type of expr({}) {} is...", expr.id,

View file

@ -724,6 +724,7 @@ pub enum Expr_ {
ExprTupField(P<Expr>, Spanned<uint>), ExprTupField(P<Expr>, Spanned<uint>),
ExprIndex(P<Expr>, P<Expr>), ExprIndex(P<Expr>, P<Expr>),
ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability), ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability),
ExprRange(P<Expr>, Option<P<Expr>>),
/// Variable reference, possibly containing `::` and/or /// Variable reference, possibly containing `::` and/or
/// type parameters, e.g. foo::bar::<baz> /// type parameters, e.g. foo::bar::<baz>

View file

@ -1390,6 +1390,10 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
e2.map(|x| folder.fold_expr(x)), e2.map(|x| folder.fold_expr(x)),
m) m)
} }
ExprRange(e1, e2) => {
ExprRange(folder.fold_expr(e1),
e2.map(|x| folder.fold_expr(x)))
}
ExprPath(pth) => ExprPath(folder.fold_path(pth)), ExprPath(pth) => ExprPath(folder.fold_path(pth)),
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),

View file

@ -26,7 +26,7 @@ use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprBreak, ExprCall, ExprCast};
use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; 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::{ExprMethodCall, ExprParen, ExprPath};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
@ -95,7 +95,8 @@ bitflags! {
const UNRESTRICTED = 0b0000, const UNRESTRICTED = 0b0000,
const RESTRICTION_STMT_EXPR = 0b0001, const RESTRICTION_STMT_EXPR = 0b0001,
const RESTRICTION_NO_BAR_OP = 0b0010, 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 ]` // Parse the `; e` in `[ int; e ]`
// where `e` is a const expression // 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), None => TyVec(t),
Some(suffix) => TyFixedLengthVec(t, suffix) Some(suffix) => TyFixedLengthVec(t, suffix)
}; };
@ -1707,12 +1708,12 @@ impl<'a> Parser<'a> {
} }
} }
pub fn maybe_parse_fixed_vstore(&mut self) -> Option<P<ast::Expr>> { pub fn maybe_parse_fixed_length_of_vec(&mut self) -> Option<P<ast::Expr>> {
if self.check(&token::Comma) && if self.check(&token::Comma) &&
self.look_ahead(1, |t| *t == token::DotDot) { self.look_ahead(1, |t| *t == token::DotDot) {
self.bump(); self.bump();
self.bump(); self.bump();
Some(self.parse_expr()) Some(self.parse_expr_res(RESTRICTION_NO_DOTS))
} else if self.check(&token::Semi) { } else if self.check(&token::Semi) {
self.bump(); self.bump();
Some(self.parse_expr()) Some(self.parse_expr())
@ -2130,7 +2131,8 @@ impl<'a> Parser<'a> {
ExprIndex(expr, idx) ExprIndex(expr, idx)
} }
pub fn mk_slice(&mut self, expr: P<Expr>, pub fn mk_slice(&mut self,
expr: P<Expr>,
start: Option<P<Expr>>, start: Option<P<Expr>>,
end: Option<P<Expr>>, end: Option<P<Expr>>,
mutbl: Mutability) mutbl: Mutability)
@ -2138,6 +2140,13 @@ impl<'a> Parser<'a> {
ExprSlice(expr, start, end, mutbl) ExprSlice(expr, start, end, mutbl)
} }
pub fn mk_range(&mut self,
start: P<Expr>,
end: Option<P<Expr>>)
-> ast::Expr_ {
ExprRange(start, end)
}
pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::Expr_ { pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::Expr_ {
ExprField(expr, ident) ExprField(expr, ident)
} }
@ -2615,7 +2624,7 @@ impl<'a> Parser<'a> {
} }
// e[e] | e[e..] | e[e..e] // e[e] | e[e..] | e[e..e]
_ => { _ => {
let ix = self.parse_expr(); let ix = self.parse_expr_res(RESTRICTION_NO_DOTS);
match self.token { match self.token {
// e[e..] | e[e..e] // e[e..] | e[e..e]
token::DotDot => { token::DotDot => {
@ -2628,7 +2637,7 @@ impl<'a> Parser<'a> {
} }
// e[e..e] // e[e..e]
_ => { _ => {
let e2 = self.parse_expr(); let e2 = self.parse_expr_res(RESTRICTION_NO_DOTS);
self.commit_expr_expecting(&*e2, self.commit_expr_expecting(&*e2,
token::CloseDelim(token::Bracket)); token::CloseDelim(token::Bracket));
Some(e2) 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 _ => return e
} }
} }

View file

@ -1759,6 +1759,13 @@ impl<'a> State<'a> {
} }
try!(word(&mut self.s, "]")); 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::ExprPath(ref path) => try!(self.print_path(path, true)),
ast::ExprBreak(opt_ident) => { ast::ExprBreak(opt_ident) => {
try!(word(&mut self.s, "break")); try!(word(&mut self.s, "break"));

View file

@ -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, start);
walk_expr_opt(visitor, end) walk_expr_opt(visitor, end)
} }
ExprRange(ref start, ref end) => {
visitor.visit_expr(&**start);
walk_expr_opt(visitor, end)
}
ExprPath(ref path) => { ExprPath(ref path) => {
visitor.visit_path(path, expression.id) visitor.visit_path(path, expression.id)
} }