about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2011-07-27 17:36:37 -0700
committerPaul Stansifer <paul.stansifer@gmail.com>2011-07-28 12:12:08 -0700
commit86f337484eeabb5e74060d3549974b3bd85e7f3b (patch)
tree0685f587648b05ad133da83132d40fb85411437e
parent3d7016ae9575a36fd96ec264274bbe0c660a7758 (diff)
downloadrust-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.rs2
-rw-r--r--src/comp/syntax/ext/base.rs4
-rw-r--r--src/comp/syntax/ext/env.rs6
-rw-r--r--src/comp/syntax/ext/fmt.rs6
-rw-r--r--src/comp/syntax/ext/simplext.rs73
-rw-r--r--src/comp/syntax/fold.rs17
-rw-r--r--src/comp/syntax/parse/parser.rs13
-rw-r--r--src/comp/syntax/print/pprust.rs11
-rw-r--r--src/comp/syntax/visit.rs2
-rw-r--r--src/comp/syntax/walk.rs2
-rw-r--r--src/test/run-pass/macro-by-example-2.rs22
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