Skip to content

Commit be4f735

Browse files
committed
Add box patterns
An @ can now be prepended to a pattern to unbox something during pattern matching. Closes #661
1 parent 6cb5c09 commit be4f735

File tree

2 files changed

+68
-13
lines changed

2 files changed

+68
-13
lines changed

Diff for: src/comp/middle/trans_alt.rs

+56-13
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ fn enter_rec(&@crate_ctxt ccx, &match m, uint col, &ast::ident[] fields,
164164
ret result;
165165
}
166166

167+
fn enter_box(&@crate_ctxt ccx, &match m, uint col, ValueRef val) -> match {
168+
auto result = ~[];
169+
auto dummy = @rec(id=0, node=ast::pat_wild, span=rec(lo=0u, hi=0u));
170+
for (match_branch br in m) {
171+
auto pats = ivec::slice(br.pats, 0u, col);
172+
alt (br.pats.(col).node) {
173+
ast::pat_box(?sub) { pats += ~[sub]; }
174+
_ { pats += ~[dummy]; }
175+
}
176+
pats += ivec::slice(br.pats, col + 1u, ivec::len(br.pats));
177+
auto new_br = @rec(pats=pats with *br);
178+
result += ~[new_br];
179+
bind_for_pat(br.pats.(col), new_br, val);
180+
}
181+
ret result;
182+
}
183+
167184
fn get_options(&@crate_ctxt ccx, &match m, uint col) -> opt[] {
168185
fn add_to_set(&mutable opt[] set, &opt val) {
169186
for (opt l in set) {
@@ -211,6 +228,33 @@ fn extract_variant_args(@block_ctxt bcx, ast::node_id pat_id,
211228
ret tup(args, bcx);
212229
}
213230

231+
fn collect_record_fields(&match m, uint col) -> ast::ident[] {
232+
auto fields = ~[];
233+
for (match_branch br in m) {
234+
alt (br.pats.(col).node) {
235+
ast::pat_rec(?fs, _) {
236+
for (ast::field_pat f in fs) {
237+
if (!ivec::any(bind str::eq(f.ident, _), fields)) {
238+
fields += ~[f.ident];
239+
}
240+
}
241+
}
242+
_ {}
243+
}
244+
}
245+
ret fields;
246+
}
247+
248+
fn any_box_pat(&match m, uint col) -> bool {
249+
for (match_branch br in m) {
250+
alt (br.pats.(col).node) {
251+
ast::pat_box(_) { ret true; }
252+
_ {}
253+
}
254+
}
255+
ret false;
256+
}
257+
214258
type exit_node = rec(bind_map bound,
215259
BasicBlockRef from,
216260
BasicBlockRef to);
@@ -236,24 +280,13 @@ fn compile_submatch(@block_ctxt bcx, &match m, ValueRef[] vals, &mk_fail f,
236280
auto vals_left = ivec::slice(vals, 1u, ivec::len(vals));
237281
auto ccx = bcx.fcx.lcx.ccx;
238282
auto pat_id = 0;
239-
240-
auto rec_fields = ~[];
241283
for (match_branch br in m) {
242284
// Find a real id (we're adding placeholder wildcard patterns, but
243285
// each column is guaranteed to have at least one real pattern)
244286
if (pat_id == 0) { pat_id = br.pats.(col).id; }
245-
// Gather field names
246-
alt (br.pats.(col).node) {
247-
ast::pat_rec(?fs, _) {
248-
for (ast::field_pat f in fs) {
249-
if (!ivec::any(bind str::eq(f.ident, _), rec_fields)) {
250-
rec_fields += ~[f.ident];
251-
}
252-
}
253-
}
254-
_ {}
255-
}
256287
}
288+
289+
auto rec_fields = collect_record_fields(m, col);
257290
// Separate path for extracting and binding record fields
258291
if (ivec::len(rec_fields) > 0u) {
259292
auto rec_ty = ty::node_id_to_monotype(ccx.tcx, pat_id);
@@ -273,6 +306,16 @@ fn compile_submatch(@block_ctxt bcx, &match m, ValueRef[] vals, &mk_fail f,
273306
ret;
274307
}
275308

309+
// Unbox in case of a box field
310+
if (any_box_pat(m, col)) {
311+
auto box = bcx.build.Load(val);
312+
auto unboxed = bcx.build.InBoundsGEP
313+
(box, ~[C_int(0), C_int(back::abi::box_rc_field_body)]);
314+
compile_submatch(bcx, enter_box(ccx, m, col, val),
315+
~[unboxed] + vals_left, f, exits);
316+
ret;
317+
}
318+
276319
// Decide what kind of branch we need
277320
auto opts = get_options(ccx, m, col);
278321
tag branch_kind { no_branch; single; switch; compare; }

Diff for: src/test/run-pass/box-pattern.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
type foo = rec(int a, uint b);
2+
tag bar {
3+
u(@foo);
4+
w(int);
5+
}
6+
7+
fn main() {
8+
assert alt (u(@rec(a=10, b=40u))) {
9+
u(@{a, b}) { a + (b as int) }
10+
_ { 66 }
11+
} == 50;
12+
}

0 commit comments

Comments
 (0)