about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorPaul Stansifer <paul.stansifer@gmail.com>2012-11-17 07:41:36 -0500
committerGraydon Hoare <graydon@mozilla.com>2012-11-29 12:09:10 -0800
commitb7fcc9b52e83db053633648a61b1a3f4c8ce25e6 (patch)
tree9d1230412364a067e8fe85eb39acbc6610f213e4 /src/libsyntax/ext
parentcf26a7d7b952cf94fb4bb185c2eb0cb47e4551ce (diff)
Use `biased_match!` to avoid over-deep indentation in expand.rs.
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/expand.rs166
1 files changed, 89 insertions, 77 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b997106b4ed..f919c1f03c0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -10,6 +10,7 @@ use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};
 
 use codemap::{span, ExpandedFrom};
 
+
 fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                e: expr_, s: span, fld: ast_fold,
                orig: fn@(expr_, span, ast_fold) -> (expr_, span))
@@ -191,21 +192,43 @@ fn expand_item(exts: HashMap<~str, syntax_extension>,
     }
 }
 
+// avoid excess indentation when a series of nested `match`es
+// has only one "good" outcome
+macro_rules! biased_match (
+    (   ($e    :expr) ~ ($p    :pat) else $err    :stmt ;
+     $( ($e_cdr:expr) ~ ($p_cdr:pat) else $err_cdr:stmt ; )*
+     => $body:expr
+    ) => (
+        match $e {
+            $p => {
+                biased_match!($( ($e_cdr) ~ ($p_cdr) else $err_cdr ; )*
+                              => $body)
+            }
+            _ => { $err }
+        }
+    );
+    ( => $body:expr ) => ( $body )
+)
+
 
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
 fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                    cx: ext_ctxt, &&it: @ast::item,
                    fld: ast_fold) -> Option<@ast::item> {
-    match it.node {
-      item_mac({node: mac_invoc_tt(pth, tts), _}) => {
-        let extname = cx.parse_sess().interner.get(pth.idents[0]);
-        let (expanded, ex_span) = match exts.find(*extname) {
-          None => {
-            cx.span_fatal(pth.span,
-                          fmt!("macro undefined: '%s!'", *extname))
-          }
-          Some(normal_tt(expand)) => {
+    let (pth, tts) = biased_match!(
+        (it.node) ~ (item_mac({node: mac_invoc_tt(pth, tts), _})) else {
+            cx.span_bug(it.span, ~"invalid item macro invocation")
+        };
+        => (pth, tts)
+    );
+
+    let extname = cx.parse_sess().interner.get(pth.idents[0]);
+    let (expanded, ex_span) = match exts.find(*extname) {
+        None => cx.span_fatal(pth.span,
+                              fmt!("macro undefined: '%s!'", *extname)),
+
+        Some(normal_tt(expand)) => {
             if it.ident != parse::token::special_idents::invalid {
                 cx.span_fatal(pth.span,
                               fmt!("macro %s! expects no ident argument, \
@@ -213,39 +236,35 @@ fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                                    *cx.parse_sess().interner.get(it.ident)));
             }
             (expand.expander(cx, it.span, tts), expand.span)
-          }
-          Some(item_tt(expand)) => {
+        }
+        Some(item_tt(expand)) => {
             if it.ident == parse::token::special_idents::invalid {
                 cx.span_fatal(pth.span,
                               fmt!("macro %s! expects an ident argument",
                                    *extname));
             }
             (expand.expander(cx, it.span, it.ident, tts), expand.span)
-          }
-          _ => cx.span_fatal(
-              it.span, fmt!("%s! is not legal in item position", *extname))
-        };
+        }
+        _ => cx.span_fatal(
+            it.span, fmt!("%s! is not legal in item position", *extname))
+    };
 
-        cx.bt_push(ExpandedFrom({call_site: it.span,
-                                  callie: {name: *extname,
-                                           span: ex_span}}));
-        let maybe_it = match expanded {
-            mr_item(it) => fld.fold_item(it),
-            mr_expr(_) => cx.span_fatal(pth.span,
-                                        ~"expr macro in item position: " +
-                                        *extname),
-            mr_any(_, item_maker, _) =>
-                option::chain(item_maker(), |i| {fld.fold_item(i)}),
-            mr_def(mdef) => {
-                exts.insert(mdef.name, mdef.ext);
-                None
-            }
-        };
-        cx.bt_pop();
-        return maybe_it;
-      }
-      _ => cx.span_bug(it.span, ~"invalid item macro invocation")
-    }
+    cx.bt_push(ExpandedFrom({call_site: it.span,
+                              callie: {name: *extname, span: ex_span}}));
+    let maybe_it = match expanded {
+        mr_item(it) => fld.fold_item(it),
+        mr_expr(_) => cx.span_fatal(pth.span,
+                                    ~"expr macro in item position: "
+                                    + *extname),
+        mr_any(_, item_maker, _) =>
+            option::chain(item_maker(), |i| {fld.fold_item(i)}),
+        mr_def(mdef) => {
+            exts.insert(mdef.name, mdef.ext);
+            None
+        }
+    };
+    cx.bt_pop();
+    return maybe_it;
 }
 
 fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
@@ -253,51 +272,44 @@ fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
     -> (stmt_, span)
 {
-    return match s {
-        stmt_mac(mac) => {
-            match mac.node {
-                mac_invoc_tt(pth, tts) => {
-                    assert(vec::len(pth.idents) == 1u);
-                    let extname = cx.parse_sess().interner.get(pth.idents[0]);
-                    match exts.find(*extname) {
-                        None => {
-                            cx.span_fatal(
-                                pth.span,
-                                fmt!("macro undefined: '%s'", *extname))
-                        }
-                        Some(normal_tt({expander: exp, span: exp_sp})) => {
-                            let expanded = match exp(cx, mac.span, tts) {
-                                mr_expr(e) =>
-                                @{node: ast::stmt_expr(e, cx.next_id()),
-                                  span: e.span},
-                                mr_any(_,_,stmt_mkr) => stmt_mkr(),
-                                _ => cx.span_fatal(
-                                    pth.span,
-                                    fmt!("non-stmt macro in stmt pos: %s",
-                                         *extname))
-                            };
+    let (mac, pth, tts) = biased_match! (
+        (s)        ~ (stmt_mac(mac))          else return orig(s, sp, fld);
+        (mac.node) ~ (mac_invoc_tt(pth, tts)) else {
+            cx.span_bug(mac.span, ~"naked syntactic bit")
+        };
+        => (mac, pth, tts));
+
+    assert(vec::len(pth.idents) == 1u);
+    let extname = cx.parse_sess().interner.get(pth.idents[0]);
+    match exts.find(*extname) {
+        None =>
+            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),
+
+        Some(normal_tt({expander: exp, span: exp_sp})) => {
+            let expanded = match exp(cx, mac.span, tts) {
+                mr_expr(e) =>
+                    @{node: ast::stmt_expr(e, cx.next_id()), span: e.span},
+                mr_any(_,_,stmt_mkr) => stmt_mkr(),
+                _ => cx.span_fatal(
+                    pth.span,
+                    fmt!("non-stmt macro in stmt pos: %s", *extname))
+            };
 
-                            cx.bt_push(ExpandedFrom(
-                                {call_site: sp,
-                                 callie: {name: *extname, span: exp_sp}}));
-                            //keep going, outside-in
-                            let fully_expanded = fld.fold_stmt(expanded).node;
-                            cx.bt_pop();
+            cx.bt_push(ExpandedFrom(
+                {call_site: sp, callie: {name: *extname, span: exp_sp}}));
+            //keep going, outside-in
+            let fully_expanded = fld.fold_stmt(expanded).node;
+            cx.bt_pop();
 
-                            (fully_expanded, sp)
-                        }
-                        _ => {
-                            cx.span_fatal(pth.span,
-                                          fmt!("'%s' is not a tt-style macro",
-                                               *extname))
-                        }
-                    }
-                }
-                _ => cx.span_bug(mac.span, ~"naked syntactic bit")
-            }
+            return (fully_expanded, sp)
         }
-        _ => orig(s, sp, fld)
-    };
+        _ => {
+            cx.span_fatal(pth.span,
+                          fmt!("'%s' is not a tt-style macro",
+                               *extname))
+        }
+    }
+
 }