HIR: add inclusive ranges, desugar all ranges (remove ExprRange)

This commit is contained in:
Alex Burka 2016-01-13 01:24:34 -05:00
parent 5daf13cae3
commit a331278451
2 changed files with 89 additions and 5 deletions

View 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>.

View File

@ -65,6 +65,7 @@ use hir;
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 {