diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 3a71f361b4c387996de971b4081a7ced57ca2190..03a060a57fd57235e67b5b6035fd4484523d4a3a 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -642,7 +642,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t, pat: @ast::pat) fn walk(tcx: ty::ctxt, mut: option::t, 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}]; } diff --git a/src/comp/middle/check_alt.rs b/src/comp/middle/check_alt.rs index 52d9755108fa84b40ad673e2c4442ab33f5062e8..236b040335886882c9d6ac698bd47e2e5e8787af 100644 --- a/src/comp/middle/check_alt.rs +++ b/src/comp/middle/check_alt.rs @@ -62,12 +62,15 @@ fn field_patterns_supersede(tcx: ty::ctxt, fas: [field_pat], 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 field_patterns_supersede(tcx: ty::ctxt, fas: [field_pat], _ { 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; } + } + } } } diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs index e2386f9623cab1e79ba165c2792d71031e7647c1..175b8b9ec9b8f7aba378cc9d549b16687d912228 100644 --- a/src/comp/middle/trans_alt.rs +++ b/src/comp/middle/trans_alt.rs @@ -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 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 e(ccx: @crate_ctxt, dummy: @ast::pat, opt: opt, 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 add_to_set(&set: [opt], val: 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 diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 3bc74662ca66f745fbabf78d12b20e5d9a5ffbab..bdf8b91c8ff70f3afaad04c0f867821b44620766 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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); diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index b0793b76ca5b20b5321c747f1029fd1cfe352748..6dced2bf32a6ed9d1f20d080c6af2c2c0406b445 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -93,6 +93,7 @@ pat_tup([@pat]); pat_box(@pat); pat_uniq(@pat); + pat_range(@lit, @lit); } tag mutability { mut; imm; maybe_mut; } diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index 4fd76c6a4c6b8fcaf9c98e768690afc213fa8c4c..c4d0272b95fa10d5e800971b54aacf51770b647b 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -70,7 +70,7 @@ fn pat_id_map(pat: @pat) -> pat_id_map { } 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: + diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 9745b774d8e414d8ff1d6caf260d4a8fe86f5509..bf8504f3c1aa52283385f984790020061bafcd3a 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -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 } }; } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index ba01d4e4a1e149fe6ca148c636ab21c09b4f97a4..b2a89a43ec53d4f9f48ed147ed4fbf33a85285f1 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -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. { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 129d00f0f88603245187a39408c65344777f6f8c..458af7e9b12ee12bf9242b4863b182cac63cbfb3 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -1114,6 +1114,12 @@ fn print_field(s: ps, f: ast::field_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); } diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs index 355fcd934b4fea28be6e69a2e2cbfcce58372ef9..6966cafbe048caecb519b353a8da68dcc852d288 100644 --- a/src/comp/util/common.rs +++ b/src/comp/util/common.rs @@ -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: diff --git a/src/lib/int.rs b/src/lib/int.rs index 98d8bb5e157e196618f48bdb05e35b9aac3d283e..0a6e69ceadc7e3ad32280c057e61fdf08b1e711f 100644 --- a/src/lib/int.rs +++ b/src/lib/int.rs @@ -41,6 +41,29 @@ while lo_ < hi { put lo_; lo_ += 1; } } +fn parse_buf(buf: [u8], radix: uint) -> int { + if vec::len::(buf) == 0u { + log_err "parse_buf(): buf is empty"; + fail; + } + let i = vec::len::(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 { diff --git a/src/test/compile-fail/alt-range-fail-dominate.rs b/src/test/compile-fail/alt-range-fail-dominate.rs new file mode 100644 index 0000000000000000000000000000000000000000..51883e8f8ddbafe01c042d3b0843398392c733f5 --- /dev/null +++ b/src/test/compile-fail/alt-range-fail-dominate.rs @@ -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 {} + }; +} \ No newline at end of file diff --git a/src/test/compile-fail/alt-range-fail.rs b/src/test/compile-fail/alt-range-fail.rs new file mode 100644 index 0000000000000000000000000000000000000000..0a9acdcd4b98b63b86352d4ecdd8b95abe8ead36 --- /dev/null +++ b/src/test/compile-fail/alt-range-fail.rs @@ -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 { } + _ { } + }; +} \ No newline at end of file diff --git a/src/test/run-pass/alt-range.rs b/src/test/run-pass/alt-range.rs new file mode 100644 index 0000000000000000000000000000000000000000..1cd29cb35177bb978e94fb0f8a649ecd6115881c --- /dev/null +++ b/src/test/run-pass/alt-range.rs @@ -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"; } + } +}