Skip to content

Commit ab47645

Browse files
committed
Allow patterns of the form `[a, b, c ...] to be matched and transcribed.
1 parent ea2a968 commit ab47645

File tree

6 files changed

+99
-71
lines changed

6 files changed

+99
-71
lines changed

src/comp/syntax/ext/simplext.rs

Lines changed: 80 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -93,19 +93,20 @@ fn match_error(cx: &ext_ctxt, m: &matchable, expected: &str) -> ! {
9393
type match_result = option::t[arb_depth[matchable]];
9494
type selector = fn(&matchable) -> match_result ;
9595

96-
fn elts_to_ell(cx: &ext_ctxt, elts: &(@expr)[]) -> option::t[@expr] {
96+
fn elts_to_ell(cx: &ext_ctxt, elts: &(@expr)[])
97+
-> {fixed: (@expr)[], rep: option::t[@expr]} {
9798
let idx: uint = 0u;
9899
for elt: @expr in elts {
99100
alt elt.node {
100101
expr_mac(m) {
101102
alt m.node {
102103
ast::mac_ellipsis. {
103-
if idx != 1u || ivec::len(elts) != 2u {
104-
cx.span_fatal(m.span,
105-
"Ellpisis may only appear" +
106-
" after exactly 1 item.");
104+
let last = ivec::len(elts) - 1u;
105+
if idx != last {
106+
cx.span_fatal(m.span, "ellipses must occur last");
107107
}
108-
ret some(elts.(0));
108+
ret {fixed: ivec::slice(elts, 0u, last - 1u),
109+
rep: some(elts.(last - 1u))};
109110
}
110111
_ { }
111112
}
@@ -114,7 +115,7 @@ fn elts_to_ell(cx: &ext_ctxt, elts: &(@expr)[]) -> option::t[@expr] {
114115
}
115116
idx += 1u;
116117
}
117-
ret none;
118+
ret {fixed: elts, rep: none};
118119
}
119120

120121
fn option_flatten_map[T, U](f: &fn(&T) -> option::t[U] , v: &vec[T]) ->
@@ -271,57 +272,60 @@ iter free_vars(b: &bindings, e: @expr) -> ident {
271272

272273
/* handle sequences (anywhere in the AST) of exprs, either real or ...ed */
273274
fn transcribe_exprs(cx: &ext_ctxt, b: &bindings, idx_path: @mutable vec[uint],
274-
recur: fn(&@expr) -> @expr , exprs: (@expr)[]) ->
275-
(@expr)[] {
275+
recur: fn(&@expr) -> @expr , exprs: (@expr)[])
276+
-> (@expr)[] {
276277
alt elts_to_ell(cx, exprs) {
277-
some(repeat_me) {
278-
let repeat: option::t[{rep_count: uint, name: ident}] = none;
279-
/* we need to walk over all the free vars in lockstep, except for
280-
the leaves, which are just duplicated */
281-
for each fv: ident in free_vars(b, repeat_me) {
282-
let cur_pos = follow(b.get(fv), idx_path);
283-
alt cur_pos {
284-
leaf(_) { }
285-
seq(ms, _) {
286-
alt repeat {
287-
none. {
288-
repeat = some({rep_count: vec::len(ms), name: fv});
289-
}
290-
some({rep_count: old_len, name: old_name}) {
291-
let len = vec::len(ms);
292-
if old_len != len {
293-
cx.span_fatal(repeat_me.span,
294-
#fmt("'%s' occurs %u times, but ", fv,
295-
len) +
296-
#fmt("'%s' occurs %u times",
297-
old_name, old_len));
278+
{fixed: fixed, rep: repeat_me_maybe} {
279+
let res = ivec::map(recur, fixed);
280+
alt repeat_me_maybe {
281+
none. {}
282+
some(repeat_me) {
283+
let repeat: option::t[{rep_count: uint, name: ident}] = none;
284+
/* we need to walk over all the free vars in lockstep, except for
285+
the leaves, which are just duplicated */
286+
for each fv: ident in free_vars(b, repeat_me) {
287+
let cur_pos = follow(b.get(fv), idx_path);
288+
alt cur_pos {
289+
leaf(_) { }
290+
seq(ms, _) {
291+
alt repeat {
292+
none. {
293+
repeat = some({rep_count: vec::len(ms), name: fv});
294+
}
295+
some({rep_count: old_len, name: old_name}) {
296+
let len = vec::len(ms);
297+
if old_len != len {
298+
let msg = #fmt("'%s' occurs %u times, but ", fv,
299+
len) + #fmt("'%s' occurs %u times",
300+
old_name, old_len);
301+
cx.span_fatal(repeat_me.span, msg);
302+
}
303+
}
298304
}
299305
}
300306
}
301-
}
302307
}
303-
}
304-
let res = ~[];
305-
alt repeat {
306-
none. {
307-
cx.span_fatal(repeat_me.span,
308-
"'...' surrounds an expression without any" +
308+
alt repeat {
309+
none. {
310+
cx.span_fatal(repeat_me.span,
311+
"'...' surrounds an expression without any" +
309312
" repeating syntax variables");
310-
}
311-
some({rep_count: rc, _}) {
312-
/* Whew, we now know how how many times to repeat */
313-
let idx: uint = 0u;
314-
while idx < rc {
315-
vec::push(*idx_path, idx);
316-
res += ~[recur(repeat_me)]; // whew!
317-
vec::pop(*idx_path);
318-
idx += 1u;
313+
}
314+
some({rep_count: rc, _}) {
315+
/* Whew, we now know how how many times to repeat */
316+
let idx: uint = 0u;
317+
while idx < rc {
318+
vec::push(*idx_path, idx);
319+
res += ~[recur(repeat_me)]; // whew!
320+
vec::pop(*idx_path);
321+
idx += 1u;
322+
}
323+
}
319324
}
320325
}
321326
}
322327
ret res;
323328
}
324-
none. { ret ivec::map(recur, exprs); }
325329
}
326330
}
327331

@@ -436,8 +440,15 @@ fn p_t_s_rec(cx: &ext_ctxt, m: &matchable, s: &selector, b: &binders) {
436440
expr_path(p_pth) { p_t_s_r_path(cx, p_pth, s, b); }
437441
expr_vec(p_elts, _, _) {
438442
alt elts_to_ell(cx, p_elts) {
439-
some(repeat_me) { p_t_s_r_ellipses(cx, repeat_me, s, b); }
440-
none. { p_t_s_r_actual_vector(cx, p_elts, s, b); }
443+
{fixed: fixed, rep: some(repeat_me)} {
444+
if(ivec::len(fixed) > 0u) {
445+
p_t_s_r_actual_vector(cx, fixed, true, s, b);
446+
}
447+
p_t_s_r_ellipses(cx, repeat_me, ivec::len(fixed), s, b);
448+
}
449+
{fixed: fixed, rep: none.} {
450+
p_t_s_r_actual_vector(cx, fixed, false, s, b);
451+
}
441452
}
442453
}
443454

@@ -575,20 +586,23 @@ fn ivec_to_vec[T](v: &T[]) -> vec[T] {
575586
ret rs;
576587
}
577588

578-
fn p_t_s_r_ellipses(cx: &ext_ctxt, repeat_me: @expr, s: &selector,
579-
b: &binders) {
580-
fn select(cx: &ext_ctxt, repeat_me: @expr, m: &matchable) ->
589+
fn p_t_s_r_ellipses(cx: &ext_ctxt, repeat_me: @expr, offset: uint,
590+
s: &selector, b: &binders) {
591+
fn select(cx: &ext_ctxt, repeat_me: @expr, offset: uint, m: &matchable) ->
581592
match_result {
582593
ret alt m {
583594
match_expr(e) {
584595
alt e.node {
585596
expr_vec(arg_elts, _, _) {
586-
let elts =
587-
ivec::map(leaf, ivec::map(match_expr, arg_elts));
588-
597+
let elts = [];
598+
let idx = offset;
599+
while idx < ivec::len(arg_elts) {
600+
elts += [leaf(match_expr(arg_elts.(idx)))];
601+
idx += 1u;
602+
}
589603
// using repeat_me.span is a little wacky, but the
590604
// error we want to report is one in the macro def
591-
some(seq(ivec_to_vec(elts), repeat_me.span))
605+
some(seq(elts, repeat_me.span))
592606
}
593607
_ { none }
594608
}
@@ -597,17 +611,20 @@ fn p_t_s_r_ellipses(cx: &ext_ctxt, repeat_me: @expr, s: &selector,
597611
}
598612
}
599613
p_t_s_rec(cx, match_expr(repeat_me),
600-
compose_sels(s, bind select(cx, repeat_me, _)), b);
614+
compose_sels(s, bind select(cx, repeat_me, offset, _)), b);
601615
}
602616

603-
fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: (@expr)[], s: &selector,
604-
b: &binders) {
605-
fn len_select(cx: &ext_ctxt, m: &matchable, len: uint) -> match_result {
617+
fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: (@expr)[], repeat_after: bool,
618+
s: &selector, b: &binders) {
619+
fn len_select(cx: &ext_ctxt, m: &matchable, repeat_after: bool, len: uint)
620+
-> match_result {
606621
ret alt m {
607622
match_expr(e) {
608623
alt e.node {
609624
expr_vec(arg_elts, _, _) {
610-
if ivec::len(arg_elts) == len {
625+
let actual_len = ivec::len(arg_elts);
626+
if (repeat_after && actual_len >= len)
627+
|| actual_len == len {
611628
some(leaf(match_exact))
612629
} else { none }
613630
}
@@ -618,7 +635,8 @@ fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: (@expr)[], s: &selector,
618635
}
619636
}
620637
b.literal_ast_matchers +=
621-
~[compose_sels(s, bind len_select(cx, _, ivec::len(elts)))];
638+
~[compose_sels(s, bind len_select(cx, _, repeat_after,
639+
ivec::len(elts)))];
622640

623641

624642
let idx: uint = 0u;

src/test/run-pass/macro-2.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// xfail-stage0
22

33
fn main() {
4-
#macro([#mylambda(x,body), {fn f(x: int) -> int { ret body }; f}]);
4+
#macro([#mylambda[x,body], {fn f(x: int) -> int { ret body }; f}]);
55

6-
assert(#mylambda(y,y*2)(8) == 16);
6+
assert(#mylambda[y,y*2](8) == 16);
77
}

src/test/run-pass/macro-3.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// xfail-stage0
22

33
fn main() {
4-
#macro([#trivial(), 1*2*4*2*1]);
4+
#macro([#trivial[], 1*2*4*2*1]);
55

6-
assert(#trivial() == 16);
6+
assert(#trivial[] == 16);
77
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn main() {
2-
#macro([#apply(f, [x, ...]), f(x, ...)]);
2+
#macro([#apply[f, [x, ...]], f(x, ...)]);
33

44
fn add(a: int, b: int) -> int { ret a + b; }
55

6-
assert (#apply(add, [1, 15]) == 16);
6+
assert (#apply[add, [1, 15]] == 16);
77
}

src/test/run-pass/macro-by-example-2.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ fn main() {
3131
}]);
3232

3333

34-
assert ((#lambda[i, #<uint>, i + 4u, #<uint>])(12u) == 16u)
34+
assert ((#lambda[i, #<uint>, i + 4u, #<uint>])(12u) == 16u);
35+
36+
#macro[[#sum[x, xs, ...], x + #sum[xs, ...]],
37+
[#sum[], 0]];
38+
39+
assert (#sum[1,2,3,4] == 10);
40+
41+
42+
#macro[[#transcr_mixed[a, as, ...], #sum[6, as, ...] * a]];
43+
44+
assert (#transcr_mixed[10, 5, 4, 3, 2, 1] == 210);
3545

3646
}

src/test/run-pass/macro.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// xfail-stage0
22

33
fn main() {
4-
#macro([#m1(a), a*4]);
5-
assert (#m1(2) == 8);
4+
#macro[[#m1[a], a*4]];
5+
assert (#m1[2] == 8);
66
}

0 commit comments

Comments
 (0)