Preserve parenthesization in the AST
Maintain explicit "paren" nodes in the AST so we can pretty-print without having to guess where parens should go. We may revisit this in the future. r=graydon
This commit is contained in:
parent
17a5d0f3a0
commit
62f98c8ff8
20 changed files with 148 additions and 217 deletions
|
@ -744,7 +744,10 @@ enum expr_ {
|
|||
expr_struct(@path, ~[field], Option<@expr>),
|
||||
|
||||
// A vector literal constructed from one repeated element.
|
||||
expr_repeat(@expr /* element */, @expr /* count */, mutability)
|
||||
expr_repeat(@expr /* element */, @expr /* count */, mutability),
|
||||
|
||||
// No-op: used solely so we can pretty-print faithfully
|
||||
expr_paren(@expr)
|
||||
}
|
||||
|
||||
#[auto_serialize]
|
||||
|
|
|
@ -494,7 +494,8 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||
expr_struct(fld.fold_path(path),
|
||||
vec::map(fields, |x| fold_field(*x)),
|
||||
option::map(&maybe_expr, |x| fld.fold_expr(*x)))
|
||||
}
|
||||
},
|
||||
expr_paren(ex) => expr_paren(fld.fold_expr(ex))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,39 +36,3 @@ fn stmt_ends_with_semi(stmt: ast::stmt) -> bool {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn need_parens(expr: @ast::expr, outer_prec: uint) -> bool {
|
||||
match expr.node {
|
||||
ast::expr_binary(op, _, _) => operator_prec(op) < outer_prec,
|
||||
ast::expr_cast(_, _) => parse::prec::as_prec < outer_prec,
|
||||
// This may be too conservative in some cases
|
||||
ast::expr_assign(_, _) => true,
|
||||
ast::expr_swap(_, _) => true,
|
||||
ast::expr_assign_op(_, _, _) => true,
|
||||
ast::expr_ret(_) => true,
|
||||
ast::expr_assert(_) => true,
|
||||
ast::expr_log(_, _, _) => true,
|
||||
_ => !parse::classify::expr_requires_semi_to_be_stmt(expr)
|
||||
}
|
||||
}
|
||||
|
||||
fn ends_in_lit_int(ex: @ast::expr) -> bool {
|
||||
match ex.node {
|
||||
ast::expr_lit(node) => match node {
|
||||
@{node: ast::lit_int(_, ast::ty_i), _}
|
||||
| @{node: ast::lit_int_unsuffixed(_), _} => true,
|
||||
_ => false
|
||||
},
|
||||
ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
|
||||
ast::expr_copy(sub) | ast::expr_assign(_, sub) |
|
||||
ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
|
||||
ast::expr_log(_, _, sub) | ast::expr_assert(sub) => {
|
||||
ends_in_lit_int(sub)
|
||||
}
|
||||
ast::expr_fail(osub) | ast::expr_ret(osub) => match osub {
|
||||
Some(ex) => ends_in_lit_int(ex),
|
||||
_ => false
|
||||
},
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,11 +36,11 @@ use ast::{_mod, add, arg, arm, attribute,
|
|||
expr_call, expr_cast, expr_copy, expr_do_body, expr_fail,
|
||||
expr_field, expr_fn, expr_fn_block, expr_if, expr_index,
|
||||
expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac,
|
||||
expr_path, expr_rec, expr_repeat, expr_ret, expr_swap,
|
||||
expr_struct, expr_tup, expr_unary, expr_unary_move, expr_vec,
|
||||
expr_vstore, expr_while, extern_fn, field, fn_decl, foreign_item,
|
||||
foreign_item_const, foreign_item_fn, foreign_mod, ident,
|
||||
impure_fn, infer, inherited,
|
||||
expr_paren, expr_path, expr_rec, expr_repeat, expr_ret,
|
||||
expr_swap, expr_struct, expr_tup, expr_unary, expr_unary_move,
|
||||
expr_vec, expr_vstore, expr_while, extern_fn, field, fn_decl,
|
||||
foreign_item, foreign_item_const, foreign_item_fn, foreign_mod,
|
||||
ident, impure_fn, infer, inherited,
|
||||
item, item_, item_class, item_const, item_enum, item_fn,
|
||||
item_foreign_mod, item_impl, item_mac, item_mod, item_trait,
|
||||
item_ty, lit, lit_, lit_bool, lit_float, lit_int,
|
||||
|
@ -94,18 +94,6 @@ enum restriction {
|
|||
|
||||
enum file_type { CRATE_FILE, SOURCE_FILE, }
|
||||
|
||||
|
||||
// We don't allow single-entry tuples in the true AST; that indicates a
|
||||
// parenthesized expression. However, we preserve them temporarily while
|
||||
// parsing because `(while{...})+3` parses differently from `while{...}+3`.
|
||||
//
|
||||
// To reflect the fact that the @expr is not a true expr that should be
|
||||
// part of the AST, we wrap such expressions in the pexpr enum. They
|
||||
// can then be converted to true expressions by a call to `to_expr()`.
|
||||
enum pexpr {
|
||||
pexpr(@expr),
|
||||
}
|
||||
|
||||
enum class_member {
|
||||
field_member(@struct_field),
|
||||
method_member(@method)
|
||||
|
@ -141,11 +129,11 @@ macro_rules! maybe_whole_expr (
|
|||
($p:expr) => { match copy $p.token {
|
||||
INTERPOLATED(token::nt_expr(e)) => {
|
||||
$p.bump();
|
||||
return pexpr(e);
|
||||
return e;
|
||||
}
|
||||
INTERPOLATED(token::nt_path(pt)) => {
|
||||
$p.bump();
|
||||
return $p.mk_pexpr($p.span.lo, $p.span.lo,
|
||||
return $p.mk_expr($p.span.lo, $p.span.lo,
|
||||
expr_path(pt));
|
||||
}
|
||||
_ => ()
|
||||
|
@ -850,18 +838,7 @@ impl Parser {
|
|||
node: expr_lit(lv_lit), span: span};
|
||||
}
|
||||
|
||||
fn mk_pexpr(lo: uint, hi: uint, node: expr_) -> pexpr {
|
||||
return pexpr(self.mk_expr(lo, hi, node));
|
||||
}
|
||||
|
||||
fn to_expr(e: pexpr) -> @expr {
|
||||
match e.node {
|
||||
expr_tup(es) if vec::len(es) == 1u => es[0u],
|
||||
_ => *e
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_bottom_expr() -> pexpr {
|
||||
fn parse_bottom_expr() -> @expr {
|
||||
maybe_whole_expr!(self);
|
||||
let lo = self.span.lo;
|
||||
let mut hi = self.span.hi;
|
||||
|
@ -869,7 +846,7 @@ impl Parser {
|
|||
let mut ex: expr_;
|
||||
|
||||
match self.maybe_parse_dollar_mac() {
|
||||
Some(x) => return pexpr(self.mk_mac_expr(lo, self.span.hi, x)),
|
||||
Some(x) => return self.mk_mac_expr(lo, self.span.hi, x),
|
||||
_ => ()
|
||||
}
|
||||
|
||||
|
@ -879,7 +856,7 @@ impl Parser {
|
|||
hi = self.span.hi;
|
||||
self.bump();
|
||||
let lit = @spanned(lo, hi, lit_nil);
|
||||
return self.mk_pexpr(lo, hi, expr_lit(lit));
|
||||
return self.mk_expr(lo, hi, expr_lit(lit));
|
||||
}
|
||||
let mut es = ~[self.parse_expr()];
|
||||
while self.token == token::COMMA {
|
||||
|
@ -888,12 +865,12 @@ impl Parser {
|
|||
hi = self.span.hi;
|
||||
self.expect(token::RPAREN);
|
||||
|
||||
// Note: we retain the expr_tup() even for simple
|
||||
// parenthesized expressions, but only for a "little while".
|
||||
// This is so that wrappers around parse_bottom_expr()
|
||||
// can tell whether the expression was parenthesized or not,
|
||||
// which affects expr_is_complete().
|
||||
return self.mk_pexpr(lo, hi, expr_tup(es));
|
||||
return if es.len() == 1 {
|
||||
self.mk_expr(lo, self.span.hi, expr_paren(es[0]))
|
||||
}
|
||||
else {
|
||||
self.mk_expr(lo, hi, expr_tup(es))
|
||||
}
|
||||
} else if self.token == token::LBRACE {
|
||||
if self.looking_at_record_literal() {
|
||||
ex = self.parse_record_literal();
|
||||
|
@ -901,32 +878,32 @@ impl Parser {
|
|||
} else {
|
||||
self.bump();
|
||||
let blk = self.parse_block_tail(lo, default_blk);
|
||||
return self.mk_pexpr(blk.span.lo, blk.span.hi,
|
||||
return self.mk_expr(blk.span.lo, blk.span.hi,
|
||||
expr_block(blk));
|
||||
}
|
||||
} else if token::is_bar(self.token) {
|
||||
return pexpr(self.parse_lambda_expr());
|
||||
return self.parse_lambda_expr();
|
||||
} else if self.eat_keyword(~"if") {
|
||||
return pexpr(self.parse_if_expr());
|
||||
return self.parse_if_expr();
|
||||
} else if self.eat_keyword(~"for") {
|
||||
return pexpr(self.parse_sugary_call_expr(~"for", expr_loop_body));
|
||||
return self.parse_sugary_call_expr(~"for", expr_loop_body);
|
||||
} else if self.eat_keyword(~"do") {
|
||||
return pexpr(self.parse_sugary_call_expr(~"do", expr_do_body));
|
||||
return self.parse_sugary_call_expr(~"do", expr_do_body);
|
||||
} else if self.eat_keyword(~"while") {
|
||||
return pexpr(self.parse_while_expr());
|
||||
return self.parse_while_expr();
|
||||
} else if self.eat_keyword(~"loop") {
|
||||
return pexpr(self.parse_loop_expr());
|
||||
return self.parse_loop_expr();
|
||||
} else if self.eat_keyword(~"match") {
|
||||
return pexpr(self.parse_alt_expr());
|
||||
return self.parse_alt_expr();
|
||||
} else if self.eat_keyword(~"fn") {
|
||||
let proto = self.parse_fn_ty_proto();
|
||||
match proto {
|
||||
proto_bare => self.fatal(~"fn expr are deprecated, use fn@"),
|
||||
_ => { /* fallthrough */ }
|
||||
}
|
||||
return pexpr(self.parse_fn_expr(proto));
|
||||
return self.parse_fn_expr(proto);
|
||||
} else if self.eat_keyword(~"unsafe") {
|
||||
return pexpr(self.parse_block_expr(lo, unsafe_blk));
|
||||
return self.parse_block_expr(lo, unsafe_blk);
|
||||
} else if self.token == token::LBRACKET {
|
||||
self.bump();
|
||||
let mutbl = self.parse_mutability();
|
||||
|
@ -962,7 +939,7 @@ impl Parser {
|
|||
hi = self.span.hi;
|
||||
} else if self.token == token::ELLIPSIS {
|
||||
self.bump();
|
||||
return pexpr(self.mk_mac_expr(lo, self.span.hi, mac_ellipsis));
|
||||
return self.mk_mac_expr(lo, self.span.hi, mac_ellipsis);
|
||||
} else if self.token == token::POUND {
|
||||
let ex_ext = self.parse_syntax_ext();
|
||||
hi = ex_ext.span.hi;
|
||||
|
@ -1020,8 +997,8 @@ impl Parser {
|
|||
|
||||
let hi = self.span.hi;
|
||||
|
||||
return pexpr(self.mk_mac_expr(
|
||||
lo, hi, mac_invoc_tt(pth, tts)));
|
||||
return self.mk_mac_expr(
|
||||
lo, hi, mac_invoc_tt(pth, tts));
|
||||
} else if self.token == token::LBRACE {
|
||||
// This might be a struct literal.
|
||||
if self.looking_at_record_literal() {
|
||||
|
@ -1053,7 +1030,7 @@ impl Parser {
|
|||
hi = pth.span.hi;
|
||||
self.expect(token::RBRACE);
|
||||
ex = expr_struct(pth, fields, base);
|
||||
return self.mk_pexpr(lo, hi, ex);
|
||||
return self.mk_expr(lo, hi, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1068,7 +1045,7 @@ impl Parser {
|
|||
let (hi, ex) =
|
||||
self.try_convert_expr_to_obsolete_fixed_length_vstore(lo, hi, ex);
|
||||
|
||||
return self.mk_pexpr(lo, hi, ex);
|
||||
return self.mk_expr(lo, hi, ex);
|
||||
}
|
||||
|
||||
fn parse_block_expr(lo: uint, blk_mode: blk_check_mode) -> @expr {
|
||||
|
@ -1125,7 +1102,7 @@ impl Parser {
|
|||
return self.mk_mac_expr(lo, self.span.hi, mac_invoc(pth, e, b));
|
||||
}
|
||||
|
||||
fn parse_dot_or_call_expr() -> pexpr {
|
||||
fn parse_dot_or_call_expr() -> @expr {
|
||||
let b = self.parse_bottom_expr();
|
||||
self.parse_dot_or_call_expr_with(b)
|
||||
}
|
||||
|
@ -1134,7 +1111,7 @@ impl Parser {
|
|||
return self.restriction != RESTRICT_NO_CALL_EXPRS;
|
||||
}
|
||||
|
||||
fn parse_dot_or_call_expr_with(e0: pexpr) -> pexpr {
|
||||
fn parse_dot_or_call_expr_with(e0: @expr) -> @expr {
|
||||
let mut e = e0;
|
||||
let lo = e.span.lo;
|
||||
let mut hi;
|
||||
|
@ -1150,8 +1127,7 @@ impl Parser {
|
|||
self.parse_seq_to_gt(Some(token::COMMA),
|
||||
|p| p.parse_ty(false))
|
||||
} else { ~[] };
|
||||
e = self.mk_pexpr(lo, hi, expr_field(self.to_expr(e), i,
|
||||
tys));
|
||||
e = self.mk_expr(lo, hi, expr_field(e, i, tys));
|
||||
}
|
||||
_ => self.unexpected()
|
||||
}
|
||||
|
@ -1167,8 +1143,8 @@ impl Parser {
|
|||
|p| p.parse_expr());
|
||||
hi = self.span.hi;
|
||||
|
||||
let nd = expr_call(self.to_expr(e), es, false);
|
||||
e = self.mk_pexpr(lo, hi, nd);
|
||||
let nd = expr_call(e, es, false);
|
||||
e = self.mk_expr(lo, hi, nd);
|
||||
}
|
||||
|
||||
// expr[...]
|
||||
|
@ -1177,7 +1153,7 @@ impl Parser {
|
|||
let ix = self.parse_expr();
|
||||
hi = ix.span.hi;
|
||||
self.expect(token::RBRACKET);
|
||||
e = self.mk_pexpr(lo, hi, expr_index(self.to_expr(e), ix));
|
||||
e = self.mk_expr(lo, hi, expr_index(e, ix));
|
||||
}
|
||||
|
||||
_ => return e
|
||||
|
@ -1326,7 +1302,7 @@ impl Parser {
|
|||
}
|
||||
|
||||
|
||||
fn parse_prefix_expr() -> pexpr {
|
||||
fn parse_prefix_expr() -> @expr {
|
||||
let lo = self.span.lo;
|
||||
let mut hi;
|
||||
|
||||
|
@ -1334,7 +1310,7 @@ impl Parser {
|
|||
match copy self.token {
|
||||
token::NOT => {
|
||||
self.bump();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
self.get_id(); // see ast_util::op_expr_callee_id
|
||||
ex = expr_unary(not, e);
|
||||
|
@ -1343,21 +1319,21 @@ impl Parser {
|
|||
match b {
|
||||
token::MINUS => {
|
||||
self.bump();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
self.get_id(); // see ast_util::op_expr_callee_id
|
||||
ex = expr_unary(neg, e);
|
||||
}
|
||||
token::STAR => {
|
||||
self.bump();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
ex = expr_unary(deref, e);
|
||||
}
|
||||
token::AND => {
|
||||
self.bump();
|
||||
let m = self.parse_mutability();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
// HACK: turn &[...] into a &-evec
|
||||
ex = match e.node {
|
||||
|
@ -1374,7 +1350,7 @@ impl Parser {
|
|||
token::AT => {
|
||||
self.bump();
|
||||
let m = self.parse_mutability();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
// HACK: turn @[...] into a @-evec
|
||||
ex = match e.node {
|
||||
|
@ -1386,7 +1362,7 @@ impl Parser {
|
|||
token::TILDE => {
|
||||
self.bump();
|
||||
let m = self.parse_mutability();
|
||||
let e = self.to_expr(self.parse_prefix_expr());
|
||||
let e = self.parse_prefix_expr();
|
||||
hi = e.span.hi;
|
||||
// HACK: turn ~[...] into a ~-evec
|
||||
ex = match e.node {
|
||||
|
@ -1397,18 +1373,17 @@ impl Parser {
|
|||
}
|
||||
_ => return self.parse_dot_or_call_expr()
|
||||
}
|
||||
return self.mk_pexpr(lo, hi, ex);
|
||||
return self.mk_expr(lo, hi, ex);
|
||||
}
|
||||
|
||||
|
||||
fn parse_binops() -> @expr {
|
||||
return self.parse_more_binops(self.parse_prefix_expr(), 0u);
|
||||
return self.parse_more_binops(self.parse_prefix_expr(), 0);
|
||||
}
|
||||
|
||||
fn parse_more_binops(plhs: pexpr, min_prec: uint) ->
|
||||
fn parse_more_binops(lhs: @expr, min_prec: uint) ->
|
||||
@expr {
|
||||
let lhs = self.to_expr(plhs);
|
||||
if self.expr_is_complete(plhs) { return lhs; }
|
||||
if self.expr_is_complete(lhs) { return lhs; }
|
||||
let peeked = self.token;
|
||||
if peeked == token::BINOP(token::OR) &&
|
||||
(self.restriction == RESTRICT_NO_BAR_OP ||
|
||||
|
@ -1428,7 +1403,7 @@ impl Parser {
|
|||
let expr = self.parse_prefix_expr();
|
||||
let rhs = self.parse_more_binops(expr, cur_prec);
|
||||
self.get_id(); // see ast_util::op_expr_callee_id
|
||||
let bin = self.mk_pexpr(lhs.span.lo, rhs.span.hi,
|
||||
let bin = self.mk_expr(lhs.span.lo, rhs.span.hi,
|
||||
expr_binary(cur_op, lhs, rhs));
|
||||
return self.parse_more_binops(bin, min_prec);
|
||||
}
|
||||
|
@ -1438,7 +1413,7 @@ impl Parser {
|
|||
if as_prec > min_prec && self.eat_keyword(~"as") {
|
||||
let rhs = self.parse_ty(true);
|
||||
let _as =
|
||||
self.mk_pexpr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs));
|
||||
self.mk_expr(lhs.span.lo, rhs.span.hi, expr_cast(lhs, rhs));
|
||||
return self.parse_more_binops(_as, min_prec);
|
||||
}
|
||||
return lhs;
|
||||
|
@ -2173,9 +2148,9 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_is_complete(e: pexpr) -> bool {
|
||||
fn expr_is_complete(e: @expr) -> bool {
|
||||
return self.restriction == RESTRICT_STMT_EXPR &&
|
||||
!classify::expr_requires_semi_to_be_stmt(*e);
|
||||
!classify::expr_requires_semi_to_be_stmt(e);
|
||||
}
|
||||
|
||||
fn parse_block() -> blk {
|
||||
|
|
|
@ -773,7 +773,7 @@ fn print_variant(s: ps, v: ast::variant) {
|
|||
match v.node.kind {
|
||||
ast::tuple_variant_kind(args) => {
|
||||
print_ident(s, v.node.name);
|
||||
if vec::len(args) > 0u {
|
||||
if args.is_not_empty() {
|
||||
popen(s);
|
||||
fn print_variant_arg(s: ps, arg: ast::variant_arg) {
|
||||
print_type(s, arg.ty);
|
||||
|
@ -951,25 +951,11 @@ fn print_possibly_embedded_block_(s: ps, blk: ast::blk, embedded: embed_type,
|
|||
s.ann.post(ann_node);
|
||||
}
|
||||
|
||||
// return and fail, without arguments cannot appear is the discriminant of if,
|
||||
// alt, do, & while unambiguously without being parenthesized
|
||||
fn print_maybe_parens_discrim(s: ps, e: @ast::expr) {
|
||||
let disambig = match e.node {
|
||||
ast::expr_ret(None)
|
||||
| ast::expr_fail(None)
|
||||
| ast::expr_again(*) => true,
|
||||
_ => false
|
||||
};
|
||||
if disambig { popen(s); }
|
||||
print_expr(s, e);
|
||||
if disambig { pclose(s); }
|
||||
}
|
||||
|
||||
fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
|
||||
elseopt: Option<@ast::expr>, chk: bool) {
|
||||
head(s, ~"if");
|
||||
if chk { word_nbsp(s, ~"check"); }
|
||||
print_maybe_parens_discrim(s, test);
|
||||
print_expr(s, test);
|
||||
space(s.s);
|
||||
print_block(s, blk);
|
||||
fn do_else(s: ps, els: Option<@ast::expr>) {
|
||||
|
@ -981,7 +967,7 @@ fn print_if(s: ps, test: @ast::expr, blk: ast::blk,
|
|||
cbox(s, indent_unit - 1u);
|
||||
ibox(s, 0u);
|
||||
word(s.s, ~" else if ");
|
||||
print_maybe_parens_discrim(s, i);
|
||||
print_expr(s, i);
|
||||
space(s.s);
|
||||
print_block(s, t);
|
||||
do_else(s, e);
|
||||
|
@ -1154,8 +1140,8 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
Some(blk_arg)
|
||||
} else { None };
|
||||
print_expr_parens_if_not_bot(s, func);
|
||||
if !has_block || vec::len(base_args) > 0u {
|
||||
print_expr(s, func);
|
||||
if !has_block || base_args.is_not_empty() {
|
||||
popen(s);
|
||||
commasep_exprs(s, inconsistent, base_args);
|
||||
pclose(s);
|
||||
|
@ -1178,15 +1164,14 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
}
|
||||
ast::expr_binary(op, lhs, rhs) => {
|
||||
let prec = operator_prec(op);
|
||||
print_op_maybe_parens(s, lhs, prec);
|
||||
print_expr(s, lhs);
|
||||
space(s.s);
|
||||
word_space(s, ast_util::binop_to_str(op));
|
||||
print_op_maybe_parens(s, rhs, prec + 1u);
|
||||
print_expr(s, rhs);
|
||||
}
|
||||
ast::expr_unary(op, expr) => {
|
||||
word(s.s, ast_util::unop_to_str(op));
|
||||
print_op_maybe_parens(s, expr, parse::prec::unop_prec);
|
||||
print_expr(s, expr);
|
||||
}
|
||||
ast::expr_addr_of(m, expr) => {
|
||||
word(s.s, ~"&");
|
||||
|
@ -1195,7 +1180,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
ast::expr_lit(lit) => print_literal(s, lit),
|
||||
ast::expr_cast(expr, ty) => {
|
||||
print_op_maybe_parens(s, expr, parse::prec::as_prec);
|
||||
print_expr(s, expr);
|
||||
space(s.s);
|
||||
word_space(s, ~"as");
|
||||
print_type_ex(s, ty, true);
|
||||
|
@ -1205,7 +1190,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
ast::expr_while(test, blk) => {
|
||||
head(s, ~"while");
|
||||
print_maybe_parens_discrim(s, test);
|
||||
print_expr(s, test);
|
||||
space(s.s);
|
||||
print_block(s, blk);
|
||||
}
|
||||
|
@ -1220,9 +1205,9 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
ast::expr_match(expr, arms) => {
|
||||
cbox(s, alt_indent_unit);
|
||||
ibox(s, 4u);
|
||||
ibox(s, 4);
|
||||
word_nbsp(s, ~"match");
|
||||
print_maybe_parens_discrim(s, expr);
|
||||
print_expr(s, expr);
|
||||
space(s.s);
|
||||
bopen(s);
|
||||
let len = arms.len();
|
||||
|
@ -1335,12 +1320,9 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
print_block(s, blk);
|
||||
}
|
||||
ast::expr_copy(e) => { word_space(s, ~"copy"); print_expr(s, e); }
|
||||
// shouldn't parenthesize unless it's needed
|
||||
ast::expr_unary_move(e) => {
|
||||
popen(s);
|
||||
word_space(s, ~"move");
|
||||
print_expr(s, e);
|
||||
pclose(s);
|
||||
}
|
||||
ast::expr_assign(lhs, rhs) => {
|
||||
print_expr(s, lhs);
|
||||
|
@ -1362,12 +1344,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
print_expr(s, rhs);
|
||||
}
|
||||
ast::expr_field(expr, id, tys) => {
|
||||
// Deal with '10.x'
|
||||
if ends_in_lit_int(expr) {
|
||||
popen(s); print_expr(s, expr); pclose(s);
|
||||
} else {
|
||||
print_expr_parens_if_not_bot(s, expr);
|
||||
}
|
||||
print_expr(s, expr);
|
||||
word(s.s, ~".");
|
||||
print_ident(s, id);
|
||||
if vec::len(tys) > 0u {
|
||||
|
@ -1377,7 +1354,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
}
|
||||
}
|
||||
ast::expr_index(expr, index) => {
|
||||
print_expr_parens_if_not_bot(s, expr);
|
||||
print_expr(s, expr);
|
||||
word(s.s, ~"[");
|
||||
print_expr(s, index);
|
||||
word(s.s, ~"]");
|
||||
|
@ -1427,27 +1404,16 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
|||
print_expr(s, expr);
|
||||
}
|
||||
ast::expr_mac(m) => print_mac(s, m),
|
||||
ast::expr_paren(e) => {
|
||||
popen(s);
|
||||
print_expr(s, e);
|
||||
pclose(s);
|
||||
}
|
||||
}
|
||||
s.ann.post(ann_node);
|
||||
end(s);
|
||||
}
|
||||
|
||||
fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
|
||||
let parens = match ex.node {
|
||||
ast::expr_fail(_) | ast::expr_ret(_) |
|
||||
ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
|
||||
ast::expr_copy(_) | ast::expr_assign(_, _) |
|
||||
ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
|
||||
ast::expr_log(_, _, _) | ast::expr_assert(_) |
|
||||
ast::expr_call(_, _, true) |
|
||||
ast::expr_vstore(_, _) => true,
|
||||
_ => false
|
||||
};
|
||||
if parens { popen(s); }
|
||||
print_expr(s, ex);
|
||||
if parens { pclose(s); }
|
||||
}
|
||||
|
||||
fn print_local_decl(s: ps, loc: @ast::local) {
|
||||
print_pat(s, loc.node.pat);
|
||||
match loc.node.ty.node {
|
||||
|
@ -1557,7 +1523,7 @@ fn print_pat(s: ps, &&pat: @ast::pat) {
|
|||
match args_ {
|
||||
None => word(s.s, ~"(*)"),
|
||||
Some(args) => {
|
||||
if vec::len(args) > 0u {
|
||||
if args.is_not_empty() {
|
||||
popen(s);
|
||||
commasep(s, inconsistent, args, print_pat);
|
||||
pclose(s);
|
||||
|
@ -1813,7 +1779,7 @@ fn print_view_item(s: ps, item: @ast::view_item) {
|
|||
ast::view_item_use(id, mta, _) => {
|
||||
head(s, ~"extern mod");
|
||||
print_ident(s, id);
|
||||
if vec::len(mta) > 0u {
|
||||
if mta.is_not_empty() {
|
||||
popen(s);
|
||||
commasep(s, consistent, mta, print_meta_item);
|
||||
pclose(s);
|
||||
|
@ -1835,13 +1801,6 @@ fn print_view_item(s: ps, item: @ast::view_item) {
|
|||
end(s); // end outer head-block
|
||||
}
|
||||
|
||||
fn print_op_maybe_parens(s: ps, expr: @ast::expr, outer_prec: uint) {
|
||||
let add_them = need_parens(expr, outer_prec);
|
||||
if add_them { popen(s); }
|
||||
print_expr(s, expr);
|
||||
if add_them { pclose(s); }
|
||||
}
|
||||
|
||||
fn print_mutability(s: ps, mutbl: ast::mutability) {
|
||||
match mutbl {
|
||||
ast::m_mutbl => word_nbsp(s, ~"mut"),
|
||||
|
|
|
@ -462,6 +462,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
|||
v.visit_expr(x, e, v);
|
||||
}
|
||||
expr_mac(mac) => visit_mac(mac, e, v),
|
||||
expr_paren(x) => v.visit_expr(x, e, v),
|
||||
}
|
||||
v.visit_expr_post(ex, e, v);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ fn check_expr(sess: Session, def_map: resolve::DefMap,
|
|||
}
|
||||
}
|
||||
}
|
||||
expr_paren(e) => { check_expr(sess, def_map, method_map,
|
||||
tcx, e, is_const, v); }
|
||||
expr_vstore(_, expr_vstore_slice) |
|
||||
expr_vstore(_, expr_vstore_fixed(_)) |
|
||||
expr_vec(_, m_imm) |
|
||||
|
|
|
@ -72,7 +72,8 @@ fn classify(e: @expr,
|
|||
}
|
||||
|
||||
ast::expr_copy(inner) |
|
||||
ast::expr_unary(_, inner) => {
|
||||
ast::expr_unary(_, inner) |
|
||||
ast::expr_paren(inner) => {
|
||||
classify(inner, def_map, tcx)
|
||||
}
|
||||
|
||||
|
@ -376,6 +377,7 @@ fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr)
|
|||
expr_lit(lit) => Ok(lit_to_const(lit)),
|
||||
// If we have a vstore, just keep going; it has to be a string
|
||||
expr_vstore(e, _) => eval_const_expr_partial(tcx, e),
|
||||
expr_paren(e) => eval_const_expr_partial(tcx, e),
|
||||
_ => Err(~"Unsupported constant expr")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -554,7 +554,7 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
|
|||
expr_break(_) | expr_again(_) | expr_lit(_) | expr_ret(*) |
|
||||
expr_block(*) | expr_unary_move(*) | expr_assign(*) |
|
||||
expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) |
|
||||
expr_repeat(*) => {
|
||||
expr_repeat(*) | expr_paren(*) => {
|
||||
visit::visit_expr(expr, self, vt);
|
||||
}
|
||||
}
|
||||
|
@ -1253,7 +1253,8 @@ impl Liveness {
|
|||
expr_loop_body(e) |
|
||||
expr_do_body(e) |
|
||||
expr_cast(e, _) |
|
||||
expr_unary(_, e) => {
|
||||
expr_unary(_, e) |
|
||||
expr_paren(e) => {
|
||||
self.propagate_through_expr(e, succ)
|
||||
}
|
||||
|
||||
|
@ -1550,7 +1551,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
|
|||
expr_cast(*) | expr_unary(*) | expr_fail(*) |
|
||||
expr_ret(*) | expr_break(*) | expr_again(*) | expr_lit(_) |
|
||||
expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) |
|
||||
expr_struct(*) | expr_repeat(*) => {
|
||||
expr_struct(*) | expr_repeat(*) | expr_paren(*) => {
|
||||
visit::visit_expr(expr, self, vt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,6 +481,8 @@ impl &mem_categorization_ctxt {
|
|||
self.cat_def(expr.id, expr.span, expr_ty, def)
|
||||
}
|
||||
|
||||
ast::expr_paren(e) => self.cat_expr_unadjusted(e),
|
||||
|
||||
ast::expr_addr_of(*) | ast::expr_call(*) |
|
||||
ast::expr_swap(*) | ast::expr_assign(*) |
|
||||
ast::expr_assign_op(*) | ast::expr_fn(*) | ast::expr_fn_block(*) |
|
||||
|
|
|
@ -361,6 +361,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
|
|||
_ => cx.sess.span_bug(e.span, ~"expected to find a const def")
|
||||
}
|
||||
}
|
||||
ast::expr_paren(e) => { return const_expr(cx, e); }
|
||||
_ => cx.sess.span_bug(e.span,
|
||||
~"bad constant expression type in consts::const_expr")
|
||||
};
|
||||
|
|
|
@ -161,7 +161,6 @@ impl Dest : cmp::Eq {
|
|||
|
||||
fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
debug!("trans_to_datum(expr=%s)", bcx.expr_to_str(expr));
|
||||
|
||||
return match bcx.tcx().adjustments.find(expr.id) {
|
||||
None => {
|
||||
trans_to_datum_unadjusted(bcx, expr)
|
||||
|
@ -392,6 +391,9 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
ast::expr_cast(val, _) => {
|
||||
return trans_imm_cast(bcx, val, expr.id);
|
||||
}
|
||||
ast::expr_paren(e) => {
|
||||
return trans_rvalue_datum_unadjusted(bcx, e);
|
||||
}
|
||||
_ => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
expr.span,
|
||||
|
@ -450,6 +452,9 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
|
|||
ast::expr_assign_op(op, dst, src) => {
|
||||
return trans_assign_op(bcx, expr, op, dst, src);
|
||||
}
|
||||
ast::expr_paren(a) => {
|
||||
return trans_rvalue_stmt_unadjusted(bcx, a);
|
||||
}
|
||||
_ => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
expr.span,
|
||||
|
@ -469,6 +474,9 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
|||
trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr)));
|
||||
|
||||
match expr.node {
|
||||
ast::expr_paren(e) => {
|
||||
return trans_rvalue_dps_unadjusted(bcx, e, dest);
|
||||
}
|
||||
ast::expr_path(_) => {
|
||||
return trans_def_dps_unadjusted(bcx, expr,
|
||||
bcx.def(expr.id), dest);
|
||||
|
@ -690,6 +698,9 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
|||
let mut bcx = bcx;
|
||||
|
||||
match expr.node {
|
||||
ast::expr_paren(e) => {
|
||||
return unrooted(bcx, e);
|
||||
}
|
||||
ast::expr_path(_) => {
|
||||
return trans_def_lvalue(bcx, expr, bcx.def(expr.id));
|
||||
}
|
||||
|
|
|
@ -267,6 +267,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
|
|||
}
|
||||
}
|
||||
}
|
||||
expr_paren(e) => mark_for_expr(cx, e),
|
||||
expr_match(*) | expr_block(_) | expr_if(*) |
|
||||
expr_while(*) | expr_fail(_) | expr_break(_) | expr_again(_) |
|
||||
expr_unary(_, _) | expr_lit(_) | expr_assert(_) |
|
||||
|
|
|
@ -2872,24 +2872,6 @@ fn is_pred_ty(fty: t) -> bool {
|
|||
is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
|
||||
}
|
||||
|
||||
/*
|
||||
fn ty_var_id(typ: t) -> TyVid {
|
||||
match get(typ).sty {
|
||||
ty_infer(TyVar(vid)) => return vid,
|
||||
_ => { error!("ty_var_id called on non-var ty"); fail; }
|
||||
}
|
||||
}
|
||||
|
||||
fn int_var_id(typ: t) -> IntVid {
|
||||
match get(typ).sty {
|
||||
ty_infer(IntVar(vid)) => return vid,
|
||||
_ => { error!("ty_var_integral_id called on ty other than \
|
||||
ty_var_integral");
|
||||
fail; }
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Type accessors for AST nodes
|
||||
fn block_ty(cx: ctxt, b: &ast::blk) -> t {
|
||||
return node_id_to_type(cx, b.node.id);
|
||||
|
@ -3094,6 +3076,8 @@ fn expr_kind(tcx: ctxt,
|
|||
RvalueDatumExpr
|
||||
}
|
||||
|
||||
ast::expr_paren(e) => expr_kind(tcx, method_map, e),
|
||||
|
||||
ast::expr_mac(*) => {
|
||||
tcx.sess.span_bug(
|
||||
expr.span,
|
||||
|
|
|
@ -990,11 +990,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
debug!("check_call_inner: after universal quant., fty=%s",
|
||||
fcx.infcx().ty_to_str(fty));
|
||||
|
||||
let supplied_arg_count = vec::len(args);
|
||||
let supplied_arg_count = args.len();
|
||||
|
||||
// Grab the argument types, supplying fresh type variables
|
||||
// if the wrong number of arguments were supplied
|
||||
let expected_arg_count = vec::len(fn_ty.sig.inputs);
|
||||
let expected_arg_count = fn_ty.sig.inputs.len();
|
||||
let formal_tys = if expected_arg_count == supplied_arg_count {
|
||||
fn_ty.sig.inputs.map(|a| a.ty)
|
||||
} else {
|
||||
|
@ -1058,8 +1058,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
|
||||
bot |= check_expr_with_unifier(
|
||||
fcx, *arg, Some(formal_ty),
|
||||
|| demand::assign(fcx, arg.span, formal_ty, *arg)
|
||||
|| demand::assign(fcx, arg.span,
|
||||
formal_ty, *arg)
|
||||
);
|
||||
fcx.write_ty(arg.id, fcx.expr_ty(*arg));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1369,12 +1372,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
let expr_t = structurally_resolved_type(fcx, expr.span,
|
||||
fcx.expr_ty(base));
|
||||
let (base_t, derefs) = do_autoderef(fcx, expr.span, expr_t);
|
||||
let n_tys = vec::len(tys);
|
||||
let n_tys = tys.len();
|
||||
|
||||
match structure_of(fcx, expr.span, base_t) {
|
||||
ty::ty_rec(fields) => {
|
||||
match ty::field_idx(field, fields) {
|
||||
Some(ix) => {
|
||||
if n_tys > 0u {
|
||||
if n_tys > 0 {
|
||||
tcx.sess.span_err(
|
||||
expr.span,
|
||||
~"can't provide type parameters \
|
||||
|
@ -1680,7 +1684,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
ty::mk_estr(tcx, tt)
|
||||
}
|
||||
ast::expr_vec(args, mutbl) => {
|
||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, vec::len(args), vst);
|
||||
let tt = ast_expr_vstore_to_vstore(fcx, ev, args.len(), vst);
|
||||
let t: ty::t = fcx.infcx().next_ty_var();
|
||||
for args.each |e| { bot |= check_expr_with(fcx, *e, t); }
|
||||
ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt)
|
||||
|
@ -1871,6 +1875,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
|||
bot = check_expr(fcx, a, expected);
|
||||
fcx.write_ty(id, fcx.expr_ty(a));
|
||||
}
|
||||
ast::expr_paren(a) => {
|
||||
bot = check_expr_with_unifier(fcx, a, expected, || ());
|
||||
fcx.write_ty(id, fcx.expr_ty(a));
|
||||
do expected.iter |i| {
|
||||
demand::assign(fcx, expr.span, *i, expr);
|
||||
demand::assign(fcx, a.span, *i, a);
|
||||
};
|
||||
}
|
||||
ast::expr_assign(lhs, rhs) => {
|
||||
bot = check_assignment(fcx, expr.span, lhs, rhs, id);
|
||||
}
|
||||
|
@ -2583,9 +2595,9 @@ fn instantiate_path(fcx: @fn_ctxt,
|
|||
|
||||
// determine values for type parameters, using the values given by
|
||||
// the user (if any) and otherwise using fresh type variables
|
||||
let tps = if ty_substs_len == 0u {
|
||||
let tps = if ty_substs_len == 0 {
|
||||
fcx.infcx().next_ty_vars(ty_param_count)
|
||||
} else if ty_param_count == 0u {
|
||||
} else if ty_param_count == 0 {
|
||||
fcx.ccx.tcx.sess.span_err
|
||||
(span, ~"this item does not take type parameters");
|
||||
fcx.infcx().next_ty_vars(ty_param_count)
|
||||
|
|
|
@ -132,6 +132,10 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
|||
instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id,
|
||||
pcx.block_region);
|
||||
|
||||
// structure_of requires type variables to be resolved.
|
||||
// So when we pass in <expected>, it's an error if it
|
||||
// contains type variables.
|
||||
|
||||
// Take the enum type params out of `expected`.
|
||||
match structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_enum(_, ref expected_substs) => {
|
||||
|
@ -151,7 +155,7 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
|||
None => arg_len,
|
||||
Some(ps) => ps.len()
|
||||
};
|
||||
if arg_len > 0u {
|
||||
if arg_len > 0 {
|
||||
// N-ary variant.
|
||||
if arg_len != subpats_len {
|
||||
let s = fmt!("this pattern has %u field%s, but the \
|
||||
|
@ -168,7 +172,7 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
|||
check_pat(pcx, *subpat, *arg_ty);
|
||||
}
|
||||
};
|
||||
} else if subpats_len > 0u {
|
||||
} else if subpats_len > 0 {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, fmt!("this pattern has %u field%s, \
|
||||
but the corresponding variant has no fields",
|
||||
|
|
|
@ -486,6 +486,11 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
|||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
ast::expr_paren(e) => {
|
||||
early_resolve_expr(e, fcx, is_early);
|
||||
}
|
||||
|
||||
// Must resolve bounds on methods with bounded params
|
||||
ast::expr_field(*) | ast::expr_binary(*) |
|
||||
ast::expr_unary(*) | ast::expr_assign_op(*) |
|
||||
|
|
|
@ -3,6 +3,9 @@ trait foo<T> { }
|
|||
fn bar(x: foo<uint>) -> foo<int> {
|
||||
return (x as foo::<int>);
|
||||
//~^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
|
||||
//~^^ ERROR mismatched types: expected `@foo<int>` but found `@foo<uint>`
|
||||
// This is unfortunate -- new handling of parens means the error message
|
||||
// gets printed twice
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -8,7 +8,7 @@ fn enum_chars(start: u8, end: u8) -> ~[char] {
|
|||
assert start < end;
|
||||
let mut i = start;
|
||||
let mut r = ~[];
|
||||
while i <= end { r.push(i as char); i += 1u as u8; }
|
||||
while i <= end { r.push(i as char); i += 1 as u8; }
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -16,16 +16,16 @@ fn enum_uints(start: uint, end: uint) -> ~[uint] {
|
|||
assert start < end;
|
||||
let mut i = start;
|
||||
let mut r = ~[];
|
||||
while i <= end { r.push(i); i += 1u; }
|
||||
while i <= end { r.push(i); i += 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = 'a' as u8, j = 'j' as u8, k = 1u, l = 9u;
|
||||
let a = 'a' as u8, j = 'j' as u8, k = 1, l = 9;
|
||||
let chars = enum_chars(a, j);
|
||||
let ints = enum_uints(k, l);
|
||||
|
||||
assert (same_length(chars, ints));
|
||||
assert same_length(chars, ints);
|
||||
let ps = zip(chars, ints);
|
||||
fail ~"the impossible happened";
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ mod m1 {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
assert(line!() == 14u);
|
||||
assert(col!() == 11u);
|
||||
assert(line!() == 14);
|
||||
assert(col!() == 11);
|
||||
assert(file!().ends_with(~"syntax-extension-source-utils.rs"));
|
||||
assert(stringify!((2*3) + 5) == ~"2 * 3 + 5");
|
||||
assert(stringify!((2*3) + 5) == ~"(2 * 3) + 5");
|
||||
assert(include!("syntax-extension-source-utils-files/includeme.fragment")
|
||||
== ~"victory robot 6");
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue