Skip to content

Commit 87b56b5

Browse files
committed
Allow [a, b, ..., c] transcription patterns in MBE.
1 parent d2f9b15 commit 87b56b5

File tree

2 files changed

+47
-24
lines changed

2 files changed

+47
-24
lines changed

src/comp/syntax/ext/simplext.rs

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,21 @@ type match_result = option::t[arb_depth[matchable]];
9292
type selector = fn(&matchable) -> match_result ;
9393

9494
fn elts_to_ell(cx: &ext_ctxt, elts: &[@expr])
95-
-> {fixed: [@expr], rep: option::t[@expr]} {
95+
-> {pre: [@expr], rep: option::t[@expr], post: [@expr]} {
9696
let idx: uint = 0u;
97+
let res = none;
9798
for elt: @expr in elts {
9899
alt elt.node {
99100
expr_mac(m) {
100101
alt m.node {
101102
ast::mac_ellipsis. {
102-
let last = ivec::len(elts) - 1u;
103-
if idx != last {
104-
cx.span_fatal(m.span, "ellipses must occur last");
103+
if res != none {
104+
cx.span_fatal(m.span, "only one ellipsis allowed");
105105
}
106-
ret {fixed: ivec::slice(elts, 0u, last - 1u),
107-
rep: some(elts.(last - 1u))};
106+
res = some({pre: ivec::slice(elts, 0u, idx - 1u),
107+
rep: some(elts.(idx - 1u)),
108+
post: ivec::slice(elts, idx + 1u,
109+
ivec::len(elts))});
108110
}
109111
_ { }
110112
}
@@ -113,7 +115,10 @@ fn elts_to_ell(cx: &ext_ctxt, elts: &[@expr])
113115
}
114116
idx += 1u;
115117
}
116-
ret {fixed: elts, rep: none};
118+
ret alt res {
119+
some(val) { val }
120+
none. { {pre: elts, rep: none, post: ~[]} }
121+
}
117122
}
118123

119124
fn option_flatten_map[T, U](f: &fn(&T) -> option::t[U] , v: &[T]) ->
@@ -275,8 +280,8 @@ fn transcribe_exprs(cx: &ext_ctxt, b: &bindings, idx_path: @mutable [uint],
275280
recur: fn(&@expr) -> @expr , exprs: [@expr])
276281
-> [@expr] {
277282
alt elts_to_ell(cx, exprs) {
278-
{fixed: fixed, rep: repeat_me_maybe} {
279-
let res = ivec::map(recur, fixed);
283+
{pre: pre, rep: repeat_me_maybe, post: post} {
284+
let res = ivec::map(recur, pre);
280285
alt repeat_me_maybe {
281286
none. {}
282287
some(repeat_me) {
@@ -324,6 +329,7 @@ fn transcribe_exprs(cx: &ext_ctxt, b: &bindings, idx_path: @mutable [uint],
324329
}
325330
}
326331
}
332+
res += ivec::map(recur, post);
327333
ret res;
328334
}
329335
}
@@ -440,14 +446,25 @@ fn p_t_s_rec(cx: &ext_ctxt, m: &matchable, s: &selector, b: &binders) {
440446
expr_path(p_pth) { p_t_s_r_path(cx, p_pth, s, b); }
441447
expr_vec(p_elts, _, _) {
442448
alt elts_to_ell(cx, p_elts) {
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);
449+
{pre: pre, rep: some(repeat_me), post: post} {
450+
p_t_s_r_length(cx, ivec::len(pre) + ivec::len(post),
451+
true, s, b);
452+
if(ivec::len(pre) > 0u) {
453+
p_t_s_r_actual_vector(cx, pre, true, s, b);
454+
}
455+
p_t_s_r_ellipses(cx, repeat_me, ivec::len(pre), s, b);
456+
457+
if(ivec::len(post) > 0u) {
458+
cx.span_unimpl(e.span,
459+
"matching after `...` not yet supported");
446460
}
447-
p_t_s_r_ellipses(cx, repeat_me, ivec::len(fixed), s, b);
448461
}
449-
{fixed: fixed, rep: none.} {
450-
p_t_s_r_actual_vector(cx, fixed, false, s, b);
462+
{pre: pre, rep: none., post: post} {
463+
if post != ~[] {
464+
cx.bug("elts_to_ell provided an invalid result");
465+
}
466+
p_t_s_r_length(cx, ivec::len(pre), false, s, b);
467+
p_t_s_r_actual_vector(cx, pre, false, s, b);
451468
}
452469
}
453470
}
@@ -606,17 +623,17 @@ fn p_t_s_r_ellipses(cx: &ext_ctxt, repeat_me: @expr, offset: uint,
606623
compose_sels(s, bind select(cx, repeat_me, offset, _)), b);
607624
}
608625

609-
fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: [@expr], repeat_after: bool,
610-
s: &selector, b: &binders) {
611-
fn len_select(cx: &ext_ctxt, m: &matchable, repeat_after: bool, len: uint)
626+
627+
fn p_t_s_r_length(cx: &ext_ctxt, len: uint, at_least: bool, s: selector,
628+
b: &binders) {
629+
fn len_select(cx: &ext_ctxt, m: &matchable, at_least: bool, len: uint)
612630
-> match_result {
613631
ret alt m {
614632
match_expr(e) {
615633
alt e.node {
616634
expr_vec(arg_elts, _, _) {
617635
let actual_len = ivec::len(arg_elts);
618-
if (repeat_after && actual_len >= len)
619-
|| actual_len == len {
636+
if (at_least && actual_len >= len) || actual_len == len {
620637
some(leaf(match_exact))
621638
} else { none }
622639
}
@@ -627,10 +644,11 @@ fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: [@expr], repeat_after: bool,
627644
}
628645
}
629646
b.literal_ast_matchers +=
630-
~[compose_sels(s, bind len_select(cx, _, repeat_after,
631-
ivec::len(elts)))];
632-
647+
~[compose_sels(s, bind len_select(cx, _, at_least, len))];
648+
}
633649

650+
fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: [@expr], repeat_after: bool,
651+
s: &selector, b: &binders) {
634652
let idx: uint = 0u;
635653
while idx < ivec::len(elts) {
636654
fn select(cx: &ext_ctxt, m: &matchable, idx: uint) -> match_result {
@@ -678,7 +696,7 @@ fn add_new_extension(cx: &ext_ctxt, sp: span, arg: @expr,
678696
alt mac.node {
679697
mac_invoc(pth, invoc_arg, body) {
680698
alt path_to_ident(pth) {
681-
some(id) {
699+
some(id) {
682700
alt macro_name {
683701
none. { macro_name = some(id); }
684702
some(other_id) {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,9 @@ fn main() {
4343

4444
assert (#transcr_mixed[10, 5, 4, 3, 2, 1] == 210);
4545

46+
#macro[[#surround[pre, [xs, ...], post],
47+
[pre, xs, ..., post]]];
48+
49+
assert (#surround[1, [2,3,4], 5] == [1,2,3,4,5]);
50+
4651
}

0 commit comments

Comments
 (0)