diff options
| author | Paul Stansifer <paul.stansifer@gmail.com> | 2011-07-27 17:36:37 -0700 |
|---|---|---|
| committer | Paul Stansifer <paul.stansifer@gmail.com> | 2011-07-28 12:12:08 -0700 |
| commit | 86f337484eeabb5e74060d3549974b3bd85e7f3b (patch) | |
| tree | 0685f587648b05ad133da83132d40fb85411437e | |
| parent | 3d7016ae9575a36fd96ec264274bbe0c660a7758 (diff) | |
| download | rust-86f337484eeabb5e74060d3549974b3bd85e7f3b.tar.gz rust-86f337484eeabb5e74060d3549974b3bd85e7f3b.zip | |
Change macro syntax to accept a single expr, not a sequence of exprs.
| -rw-r--r-- | src/comp/syntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/ext/base.rs | 4 | ||||
| -rw-r--r-- | src/comp/syntax/ext/env.rs | 6 | ||||
| -rw-r--r-- | src/comp/syntax/ext/fmt.rs | 6 | ||||
| -rw-r--r-- | src/comp/syntax/ext/simplext.rs | 73 | ||||
| -rw-r--r-- | src/comp/syntax/fold.rs | 17 | ||||
| -rw-r--r-- | src/comp/syntax/parse/parser.rs | 13 | ||||
| -rw-r--r-- | src/comp/syntax/print/pprust.rs | 11 | ||||
| -rw-r--r-- | src/comp/syntax/visit.rs | 2 | ||||
| -rw-r--r-- | src/comp/syntax/walk.rs | 2 | ||||
| -rw-r--r-- | src/test/run-pass/macro-by-example-2.rs | 22 |
11 files changed, 80 insertions, 78 deletions
diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index d5d99a886aa..e09be2b3f33 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -333,7 +333,7 @@ tag expr_ { type mac = spanned[mac_]; tag mac_ { - mac_invoc(path, (@expr)[], option::t[str]); + mac_invoc(path, @expr, option::t[str]); mac_embed_type(@ty); mac_embed_block(blk); mac_ellipsis; diff --git a/src/comp/syntax/ext/base.rs b/src/comp/syntax/ext/base.rs index ed869e79f4e..b83a03c4343 100644 --- a/src/comp/syntax/ext/base.rs +++ b/src/comp/syntax/ext/base.rs @@ -7,10 +7,10 @@ import std::map::new_str_hash; import codemap; type syntax_expander = - fn(&ext_ctxt, span, &(@ast::expr)[], option::t[str]) -> @ast::expr ; + fn(&ext_ctxt, span, @ast::expr, option::t[str]) -> @ast::expr ; type macro_def = {ident: str, ext: syntax_extension}; type macro_definer = - fn(&ext_ctxt, span, &(@ast::expr)[], option::t[str]) -> macro_def ; + fn(&ext_ctxt, span, @ast::expr, option::t[str]) -> macro_def ; tag syntax_extension { normal(syntax_expander); diff --git a/src/comp/syntax/ext/env.rs b/src/comp/syntax/ext/env.rs index 88b3e3a720c..c6fe7237d2a 100644 --- a/src/comp/syntax/ext/env.rs +++ b/src/comp/syntax/ext/env.rs @@ -12,8 +12,12 @@ import std::generic_os; import base::*; export expand_syntax_ext; -fn expand_syntax_ext(cx: &ext_ctxt, sp: codemap::span, args: &(@ast::expr)[], +fn expand_syntax_ext(cx: &ext_ctxt, sp: codemap::span, arg: @ast::expr, body: option::t[str]) -> @ast::expr { + let args: (@ast::expr)[] = alt arg.node { + ast::expr_vec(elts, _, _) { elts } + _ { cx.span_fatal(sp, "#env requires arguments of the form `[...]`.") } + }; if ivec::len[@ast::expr](args) != 1u { cx.span_fatal(sp, "malformed #env call"); } diff --git a/src/comp/syntax/ext/fmt.rs b/src/comp/syntax/ext/fmt.rs index 8fb396392d7..10281a9934d 100644 --- a/src/comp/syntax/ext/fmt.rs +++ b/src/comp/syntax/ext/fmt.rs @@ -16,8 +16,12 @@ import base::*; import codemap::span; export expand_syntax_ext; -fn expand_syntax_ext(cx: &ext_ctxt, sp: span, args: &(@ast::expr)[], +fn expand_syntax_ext(cx: &ext_ctxt, sp: span, arg: @ast::expr, body: option::t[str]) -> @ast::expr { + let args: (@ast::expr)[] = alt arg.node { + ast::expr_vec(elts, _, _) { elts } + _ { cx.span_fatal(sp, "#fmt requires arguments of the form `[...]`.") } + }; if ivec::len[@ast::expr](args) == 0u { cx.span_fatal(sp, "#fmt requires a format string"); } diff --git a/src/comp/syntax/ext/simplext.rs b/src/comp/syntax/ext/simplext.rs index 729e8e5000e..4fa169545e2 100644 --- a/src/comp/syntax/ext/simplext.rs +++ b/src/comp/syntax/ext/simplext.rs @@ -42,7 +42,7 @@ fn path_to_ident(pth: &path) -> option::t[ident] { } //an ivec of binders might be a little big. -type clause = {params: binders[], body: @expr}; +type clause = {params: binders, body: @expr}; /* logically, an arb_depth should contain only one kind of matchable */ tag arb_depth[T] { leaf(T); seq(vec[arb_depth[T]], span); } @@ -107,6 +107,7 @@ fn elts_to_ell(cx: &ext_ctxt, elts: &(@expr)[]) -> option::t[@expr] { } ret some(elts.(0)); } + _ { } } } _ { } @@ -179,6 +180,10 @@ selectors. */ fn use_selectors_to_bind(b: &binders, e: @expr) -> option::t[bindings] { let res = new_str_hash[arb_depth[matchable]](); + //need to do this first, to check vec lengths. + for sel: selector in b.literal_ast_matchers { + alt sel(match_expr(e)) { none. { ret none; } _ { } } + } let never_mind: bool = false; for each pair: @{key: ident, val: selector} in b.real_binders.items() { alt pair.val(match_expr(e)) { @@ -186,12 +191,8 @@ fn use_selectors_to_bind(b: &binders, e: @expr) -> option::t[bindings] { some(mtc) { res.insert(pair.key, mtc); } } } - if never_mind { - ret none; //HACK: `ret` doesn't work in `for each` - } - for sel: selector in b.literal_ast_matchers { - alt sel(match_expr(e)) { none. { ret none; } _ { } } - } + //HACK: `ret` doesn't work in `for each` + if never_mind { ret none; } ret some(res); } @@ -537,8 +538,8 @@ fn p_t_s_r_mac(cx: &ext_ctxt, mac: &ast::mac, s: &selector, b: &binders) { _ { none } } } - b.real_binders.insert(id, - bind select_pt_1(cx, _, select_pt_2)); + let final_step = bind select_pt_1(cx, _, select_pt_2); + b.real_binders.insert(id, compose_sels(s, final_step)); } none. { no_des(cx, pth.span, "under `#<>`"); } } @@ -557,7 +558,8 @@ fn p_t_s_r_mac(cx: &ext_ctxt, mac: &ast::mac, s: &selector, b: &binders) { _ { none } } } - b.real_binders.insert(id, bind select_pt_1(cx, _, select_pt_2)); + let final_step = bind select_pt_1(cx, _, select_pt_2); + b.real_binders.insert(id, compose_sels(s, final_step)); } none. { no_des(cx, blk.span, "under `#{}`"); } } @@ -576,7 +578,7 @@ fn ivec_to_vec[T](v: &T[]) -> vec[T] { fn p_t_s_r_ellipses(cx: &ext_ctxt, repeat_me: @expr, s: &selector, b: &binders) { fn select(cx: &ext_ctxt, repeat_me: @expr, m: &matchable) -> - match_result { + match_result { ret alt m { match_expr(e) { alt e.node { @@ -640,8 +642,15 @@ fn p_t_s_r_actual_vector(cx: &ext_ctxt, elts: (@expr)[], s: &selector, } } -fn add_new_extension(cx: &ext_ctxt, sp: span, args: &(@expr)[], +fn add_new_extension(cx: &ext_ctxt, sp: span, arg: @expr, body: option::t[str]) -> base::macro_def { + let args: (@ast::expr)[] = alt arg.node { + ast::expr_vec(elts, _, _) { elts } + _ { + cx.span_fatal(sp, "#macro requires arguments of the form `[...]`.") + } + }; + let macro_name: option::t[str] = none; let clauses: clause[] = ~[]; for arg: @expr in args { @@ -657,19 +666,16 @@ fn add_new_extension(cx: &ext_ctxt, sp: span, args: &(@expr)[], alt elts.(0u).node { expr_mac(mac) { alt mac.node { - mac_invoc(pth, invoc_args, body) { + mac_invoc(pth, invoc_arg, body) { alt path_to_ident(pth) { some(id) { macro_name = some(id); } none. { cx.span_fatal(pth.span, - "macro name " + "must not be a path"); + "macro name must not be a path"); } } - let bdrses = ~[]; - for arg: @expr in invoc_args { - bdrses += ~[pattern_to_selectors(cx, arg)]; - } - clauses += ~[{params: bdrses, body: elts.(1u)}]; + clauses += ~[{params: pattern_to_selectors(cx, invoc_arg), + body: elts.(1u)}]; // FIXME: check duplicates (or just simplify // the macro arg situation) } @@ -702,32 +708,15 @@ fn add_new_extension(cx: &ext_ctxt, sp: span, args: &(@expr)[], }, ext: normal(ext)}; - - fn generic_extension(cx: &ext_ctxt, sp: span, args: &(@expr)[], + fn generic_extension(cx: &ext_ctxt, sp: span, arg: @expr, body: option::t[str], clauses: clause[]) -> @expr { - - for c: clause in clauses { - if ivec::len(args) != ivec::len(c.params) { cont; } - let i: uint = 0u; - let bdgs: bindings = new_str_hash[arb_depth[matchable]](); - let abort: bool = false; - while i < ivec::len(args) { - alt use_selectors_to_bind(c.params.(i), args.(i)) { - some(new_bindings) { - - /* ick; I wish macros just took one expr */ - for each it: @{key: ident, val: arb_depth[matchable]} in - new_bindings.items() { - bdgs.insert(it.key, it.val); - } - } - none. { abort = true; } - } - i += 1u; + alt use_selectors_to_bind(c.params, arg) { + some(bindings) { + ret transcribe(cx, bindings, c.body) + } + none. { cont; } } - if abort { cont; } - ret transcribe(cx, bdgs, c.body); } cx.span_fatal(sp, "no clauses match macro invocation"); } diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index d52c234205c..57b9ca78ff6 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -130,15 +130,14 @@ fn fold_arg_(a: &arg, fld: ast_fold) -> arg { //used in noop_fold_expr, and possibly elsewhere in the future fn fold_mac_(m: &mac, fld: ast_fold) -> mac { ret {node: - alt m.node { - mac_invoc(pth, args, body) { - mac_invoc(fld.fold_path(pth), - fld.map_exprs(fld.fold_expr, args), body) - } - mac_embed_type(ty) { mac_embed_type(fld.fold_ty(ty)) } - mac_embed_block(blk) { mac_embed_block(fld.fold_block(blk)) } - mac_ellipsis. { mac_ellipsis } - }, + alt m.node { + mac_invoc(pth, arg, body) { + mac_invoc(fld.fold_path(pth), fld.fold_expr(arg), body) + } + mac_embed_type(ty) { mac_embed_type(fld.fold_ty(ty)) } + mac_embed_block(blk) { mac_embed_block(fld.fold_block(blk)) } + mac_ellipsis. { mac_ellipsis } + }, span: m.span}; } diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 79728fade13..e24a5127074 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -1021,11 +1021,18 @@ fn parse_syntax_ext_naked(p: &parser, lo: uint) -> @ast::expr { if ivec::len(pth.node.idents) == 0u { p.fatal("expected a syntax expander name"); } - let es = + //temporary for a backwards-compatible cycle: + let es = if p.peek() == token::LPAREN { parse_seq(token::LPAREN, token::RPAREN, some(token::COMMA), - parse_expr, p); + parse_expr, p) + } else { + parse_seq(token::LBRACKET, token::RBRACKET, some(token::COMMA), + parse_expr, p) + }; let hi = es.span.hi; - ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, es.node, none)); + let e = mk_expr(p, es.span.lo, hi, + ast::expr_vec(es.node, ast::imm, ast::sk_rc)); + ret mk_mac_expr(p, lo, hi, ast::mac_invoc(pth, e, none)); } fn parse_self_method(p: &parser) -> @ast::expr { diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index db3586d9275..0b76f3c27dd 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -642,16 +642,15 @@ fn print_if(s: &ps, test: &@ast::expr, blk: &ast::blk, fn print_mac(s: &ps, m: &ast::mac) { alt m.node { - ast::mac_invoc(path, args, body) { + ast::mac_invoc(path, arg, body) { word(s.s, "#"); print_path(s, path); - if ivec::len(args) > 0u { - popen(s); - commasep_exprs(s, inconsistent, args); - pclose(s); + alt (arg.node) { + ast::expr_vec(_,_,_) {} + _ { word(s.s, " "); } } + print_expr(s, arg); // FIXME: extension 'body' - } ast::mac_embed_type(ty) { word(s.s, "#<"); diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index 7a88b98d476..2b42cfa5651 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -239,7 +239,7 @@ fn visit_exprs[E](exprs: &(@expr)[], e: &E, v: &vt[E]) { fn visit_mac[E](m: mac, e: &E, v: &vt[E]) { alt m.node { - ast::mac_invoc(pth, args, body) { visit_exprs(args, e, v); } + ast::mac_invoc(pth, arg, body) { visit_expr(arg, e, v); } ast::mac_embed_type(ty) { v.visit_ty(ty, e, v); } ast::mac_embed_block(blk) { v.visit_block(blk, e, v); } ast::mac_ellipsis. { } diff --git a/src/comp/syntax/walk.rs b/src/comp/syntax/walk.rs index 528032a1ead..30dbaa05858 100644 --- a/src/comp/syntax/walk.rs +++ b/src/comp/syntax/walk.rs @@ -262,7 +262,7 @@ fn walk_exprs(v: &ast_visitor, exprs: &(@ast::expr)[]) { fn walk_mac(v: &ast_visitor, mac: ast::mac) { alt mac.node { - ast::mac_invoc(pth, args, body) { walk_exprs(v, args); } + ast::mac_invoc(pth, arg, body) { walk_expr(v, arg); } ast::mac_embed_type(ty) { walk_ty(v, ty); } ast::mac_embed_block(blk) { walk_block(v, blk); } ast::mac_ellipsis. { } diff --git a/src/test/run-pass/macro-by-example-2.rs b/src/test/run-pass/macro-by-example-2.rs index 036bd77f2e6..5fde2f49e18 100644 --- a/src/test/run-pass/macro-by-example-2.rs +++ b/src/test/run-pass/macro-by-example-2.rs @@ -1,34 +1,34 @@ fn main() { - #macro([#zip_or_unzip([[x, ...], [y, ...]]), [[x, y], ...]], - [#zip_or_unzip([[xx, yy], ...]), [[xx, ...], [yy, ...]]]); + #macro([#zip_or_unzip[[x, ...], [y, ...]], [[x, y], ...]], + [#zip_or_unzip[[xx, yy], ...], [[xx, ...], [yy, ...]]]); - assert (#zip_or_unzip([[1, 2, 3, 4], [5, 6, 7, 8]]) == + assert (#zip_or_unzip[[1, 2, 3, 4], [5, 6, 7, 8]] == [[1, 5], [2, 6], [3, 7], [4, 8]]); - assert (#zip_or_unzip([[1, 5], [2, 6], [3, 7], [4, 8]]) == + assert (#zip_or_unzip[[1, 5], [2, 6], [3, 7], [4, 8]] == [[1, 2, 3, 4], [5, 6, 7, 8]]); - #macro([#nested([[[x, ...], ...], [[y, ...], ...]]), + #macro([#nested[[[x, ...], ...], [[y, ...], ...]], [[[x, y], ...], ...]]); - assert (#nested([[[1, 2, 3, 4, 5], [7, 8, 9, 10, 11, 12]], - [[-1, -2, -3, -4, -5], [-7, -8, -9, -10, -11, -12]]]) == + assert (#nested[[[1, 2, 3, 4, 5], [7, 8, 9, 10, 11, 12]], + [[-1, -2, -3, -4, -5], [-7, -8, -9, -10, -11, -12]]] == [[[1, -1], [2, -2], [3, -3], [4, -4], [5, -5]], [[7, -7], [8, -8], [9, -9], [10, -10], [11, -11], [12, -12]]]); - #macro([#dup([y, [x, ...]]), [[y, x], ...]]); + #macro([#dup[y, [x, ...]], [[y, x], ...]]); - assert (#dup([1, [1, 2, 3, 4]]) == [[1, 1], [1, 2], [1, 3], [1, 4]]); + assert (#dup[1, [1, 2, 3, 4]] == [[1, 1], [1, 2], [1, 3], [1, 4]]); - #macro([#lambda(x, #<t>, body, #<s>), + #macro([#lambda[x, #<t>, body, #<s>], { fn result(x: t) -> s { ret body } result }]); - assert (#lambda(i, #<uint>, i + 4u, #<uint>)(12u) == 16u) + assert ((#lambda[i, #<uint>, i + 4u, #<uint>])(12u) == 16u) } \ No newline at end of file |
