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:
Tim Chevalier
2012-10-27 17:14:09 -07:00
parent 17a5d0f3a0
commit 62f98c8ff8
20 changed files with 148 additions and 217 deletions

View File

@@ -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) |

View File

@@ -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")
}
}

View File

@@ -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);
}
}

View File

@@ -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(*) |

View File

@@ -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")
};

View File

@@ -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));
}

View File

@@ -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(_) |

View File

@@ -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,

View File

@@ -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)

View File

@@ -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",

View File

@@ -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(*) |