mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Revert "Revert "Implement pattern ranges for all numeric types.""
This reverts commit a034f87146
.
Conflicts:
src/comp/middle/check_alt.rs
src/comp/middle/trans_alt.rs
src/comp/syntax/ast.rs
src/comp/syntax/ast_util.rs
src/comp/syntax/fold.rs
src/comp/syntax/print/pprust.rs
Conflicts:
src/comp/middle/trans_alt.rs
This commit is contained in:
parent
5fac684af8
commit
381205b747
@ -642,7 +642,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
|
||||
fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
|
||||
&set: [pattern_root]) {
|
||||
alt pat.node {
|
||||
ast::pat_wild. | ast::pat_lit(_) {}
|
||||
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) {}
|
||||
ast::pat_bind(nm) {
|
||||
set += [{id: pat.id, name: nm, mut: mut, span: pat.span}];
|
||||
}
|
||||
|
@ -62,12 +62,15 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
||||
ret true;
|
||||
}
|
||||
|
||||
|
||||
alt a.node {
|
||||
pat_wild. | pat_bind(_) { ret true; }
|
||||
pat_lit(la) {
|
||||
alt b.node {
|
||||
pat_lit(lb) { ret util::common::lit_eq(la, lb); }
|
||||
pat_range(beginb, endb) {
|
||||
ret util::common::lit_type_eq(la, beginb) &&
|
||||
util::common::lit_in_range(la, beginb, endb);
|
||||
}
|
||||
_ { ret false; }
|
||||
}
|
||||
}
|
||||
@ -104,6 +107,19 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
|
||||
_ { ret pattern_supersedes(tcx, suba, b); }
|
||||
}
|
||||
}
|
||||
pat_range(begina, enda) {
|
||||
alt b.node {
|
||||
pat_lit(lb) {
|
||||
ret util::common::lit_type_eq(lb, begina) &&
|
||||
util::common::lit_in_range(lb, begina, enda);
|
||||
}
|
||||
pat_range(beginb, endb) {
|
||||
ret util::common::lit_type_eq(begina, beginb) &&
|
||||
util::common::lit_ranges_overlap(begina, enda, beginb, endb);
|
||||
}
|
||||
_ { ret false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import std::{str, vec, option};
|
||||
import std::{str, vec, option, int};
|
||||
import option::{some, none};
|
||||
import std::map::hashmap;
|
||||
|
||||
@ -16,22 +16,34 @@ import util::common::lit_eq;
|
||||
|
||||
import trans_common::*;
|
||||
|
||||
// An option identifying a branch (either a literal or a tag variant)
|
||||
// An option identifying a branch (either a literal, a tag variant or a range)
|
||||
tag opt {
|
||||
lit(@ast::lit);
|
||||
var(/* variant id */uint, /* variant dids */{tg: def_id, var: def_id});
|
||||
range(@ast::lit, @ast::lit);
|
||||
}
|
||||
fn opt_eq(a: opt, b: opt) -> bool {
|
||||
alt a {
|
||||
lit(la) {
|
||||
ret alt b { lit(lb) { lit_eq(la, lb) } var(_, _) { false } };
|
||||
ret alt b { lit(lb) { lit_eq(la, lb) } _ { false } };
|
||||
}
|
||||
var(ida, _) {
|
||||
ret alt b { lit(_) { false } var(idb, _) { ida == idb } };
|
||||
ret alt b { var(idb, _) { ida == idb } _ { false } };
|
||||
}
|
||||
range(la1, la2) {
|
||||
ret alt b {
|
||||
range(lb1, lb2) { lit_eq(la1, lb1) && lit_eq(la2, lb2) }
|
||||
_ { false }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
fn trans_opt(bcx: @block_ctxt, o: opt) -> result {
|
||||
|
||||
tag opt_result {
|
||||
single_result(result);
|
||||
range_result(result, result);
|
||||
}
|
||||
fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
|
||||
alt o {
|
||||
lit(l) {
|
||||
alt l.node {
|
||||
@ -40,14 +52,22 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> result {
|
||||
let {bcx, val: dst} = trans::alloc_ty(bcx, strty);
|
||||
bcx = trans_vec::trans_str(bcx, s, trans::save_in(dst));
|
||||
add_clean_temp(bcx, dst, strty);
|
||||
ret rslt(bcx, dst);
|
||||
ret single_result(rslt(bcx, dst));
|
||||
}
|
||||
_ {
|
||||
ret rslt(bcx, trans::trans_crate_lit(bcx_ccx(bcx), *l));
|
||||
ret single_result(
|
||||
rslt(bcx, trans::trans_crate_lit(bcx_ccx(bcx), *l)));
|
||||
}
|
||||
}
|
||||
}
|
||||
var(id, _) { ret rslt(bcx, C_int(id as int)); }
|
||||
var(id, _) { ret single_result(rslt(bcx, C_int(id as int))); }
|
||||
range(l1, l2) {
|
||||
let cell1 = trans::empty_dest_cell();
|
||||
let cell2 = trans::empty_dest_cell();
|
||||
let bcx = trans::trans_lit(bcx, *l1, trans::by_val(cell1));
|
||||
let bcx = trans::trans_lit(bcx, *l2, trans::by_val(cell2));
|
||||
ret range_result(rslt(bcx, *cell1), rslt(bcx, *cell2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,6 +157,9 @@ fn enter_opt(ccx: @crate_ctxt, m: match, opt: opt, col: uint, tag_size: uint,
|
||||
ast::pat_lit(l) {
|
||||
ret if opt_eq(lit(l), opt) { some([]) } else { none };
|
||||
}
|
||||
ast::pat_range(l1, l2) {
|
||||
ret if opt_eq(range(l1, l2), opt) { some([]) } else { none };
|
||||
}
|
||||
_ { ret some(vec::init_elt(dummy, size)); }
|
||||
}
|
||||
}
|
||||
@ -210,6 +233,9 @@ fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
|
||||
for br: match_branch in m {
|
||||
alt br.pats[col].node {
|
||||
ast::pat_lit(l) { add_to_set(found, lit(l)); }
|
||||
ast::pat_range(l1, l2) {
|
||||
add_to_set(found, range(l1, l2));
|
||||
}
|
||||
ast::pat_tag(_, _) {
|
||||
add_to_set(found, variant_opt(ccx, br.pats[col].id));
|
||||
}
|
||||
@ -296,7 +322,9 @@ fn pick_col(m: match) -> uint {
|
||||
let i = 0u;
|
||||
for p: @ast::pat in br.pats {
|
||||
alt p.node {
|
||||
ast::pat_lit(_) | ast::pat_tag(_, _) { scores[i] += 1u; }
|
||||
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) {
|
||||
scores[i] += 1u;
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
i += 1u;
|
||||
@ -450,6 +478,16 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
||||
_ { test_val = Load(bcx, val); switch }
|
||||
};
|
||||
}
|
||||
range(_, _) {
|
||||
test_val = Load(bcx, val);
|
||||
kind = compare;
|
||||
}
|
||||
}
|
||||
}
|
||||
for o: opt in opts {
|
||||
alt o {
|
||||
range(_, _) { kind = compare; break; }
|
||||
_ { }
|
||||
}
|
||||
}
|
||||
let else_cx =
|
||||
@ -473,22 +511,44 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
||||
alt kind {
|
||||
single. { Br(bcx, opt_cx.llbb); }
|
||||
switch. {
|
||||
let r = trans_opt(bcx, opt);
|
||||
bcx = r.bcx;
|
||||
AddCase(sw, r.val, opt_cx.llbb);
|
||||
let res = trans_opt(bcx, opt);
|
||||
alt res {
|
||||
single_result(r) {
|
||||
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
|
||||
bcx = r.bcx;
|
||||
}
|
||||
}
|
||||
}
|
||||
compare. {
|
||||
let compare_cx = new_scope_block_ctxt(bcx, "compare_scope");
|
||||
Br(bcx, compare_cx.llbb);
|
||||
bcx = compare_cx;
|
||||
let r = trans_opt(bcx, opt);
|
||||
bcx = r.bcx;
|
||||
let t = ty::node_id_to_type(ccx.tcx, pat_id);
|
||||
let eq =
|
||||
trans::trans_compare(bcx, ast::eq, test_val, t, r.val, t);
|
||||
let cleanup_cx = trans::trans_block_cleanups(eq.bcx, compare_cx);
|
||||
bcx = new_sub_block_ctxt(bcx, "compare_next");
|
||||
CondBr(cleanup_cx, eq.val, opt_cx.llbb, bcx.llbb);
|
||||
let res = trans_opt(bcx, opt);
|
||||
alt res {
|
||||
single_result(r) {
|
||||
bcx = r.bcx;
|
||||
let eq =
|
||||
trans::trans_compare(bcx, ast::eq, test_val, t, r.val, t);
|
||||
let cleanup_cx = trans::trans_block_cleanups(
|
||||
eq.bcx, compare_cx);
|
||||
bcx = new_sub_block_ctxt(bcx, "compare_next");
|
||||
CondBr(cleanup_cx, eq.val, opt_cx.llbb, bcx.llbb);
|
||||
}
|
||||
range_result(rbegin, rend) {
|
||||
bcx = rend.bcx;
|
||||
let ge = trans::trans_compare(bcx, ast::ge, test_val, t,
|
||||
rbegin.val, t);
|
||||
let le = trans::trans_compare(ge.bcx, ast::le, test_val, t,
|
||||
rend.val, t);
|
||||
let in_range = rslt(le.bcx, And(le.bcx, ge.val, le.val));
|
||||
/*let*/ bcx = in_range.bcx; //XXX uncomment for assertion
|
||||
let cleanup_cx =
|
||||
trans::trans_block_cleanups(bcx, compare_cx);
|
||||
bcx = new_sub_block_ctxt(bcx, "compare_next");
|
||||
CondBr(cleanup_cx, in_range.val, opt_cx.llbb, bcx.llbb);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
@ -501,7 +561,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
|
||||
unpacked = args.vals;
|
||||
opt_cx = args.bcx;
|
||||
}
|
||||
lit(_) { }
|
||||
lit(_) | range(_, _) { }
|
||||
}
|
||||
compile_submatch(opt_cx, enter_opt(ccx, m, opt, col, size, val),
|
||||
unpacked + vals_left, f, exits);
|
||||
@ -673,12 +733,13 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
|
||||
let val = Load(bcx, val);
|
||||
bcx = bind_irrefutable_pat(bcx, inner, val, table, true);
|
||||
}
|
||||
ast::pat_wild. | ast::pat_lit(_) { }
|
||||
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) { }
|
||||
}
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
|
@ -1266,6 +1266,44 @@ fn check_lit(ccx: @crate_ctxt, lit: @ast::lit) -> ty::t {
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_as_uint(l: @ast::lit) -> uint {
|
||||
alt l.node {
|
||||
ast::lit_uint(u) { u }
|
||||
ast::lit_char(c) { c as uint }
|
||||
}
|
||||
}
|
||||
fn lit_as_int(l: @ast::lit) -> int {
|
||||
alt l.node {
|
||||
ast::lit_int(i) | ast::lit_mach_int(_, i) { i }
|
||||
}
|
||||
}
|
||||
fn lit_as_float(l: @ast::lit) -> str {
|
||||
alt l.node {
|
||||
ast::lit_float(f) | ast::lit_mach_float(_, f) { f }
|
||||
}
|
||||
}
|
||||
|
||||
fn valid_range_bounds(l1: @ast::lit, l2: @ast::lit) -> bool {
|
||||
alt l1.node {
|
||||
ast::lit_float(s1) | ast::lit_mach_float(_, s1) {
|
||||
let s2 = lit_as_float(l2);
|
||||
let f1 = util::common::str_to_float(s1);
|
||||
let f2 = util::common::str_to_float(s2);
|
||||
ret *util::common::min(f1, f2) == f1
|
||||
}
|
||||
ast::lit_uint(_) | ast::lit_char(_) {
|
||||
let u1 = lit_as_uint(l1);
|
||||
let u2 = lit_as_uint(l2);
|
||||
ret *util::common::min(u1, u2) == u1
|
||||
}
|
||||
_ {
|
||||
let i1 = lit_as_int(l1);
|
||||
let i2 = lit_as_int(l2);
|
||||
ret *util::common::min(i1, i2) == i1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern checking is top-down rather than bottom-up so that bindings get
|
||||
// their types immediately.
|
||||
fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
||||
@ -1277,6 +1315,23 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
|
||||
typ = demand::simple(fcx, pat.span, expected, typ);
|
||||
write::ty_only_fixup(fcx, pat.id, typ);
|
||||
}
|
||||
ast::pat_range(begin, end) {
|
||||
if !util::common::lit_is_numeric(begin) ||
|
||||
!util::common::lit_is_numeric(end) {
|
||||
fcx.ccx.tcx.sess.span_err(pat.span,
|
||||
"non-numeric type used in range");
|
||||
} else if !valid_range_bounds(begin, end) {
|
||||
fcx.ccx.tcx.sess.span_err(begin.span,
|
||||
"lower range bound must be less \
|
||||
than upper");
|
||||
}
|
||||
let typ1 = check_lit(fcx.ccx, begin);
|
||||
typ1 = demand::simple(fcx, pat.span, expected, typ1);
|
||||
write::ty_only_fixup(fcx, pat.id, typ1);
|
||||
let typ2 = check_lit(fcx.ccx, end);
|
||||
typ2 = demand::simple(fcx, pat.span, typ1, typ2);
|
||||
write::ty_only_fixup(fcx, pat.id, typ2);
|
||||
}
|
||||
ast::pat_bind(name) {
|
||||
let vid = lookup_local(fcx, pat.span, pat.id);
|
||||
let typ = ty::mk_var(fcx.ccx.tcx, vid);
|
||||
|
@ -93,6 +93,7 @@ tag pat_ {
|
||||
pat_tup([@pat]);
|
||||
pat_box(@pat);
|
||||
pat_uniq(@pat);
|
||||
pat_range(@lit, @lit);
|
||||
}
|
||||
|
||||
tag mutability { mut; imm; maybe_mut; }
|
||||
|
@ -70,7 +70,7 @@ iter pat_bindings(pat: @pat) -> @pat {
|
||||
}
|
||||
pat_box(sub) { for each b in pat_bindings(sub) { put b; } }
|
||||
pat_uniq(sub) { for each b in pat_bindings(sub) { put b; } }
|
||||
pat_wild. | pat_lit(_) { }
|
||||
pat_wild. | pat_lit(_) | pat_range(_, _) { }
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,3 +230,4 @@ fn ret_by_ref(style: ret_style) -> bool {
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
|
||||
|
@ -292,6 +292,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
|
||||
pat_tup(elts) { pat_tup(vec::map(fld.fold_pat, elts)) }
|
||||
pat_box(inner) { pat_box(fld.fold_pat(inner)) }
|
||||
pat_uniq(inner) { pat_uniq(fld.fold_pat(inner)) }
|
||||
pat_range(_, _) { p }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1494,8 +1494,14 @@ fn parse_pat(p: parser) -> @ast::pat {
|
||||
tok {
|
||||
if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
|
||||
let lit = parse_lit(p);
|
||||
hi = lit.span.hi;
|
||||
pat = ast::pat_lit(@lit);
|
||||
if eat_word(p, "to") {
|
||||
let end = parse_lit(p);
|
||||
hi = end.span.hi;
|
||||
pat = ast::pat_range(@lit, @end);
|
||||
} else {
|
||||
hi = lit.span.hi;
|
||||
pat = ast::pat_lit(@lit);
|
||||
}
|
||||
} else if is_plain_ident(p) &&
|
||||
alt p.look_ahead(1u) {
|
||||
token::DOT. | token::LPAREN. | token::LBRACKET. {
|
||||
|
@ -1114,6 +1114,12 @@ fn print_pat(s: ps, pat: @ast::pat) {
|
||||
}
|
||||
ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
|
||||
ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
|
||||
ast::pat_range(begin, end) {
|
||||
print_literal(s, begin);
|
||||
space(s.s);
|
||||
word_space(s, "to");
|
||||
print_literal(s, end);
|
||||
}
|
||||
}
|
||||
s.ann.post(ann_node);
|
||||
}
|
||||
|
@ -84,6 +84,162 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
|
||||
alt l.node.init { some(i) { ret i.expr.span; } _ { ret def; } }
|
||||
}
|
||||
|
||||
fn lit_is_numeric(l: @ast::lit) -> bool {
|
||||
alt l.node {
|
||||
ast::lit_int(_) | ast::lit_char(_) | ast::lit_uint(_) |
|
||||
ast::lit_mach_int(_, _) | ast::lit_float(_) | ast::lit_mach_float(_,_) {
|
||||
true
|
||||
}
|
||||
_ { false }
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_type_eq(l: @ast::lit, m: @ast::lit) -> bool {
|
||||
alt l.node {
|
||||
ast::lit_str(_) {
|
||||
alt m.node { ast::lit_str(_) { true } _ { false } }
|
||||
}
|
||||
ast::lit_char(_) {
|
||||
alt m.node { ast::lit_char(_) { true } _ { false } }
|
||||
}
|
||||
ast::lit_int(_) {
|
||||
alt m.node { ast::lit_int(_) { true } _ { false } }
|
||||
}
|
||||
ast::lit_uint(_) {
|
||||
alt m.node { ast::lit_uint(_) { true } _ { false } }
|
||||
}
|
||||
ast::lit_mach_int(_, _) {
|
||||
alt m.node { ast::lit_mach_int(_, _) { true } _ { false } }
|
||||
}
|
||||
ast::lit_float(_) {
|
||||
alt m.node { ast::lit_float(_) { true } _ { false } }
|
||||
}
|
||||
ast::lit_mach_float(_, _) {
|
||||
alt m.node { ast::lit_mach_float(_, _) { true } _ { false } }
|
||||
}
|
||||
ast::lit_nil. {
|
||||
alt m.node { ast::lit_nil. { true } _ { false } }
|
||||
}
|
||||
ast::lit_bool(_) {
|
||||
alt m.node { ast::lit_bool(_) { true } _ { false } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_in_range(l: @ast::lit, m1: @ast::lit, m2: @ast::lit) -> bool {
|
||||
alt lits_to_range(m1, m2) {
|
||||
irange(i1, i2) {
|
||||
alt l.node {
|
||||
ast::lit_int(i3) | ast::lit_mach_int(_, i3) {
|
||||
i3 >= *min(i1, i2) && i3 <= *max(i1, i2)
|
||||
}
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
urange(u1, u2) {
|
||||
alt l.node {
|
||||
ast::lit_uint(u3) {
|
||||
u3 >= *min(u1, u2) && u3 <= *max(u1, u2)
|
||||
}
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
crange(c1, c2) {
|
||||
alt l.node {
|
||||
ast::lit_char(c3) {
|
||||
(c3 as uint) >= *min(c1 as uint, c2 as uint) &&
|
||||
(c3 as uint) <= *max(c1 as uint, c2 as uint)
|
||||
}
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
frange(f1, f2) {
|
||||
alt l.node {
|
||||
ast::lit_float(f3) | ast::lit_mach_float(_, f3) {
|
||||
str_to_float(f3) >= *min(f1, f2) &&
|
||||
str_to_float(f3) <= *max(f1, f2)
|
||||
}
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn min<@T>(x: T, y: T) -> @T {
|
||||
ret @(if x > y { y } else { x });
|
||||
}
|
||||
|
||||
fn max<@T>(x: T, y: T) -> @T {
|
||||
ret @(if x > y { x } else { y });
|
||||
}
|
||||
|
||||
fn ranges_overlap<@T>(a1: T, a2: T, b1: T, b2: T) -> bool {
|
||||
let min1 = *min(a1, a2);
|
||||
let max1 = *max(a1, a2);
|
||||
let min2 = *min(b1, b2);
|
||||
let max2 = *max(b1, b2);
|
||||
ret (min1 >= min2 && max1 <= max2) || (min1 <= min2 && max1 >= min2) ||
|
||||
(min1 >= min2 && min1 <= max2) || (max1 >= min2 && max1 <= max2);
|
||||
}
|
||||
|
||||
fn lit_ranges_overlap(a1: @ast::lit, a2: @ast::lit,
|
||||
b1: @ast::lit, b2: @ast::lit) -> bool {
|
||||
alt lits_to_range(a1, a2) {
|
||||
irange(i1, i2) {
|
||||
alt lits_to_range(b1, b2) {
|
||||
irange(i3, i4) { ranges_overlap(i1, i2, i3, i4) }
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
urange(u1, u2) {
|
||||
alt lits_to_range(b1, b2) {
|
||||
urange(u3, u4) { ranges_overlap(u1, u2, u3, u4) }
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
crange(c1, c2) {
|
||||
alt lits_to_range(b1, b2) {
|
||||
crange(c3, c4) { ranges_overlap(c1, c2, c3, c4) }
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
frange(f1, f2) {
|
||||
alt lits_to_range(b1, b2) {
|
||||
frange(f3, f4) { ranges_overlap(f1, f2, f3, f4) }
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag range {
|
||||
irange(int, int);
|
||||
urange(uint, uint);
|
||||
crange(char, char);
|
||||
frange(float, float);
|
||||
}
|
||||
|
||||
fn lits_to_range(l: @ast::lit, r: @ast::lit) -> range {
|
||||
alt l.node {
|
||||
ast::lit_int(i1) | ast::lit_mach_int(_, i1) {
|
||||
alt r.node { ast::lit_int(i2) { irange(i1, i2) } _ { fail } }
|
||||
}
|
||||
ast::lit_uint(u1) {
|
||||
alt r.node { ast::lit_uint(u2) { urange(u1, u2) } _ { fail } }
|
||||
}
|
||||
ast::lit_char(c1) {
|
||||
alt r.node { ast::lit_char(c2) { crange(c1, c2) } _ { fail } }
|
||||
}
|
||||
ast::lit_float(f1) | ast::lit_mach_float(_, f1) {
|
||||
alt r.node { ast::lit_float(f2) | ast::lit_mach_float(_, f2) {
|
||||
frange(str_to_float(f1), str_to_float(f2))
|
||||
}
|
||||
_ { fail } }
|
||||
}
|
||||
_ { fail }
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_eq(l: @ast::lit, m: @ast::lit) -> bool {
|
||||
alt l.node {
|
||||
ast::lit_str(s) {
|
||||
@ -156,6 +312,22 @@ fn float_to_str(num: float, digits: uint) -> str {
|
||||
ret accum;
|
||||
}
|
||||
|
||||
fn str_to_float(num: str) -> float {
|
||||
let digits = str::split(num, '.' as u8);
|
||||
let total = int::from_str(digits[0]) as float;
|
||||
|
||||
fn dec_val(c: char) -> int { ret (c as int) - ('0' as int); }
|
||||
|
||||
let right = digits[1];
|
||||
let len = str::char_len(digits[1]);
|
||||
let i = 1u;
|
||||
while (i < len) {
|
||||
total += dec_val(str::pop_char(right)) as float /
|
||||
(int::pow(10, i) as float);
|
||||
i += 1u;
|
||||
}
|
||||
ret total;
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
|
@ -41,6 +41,29 @@ iter range(lo: int, hi: int) -> int {
|
||||
while lo_ < hi { put lo_; lo_ += 1; }
|
||||
}
|
||||
|
||||
fn parse_buf(buf: [u8], radix: uint) -> int {
|
||||
if vec::len::<u8>(buf) == 0u {
|
||||
log_err "parse_buf(): buf is empty";
|
||||
fail;
|
||||
}
|
||||
let i = vec::len::<u8>(buf) - 1u;
|
||||
let power = 1;
|
||||
if buf[0] == ('-' as u8) {
|
||||
power = -1;
|
||||
i -= 1u;
|
||||
}
|
||||
let n = 0;
|
||||
while true {
|
||||
n += (buf[i] - ('0' as u8) as int) * power;
|
||||
power *= radix as int;
|
||||
if i == 0u { ret n; }
|
||||
i -= 1u;
|
||||
}
|
||||
fail;
|
||||
}
|
||||
|
||||
fn from_str(s: str) -> int { parse_buf(str::bytes(s), 10u) }
|
||||
|
||||
fn to_str(n: int, radix: uint) -> str {
|
||||
assert (0u < radix && radix <= 16u);
|
||||
ret if n < 0 {
|
||||
|
38
src/test/compile-fail/alt-range-fail-dominate.rs
Normal file
38
src/test/compile-fail/alt-range-fail-dominate.rs
Normal file
@ -0,0 +1,38 @@
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
|
||||
fn main() {
|
||||
alt 5u {
|
||||
1u to 10u { }
|
||||
5u to 6u { }
|
||||
};
|
||||
|
||||
alt 5u {
|
||||
4u to 6u { }
|
||||
3u to 5u { }
|
||||
};
|
||||
|
||||
alt 5u {
|
||||
4u to 6u { }
|
||||
5u to 7u { }
|
||||
};
|
||||
|
||||
alt 'c' {
|
||||
'A' to 'z' {}
|
||||
'a' to 'z' {}
|
||||
};
|
||||
|
||||
alt 1.0 {
|
||||
-5.0 to 5.0 {}
|
||||
0.0 to 6.5 {}
|
||||
};
|
||||
|
||||
alt 1.0 {
|
||||
0.02 {}
|
||||
0.01 to 6.5 {}
|
||||
};
|
||||
}
|
19
src/test/compile-fail/alt-range-fail.rs
Normal file
19
src/test/compile-fail/alt-range-fail.rs
Normal file
@ -0,0 +1,19 @@
|
||||
//error-pattern: lower range bound
|
||||
//error-pattern: non-numeric
|
||||
//error-pattern: mismatched types
|
||||
|
||||
fn main() {
|
||||
alt 5u {
|
||||
6u to 1u { }
|
||||
_ { }
|
||||
};
|
||||
|
||||
alt "wow" {
|
||||
"wow" to "woow" { }
|
||||
};
|
||||
|
||||
alt 5u {
|
||||
'c' to 100u { }
|
||||
_ { }
|
||||
};
|
||||
}
|
30
src/test/run-pass/alt-range.rs
Normal file
30
src/test/run-pass/alt-range.rs
Normal file
@ -0,0 +1,30 @@
|
||||
fn main() {
|
||||
alt 5u {
|
||||
1u to 5u {}
|
||||
_ { fail "should match range"; }
|
||||
}
|
||||
alt 5u {
|
||||
6u to 7u { fail "shouldn't match range"; }
|
||||
_ {}
|
||||
}
|
||||
alt 5u {
|
||||
1u { fail "should match non-first range"; }
|
||||
2u to 6u {}
|
||||
}
|
||||
alt 'c' {
|
||||
'a' to 'z' {}
|
||||
_ { fail "should suppport char ranges"; }
|
||||
}
|
||||
alt -3 {
|
||||
-7 to 5 {}
|
||||
_ { fail "should match signed range"; }
|
||||
}
|
||||
alt 3.0 {
|
||||
1.0 to 5.0 {}
|
||||
_ { fail "should match float range"; }
|
||||
}
|
||||
alt -1.5 {
|
||||
-3.6 to 3.6 {}
|
||||
_ { fail "should match negative float range"; }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user