@@ -88,14 +88,31 @@ type match_branch =
88
88
id_map : ast_util:: pat_id_map } } ;
89
89
type match = [ match_branch ] ;
90
90
91
- fn matches_always ( p : @ast:: pat ) -> bool {
92
- ret alt p. node {
93
- ast:: pat_wild. { true }
94
- ast:: pat_bind ( _) { true }
95
- ast:: pat_rec ( _, _) { true }
96
- ast:: pat_tup ( _) { true }
97
- _ { false }
98
- } ;
91
+ fn has_nested_bindings ( m : match , col : uint ) -> bool {
92
+ for br in m {
93
+ alt br. pats [ col] . node {
94
+ ast:: pat_bind ( _, some ( _) ) { ret true ; }
95
+ _ { }
96
+ }
97
+ }
98
+ ret false;
99
+ }
100
+
101
+ fn expand_nested_bindings ( m : match , col : uint , val : ValueRef ) -> match {
102
+ let result = [ ] ;
103
+ for br in m {
104
+ alt br. pats [ col] . node {
105
+ ast:: pat_bind ( name, some ( inner) ) {
106
+ let pats = vec:: slice ( br. pats , 0 u, col) + [ inner] +
107
+ vec:: slice ( br. pats , col + 1 u, vec:: len ( br. pats ) ) ;
108
+ result += [ @{ pats: pats,
109
+ bound: br. bound + [ { ident: name, val: val} ]
110
+ with * br} ] ;
111
+ }
112
+ _ { result += [ br] ; }
113
+ }
114
+ }
115
+ result
99
116
}
100
117
101
118
type enter_pat = fn @( @ast:: pat ) -> option:: t < [ @ast:: pat ] > ;
@@ -109,7 +126,7 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
109
126
vec:: slice ( br. pats , col + 1 u, vec:: len ( br. pats ) ) ;
110
127
let new_br = @{ pats: pats,
111
128
bound: alt br. pats [ col] . node {
112
- ast:: pat_bind ( name) {
129
+ ast:: pat_bind ( name, none . ) {
113
130
br . bound + [ { ident: name, val: val} ]
114
131
}
115
132
_ { br. bound }
@@ -123,6 +140,13 @@ fn enter_match(m: match, col: uint, val: ValueRef, e: enter_pat) -> match {
123
140
}
124
141
125
142
fn enter_default ( m : match , col : uint , val : ValueRef ) -> match {
143
+ fn matches_always ( p : @ast:: pat ) -> bool {
144
+ ret alt p. node {
145
+ ast:: pat_wild. | ast:: pat_bind ( _, none. ) | ast:: pat_rec ( _, _) |
146
+ ast:: pat_tup ( _) { true }
147
+ _ { false }
148
+ } ;
149
+ }
126
150
fn e ( p : @ast:: pat ) -> option:: t < [ @ast:: pat ] > {
127
151
ret if matches_always ( p) { some ( [ ] ) } else { none } ;
128
152
}
@@ -303,18 +327,17 @@ type exit_node = {bound: bind_map, from: BasicBlockRef, to: BasicBlockRef};
303
327
type mk_fail = fn @( ) -> BasicBlockRef ;
304
328
305
329
fn pick_col ( m : match ) -> uint {
330
+ fn score ( p : @ast:: pat ) -> uint {
331
+ alt p. node {
332
+ ast:: pat_lit ( _) | ast:: pat_tag ( _, _) | ast:: pat_range ( _, _) { 1 u }
333
+ ast:: pat_bind ( _, some ( p) ) { score ( p) }
334
+ _ { 0 u }
335
+ }
336
+ }
306
337
let scores = vec:: init_elt_mut ( 0 u, vec:: len ( m[ 0 ] . pats ) ) ;
307
338
for br: match_branch in m {
308
339
let i = 0 u;
309
- for p: @ast:: pat in br. pats {
310
- alt p. node {
311
- ast:: pat_lit ( _) | ast:: pat_tag ( _, _) | ast:: pat_range ( _, _) {
312
- scores[ i] += 1 u;
313
- }
314
- _ { }
315
- }
316
- i += 1 u;
317
- }
340
+ for p: @ast:: pat in br. pats { scores[ i] += score ( p) ; i += 1 u; }
318
341
}
319
342
let max_score = 0 u;
320
343
let best_col = 0 u;
@@ -368,6 +391,9 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail,
368
391
369
392
let col = pick_col ( m) ;
370
393
let val = vals[ col] ;
394
+ let m = has_nested_bindings ( m, col) ?
395
+ expand_nested_bindings ( m, col, val) : m;
396
+
371
397
let vals_left =
372
398
vec:: slice ( vals, 0 u, col) +
373
399
vec:: slice ( vals, col + 1 u, vec:: len ( vals) ) ;
@@ -662,7 +688,7 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
662
688
make_copy : bool ) -> @block_ctxt {
663
689
let ccx = bcx. fcx . lcx . ccx , bcx = bcx;
664
690
alt pat. node {
665
- ast:: pat_bind ( _) {
691
+ ast:: pat_bind ( _, inner ) {
666
692
if make_copy || ccx. copy_map . contains_key ( pat. id ) {
667
693
let ty = ty:: node_id_to_monotype ( ccx. tcx , pat. id ) ;
668
694
// FIXME: Could constrain pat_bind to make this
@@ -676,6 +702,10 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef,
676
702
bcx. fcx . lllocals . insert ( pat. id , local_mem ( alloc) ) ;
677
703
trans_common:: add_clean ( bcx, alloc, ty) ;
678
704
} else { bcx. fcx . lllocals . insert ( pat. id , local_mem ( val) ) ; }
705
+ alt inner {
706
+ some( pat) { bcx = bind_irrefutable_pat ( bcx, pat, val, true ) ; }
707
+ _ { }
708
+ }
679
709
}
680
710
ast:: pat_tag ( _, sub) {
681
711
if vec:: len ( sub) == 0 u { ret bcx; }
0 commit comments