Skip to content

Commit ea6b8cb

Browse files
committed
---
yaml --- r: 5598 b: refs/heads/master c: 381205b h: refs/heads/master v: v3
1 parent a4a13f9 commit ea6b8cb

File tree

15 files changed

+456
-27
lines changed

15 files changed

+456
-27
lines changed

[refs]

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 5fac684af87e2e9064bb561340a7fa7aadcb21ff
2+
refs/heads/master: 381205b7473765c9e34162bc7e350d67f603d579

trunk/src/comp/middle/alias.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ fn pattern_roots(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat)
642642
fn walk(tcx: ty::ctxt, mut: option::t<unsafe_ty>, pat: @ast::pat,
643643
&set: [pattern_root]) {
644644
alt pat.node {
645-
ast::pat_wild. | ast::pat_lit(_) {}
645+
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) {}
646646
ast::pat_bind(nm) {
647647
set += [{id: pat.id, name: nm, mut: mut, span: pat.span}];
648648
}

trunk/src/comp/middle/check_alt.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,15 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
6262
ret true;
6363
}
6464

65-
6665
alt a.node {
6766
pat_wild. | pat_bind(_) { ret true; }
6867
pat_lit(la) {
6968
alt b.node {
7069
pat_lit(lb) { ret util::common::lit_eq(la, lb); }
70+
pat_range(beginb, endb) {
71+
ret util::common::lit_type_eq(la, beginb) &&
72+
util::common::lit_in_range(la, beginb, endb);
73+
}
7174
_ { ret false; }
7275
}
7376
}
@@ -104,6 +107,19 @@ fn pattern_supersedes(tcx: ty::ctxt, a: @pat, b: @pat) -> bool {
104107
_ { ret pattern_supersedes(tcx, suba, b); }
105108
}
106109
}
110+
pat_range(begina, enda) {
111+
alt b.node {
112+
pat_lit(lb) {
113+
ret util::common::lit_type_eq(lb, begina) &&
114+
util::common::lit_in_range(lb, begina, enda);
115+
}
116+
pat_range(beginb, endb) {
117+
ret util::common::lit_type_eq(begina, beginb) &&
118+
util::common::lit_ranges_overlap(begina, enda, beginb, endb);
119+
}
120+
_ { ret false; }
121+
}
122+
}
107123
}
108124
}
109125

trunk/src/comp/middle/trans_alt.rs

+82-21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import std::{str, vec, option};
1+
import std::{str, vec, option, int};
22
import option::{some, none};
33
import std::map::hashmap;
44

@@ -16,22 +16,34 @@ import util::common::lit_eq;
1616

1717
import trans_common::*;
1818

19-
// An option identifying a branch (either a literal or a tag variant)
19+
// An option identifying a branch (either a literal, a tag variant or a range)
2020
tag opt {
2121
lit(@ast::lit);
2222
var(/* variant id */uint, /* variant dids */{tg: def_id, var: def_id});
23+
range(@ast::lit, @ast::lit);
2324
}
2425
fn opt_eq(a: opt, b: opt) -> bool {
2526
alt a {
2627
lit(la) {
27-
ret alt b { lit(lb) { lit_eq(la, lb) } var(_, _) { false } };
28+
ret alt b { lit(lb) { lit_eq(la, lb) } _ { false } };
2829
}
2930
var(ida, _) {
30-
ret alt b { lit(_) { false } var(idb, _) { ida == idb } };
31+
ret alt b { var(idb, _) { ida == idb } _ { false } };
32+
}
33+
range(la1, la2) {
34+
ret alt b {
35+
range(lb1, lb2) { lit_eq(la1, lb1) && lit_eq(la2, lb2) }
36+
_ { false }
37+
};
3138
}
3239
}
3340
}
34-
fn trans_opt(bcx: @block_ctxt, o: opt) -> result {
41+
42+
tag opt_result {
43+
single_result(result);
44+
range_result(result, result);
45+
}
46+
fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result {
3547
alt o {
3648
lit(l) {
3749
alt l.node {
@@ -40,14 +52,22 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> result {
4052
let {bcx, val: dst} = trans::alloc_ty(bcx, strty);
4153
bcx = trans_vec::trans_str(bcx, s, trans::save_in(dst));
4254
add_clean_temp(bcx, dst, strty);
43-
ret rslt(bcx, dst);
55+
ret single_result(rslt(bcx, dst));
4456
}
4557
_ {
46-
ret rslt(bcx, trans::trans_crate_lit(bcx_ccx(bcx), *l));
58+
ret single_result(
59+
rslt(bcx, trans::trans_crate_lit(bcx_ccx(bcx), *l)));
4760
}
4861
}
4962
}
50-
var(id, _) { ret rslt(bcx, C_int(id as int)); }
63+
var(id, _) { ret single_result(rslt(bcx, C_int(id as int))); }
64+
range(l1, l2) {
65+
let cell1 = trans::empty_dest_cell();
66+
let cell2 = trans::empty_dest_cell();
67+
let bcx = trans::trans_lit(bcx, *l1, trans::by_val(cell1));
68+
let bcx = trans::trans_lit(bcx, *l2, trans::by_val(cell2));
69+
ret range_result(rslt(bcx, *cell1), rslt(bcx, *cell2));
70+
}
5171
}
5272
}
5373

@@ -137,6 +157,9 @@ fn enter_opt(ccx: @crate_ctxt, m: match, opt: opt, col: uint, tag_size: uint,
137157
ast::pat_lit(l) {
138158
ret if opt_eq(lit(l), opt) { some([]) } else { none };
139159
}
160+
ast::pat_range(l1, l2) {
161+
ret if opt_eq(range(l1, l2), opt) { some([]) } else { none };
162+
}
140163
_ { ret some(vec::init_elt(dummy, size)); }
141164
}
142165
}
@@ -210,6 +233,9 @@ fn get_options(ccx: @crate_ctxt, m: match, col: uint) -> [opt] {
210233
for br: match_branch in m {
211234
alt br.pats[col].node {
212235
ast::pat_lit(l) { add_to_set(found, lit(l)); }
236+
ast::pat_range(l1, l2) {
237+
add_to_set(found, range(l1, l2));
238+
}
213239
ast::pat_tag(_, _) {
214240
add_to_set(found, variant_opt(ccx, br.pats[col].id));
215241
}
@@ -296,7 +322,9 @@ fn pick_col(m: match) -> uint {
296322
let i = 0u;
297323
for p: @ast::pat in br.pats {
298324
alt p.node {
299-
ast::pat_lit(_) | ast::pat_tag(_, _) { scores[i] += 1u; }
325+
ast::pat_lit(_) | ast::pat_tag(_, _) | ast::pat_range(_, _) {
326+
scores[i] += 1u;
327+
}
300328
_ { }
301329
}
302330
i += 1u;
@@ -450,6 +478,16 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
450478
_ { test_val = Load(bcx, val); switch }
451479
};
452480
}
481+
range(_, _) {
482+
test_val = Load(bcx, val);
483+
kind = compare;
484+
}
485+
}
486+
}
487+
for o: opt in opts {
488+
alt o {
489+
range(_, _) { kind = compare; break; }
490+
_ { }
453491
}
454492
}
455493
let else_cx =
@@ -473,22 +511,44 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
473511
alt kind {
474512
single. { Br(bcx, opt_cx.llbb); }
475513
switch. {
476-
let r = trans_opt(bcx, opt);
477-
bcx = r.bcx;
478-
AddCase(sw, r.val, opt_cx.llbb);
514+
let res = trans_opt(bcx, opt);
515+
alt res {
516+
single_result(r) {
517+
llvm::LLVMAddCase(sw, r.val, opt_cx.llbb);
518+
bcx = r.bcx;
519+
}
520+
}
479521
}
480522
compare. {
481523
let compare_cx = new_scope_block_ctxt(bcx, "compare_scope");
482524
Br(bcx, compare_cx.llbb);
483525
bcx = compare_cx;
484-
let r = trans_opt(bcx, opt);
485-
bcx = r.bcx;
486526
let t = ty::node_id_to_type(ccx.tcx, pat_id);
487-
let eq =
488-
trans::trans_compare(bcx, ast::eq, test_val, t, r.val, t);
489-
let cleanup_cx = trans::trans_block_cleanups(eq.bcx, compare_cx);
490-
bcx = new_sub_block_ctxt(bcx, "compare_next");
491-
CondBr(cleanup_cx, eq.val, opt_cx.llbb, bcx.llbb);
527+
let res = trans_opt(bcx, opt);
528+
alt res {
529+
single_result(r) {
530+
bcx = r.bcx;
531+
let eq =
532+
trans::trans_compare(bcx, ast::eq, test_val, t, r.val, t);
533+
let cleanup_cx = trans::trans_block_cleanups(
534+
eq.bcx, compare_cx);
535+
bcx = new_sub_block_ctxt(bcx, "compare_next");
536+
CondBr(cleanup_cx, eq.val, opt_cx.llbb, bcx.llbb);
537+
}
538+
range_result(rbegin, rend) {
539+
bcx = rend.bcx;
540+
let ge = trans::trans_compare(bcx, ast::ge, test_val, t,
541+
rbegin.val, t);
542+
let le = trans::trans_compare(ge.bcx, ast::le, test_val, t,
543+
rend.val, t);
544+
let in_range = rslt(le.bcx, And(le.bcx, ge.val, le.val));
545+
/*let*/ bcx = in_range.bcx; //XXX uncomment for assertion
546+
let cleanup_cx =
547+
trans::trans_block_cleanups(bcx, compare_cx);
548+
bcx = new_sub_block_ctxt(bcx, "compare_next");
549+
CondBr(cleanup_cx, in_range.val, opt_cx.llbb, bcx.llbb);
550+
}
551+
}
492552
}
493553
_ { }
494554
}
@@ -501,7 +561,7 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
501561
unpacked = args.vals;
502562
opt_cx = args.bcx;
503563
}
504-
lit(_) { }
564+
lit(_) | range(_, _) { }
505565
}
506566
compile_submatch(opt_cx, enter_opt(ccx, m, opt, col, size, val),
507567
unpacked + vals_left, f, exits);
@@ -673,12 +733,13 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
673733
let val = Load(bcx, val);
674734
bcx = bind_irrefutable_pat(bcx, inner, val, table, true);
675735
}
676-
ast::pat_wild. | ast::pat_lit(_) { }
736+
ast::pat_wild. | ast::pat_lit(_) | ast::pat_range(_, _) { }
677737
}
678738
ret bcx;
679739
}
680740

681741
// Local Variables:
742+
// mode: rust
682743
// fill-column: 78;
683744
// indent-tabs-mode: nil
684745
// c-basic-offset: 4

trunk/src/comp/middle/typeck.rs

+55
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,44 @@ fn check_lit(ccx: @crate_ctxt, lit: @ast::lit) -> ty::t {
12661266
}
12671267
}
12681268

1269+
fn lit_as_uint(l: @ast::lit) -> uint {
1270+
alt l.node {
1271+
ast::lit_uint(u) { u }
1272+
ast::lit_char(c) { c as uint }
1273+
}
1274+
}
1275+
fn lit_as_int(l: @ast::lit) -> int {
1276+
alt l.node {
1277+
ast::lit_int(i) | ast::lit_mach_int(_, i) { i }
1278+
}
1279+
}
1280+
fn lit_as_float(l: @ast::lit) -> str {
1281+
alt l.node {
1282+
ast::lit_float(f) | ast::lit_mach_float(_, f) { f }
1283+
}
1284+
}
1285+
1286+
fn valid_range_bounds(l1: @ast::lit, l2: @ast::lit) -> bool {
1287+
alt l1.node {
1288+
ast::lit_float(s1) | ast::lit_mach_float(_, s1) {
1289+
let s2 = lit_as_float(l2);
1290+
let f1 = util::common::str_to_float(s1);
1291+
let f2 = util::common::str_to_float(s2);
1292+
ret *util::common::min(f1, f2) == f1
1293+
}
1294+
ast::lit_uint(_) | ast::lit_char(_) {
1295+
let u1 = lit_as_uint(l1);
1296+
let u2 = lit_as_uint(l2);
1297+
ret *util::common::min(u1, u2) == u1
1298+
}
1299+
_ {
1300+
let i1 = lit_as_int(l1);
1301+
let i2 = lit_as_int(l2);
1302+
ret *util::common::min(i1, i2) == i1
1303+
}
1304+
}
1305+
}
1306+
12691307
// Pattern checking is top-down rather than bottom-up so that bindings get
12701308
// their types immediately.
12711309
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,
12771315
typ = demand::simple(fcx, pat.span, expected, typ);
12781316
write::ty_only_fixup(fcx, pat.id, typ);
12791317
}
1318+
ast::pat_range(begin, end) {
1319+
if !util::common::lit_is_numeric(begin) ||
1320+
!util::common::lit_is_numeric(end) {
1321+
fcx.ccx.tcx.sess.span_err(pat.span,
1322+
"non-numeric type used in range");
1323+
} else if !valid_range_bounds(begin, end) {
1324+
fcx.ccx.tcx.sess.span_err(begin.span,
1325+
"lower range bound must be less \
1326+
than upper");
1327+
}
1328+
let typ1 = check_lit(fcx.ccx, begin);
1329+
typ1 = demand::simple(fcx, pat.span, expected, typ1);
1330+
write::ty_only_fixup(fcx, pat.id, typ1);
1331+
let typ2 = check_lit(fcx.ccx, end);
1332+
typ2 = demand::simple(fcx, pat.span, typ1, typ2);
1333+
write::ty_only_fixup(fcx, pat.id, typ2);
1334+
}
12801335
ast::pat_bind(name) {
12811336
let vid = lookup_local(fcx, pat.span, pat.id);
12821337
let typ = ty::mk_var(fcx.ccx.tcx, vid);

trunk/src/comp/syntax/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ tag pat_ {
9393
pat_tup([@pat]);
9494
pat_box(@pat);
9595
pat_uniq(@pat);
96+
pat_range(@lit, @lit);
9697
}
9798

9899
tag mutability { mut; imm; maybe_mut; }

trunk/src/comp/syntax/ast_util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ iter pat_bindings(pat: @pat) -> @pat {
7070
}
7171
pat_box(sub) { for each b in pat_bindings(sub) { put b; } }
7272
pat_uniq(sub) { for each b in pat_bindings(sub) { put b; } }
73-
pat_wild. | pat_lit(_) { }
73+
pat_wild. | pat_lit(_) | pat_range(_, _) { }
7474
}
7575
}
7676

@@ -230,3 +230,4 @@ fn ret_by_ref(style: ret_style) -> bool {
230230
// buffer-file-coding-system: utf-8-unix
231231
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
232232
// End:
233+

trunk/src/comp/syntax/fold.rs

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ fn noop_fold_pat(p: pat_, fld: ast_fold) -> pat_ {
292292
pat_tup(elts) { pat_tup(vec::map(fld.fold_pat, elts)) }
293293
pat_box(inner) { pat_box(fld.fold_pat(inner)) }
294294
pat_uniq(inner) { pat_uniq(fld.fold_pat(inner)) }
295+
pat_range(_, _) { p }
295296
};
296297
}
297298

trunk/src/comp/syntax/parse/parser.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1494,8 +1494,14 @@ fn parse_pat(p: parser) -> @ast::pat {
14941494
tok {
14951495
if !is_ident(tok) || is_word(p, "true") || is_word(p, "false") {
14961496
let lit = parse_lit(p);
1497-
hi = lit.span.hi;
1498-
pat = ast::pat_lit(@lit);
1497+
if eat_word(p, "to") {
1498+
let end = parse_lit(p);
1499+
hi = end.span.hi;
1500+
pat = ast::pat_range(@lit, @end);
1501+
} else {
1502+
hi = lit.span.hi;
1503+
pat = ast::pat_lit(@lit);
1504+
}
14991505
} else if is_plain_ident(p) &&
15001506
alt p.look_ahead(1u) {
15011507
token::DOT. | token::LPAREN. | token::LBRACKET. {

trunk/src/comp/syntax/print/pprust.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,12 @@ fn print_pat(s: ps, pat: @ast::pat) {
11141114
}
11151115
ast::pat_box(inner) { word(s.s, "@"); print_pat(s, inner); }
11161116
ast::pat_uniq(inner) { word(s.s, "~"); print_pat(s, inner); }
1117+
ast::pat_range(begin, end) {
1118+
print_literal(s, begin);
1119+
space(s.s);
1120+
word_space(s, "to");
1121+
print_literal(s, end);
1122+
}
11171123
}
11181124
s.ann.post(ann_node);
11191125
}

0 commit comments

Comments
 (0)