Skip to content

Allow macro_rules! to also define item and stmt macros #4021

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0faf3ed
Allow `macro_rules!` macros to expand to expressions or items.
paulstansifer Nov 8, 2012
345349d
Grammaticalinate an error message.
paulstansifer Nov 9, 2012
7bb81bf
Make it possible to invoke item macros without passing identifier arg…
paulstansifer Nov 9, 2012
b35992b
Allow for macros to occur in statement position.
paulstansifer Nov 13, 2012
c6b118e
Make it possible to expand stmt macros.
paulstansifer Nov 20, 2012
ae1718f
Use `biased_match!` to avoid over-deep indentation in expand.rs.
paulstansifer Nov 17, 2012
fab9000
Allow the expansion of old-style expr macros in stmt position.
paulstansifer Nov 19, 2012
a160714
No longer parse the delimiters of the RHS of a macro as part of the e…
paulstansifer Nov 20, 2012
5f95bfb
Allow parsing of macros in statement position.
paulstansifer Nov 14, 2012
c7811c2
Make the parser handle stmt macros that might be exprs at the end of …
paulstansifer Nov 19, 2012
bbe5d63
Distinguish `stmt_mac`s that are followed by semicolons and those tha…
paulstansifer Nov 21, 2012
d63f3d5
Forbid item macros from occuring where statement macros might occur, …
paulstansifer Nov 21, 2012
887cf28
Update tests to respect the way that macros work now.
paulstansifer Nov 21, 2012
9b5995e
Respect semicolons always when expanding statments.
paulstansifer Nov 21, 2012
2db3b79
Forbid attrs on macros, since we don't handle them properly yet.
paulstansifer Nov 22, 2012
539fe0e
Test statement macros.
paulstansifer Nov 22, 2012
9962689
Macros can now also be stmts and items.
paulstansifer Nov 22, 2012
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']'

User-defined syntax extensions are called "macros", and they can be defined
with the `macro_rules!` syntax extension. User-defined macros can currently
only be invoked in expression position.
be invoked as expressions, statements, or items.

(A `sep_token` is any token other than `*` and `+`. A `non_special_token` is
any token other than a delimiter or `$`.)
Expand All @@ -510,7 +510,7 @@ For parsing reasons, delimiters must be balanced, but they are otherwise not spe

In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the
Rust syntax named by _designator_. Valid designators are `item`, `block`,
`stmt`, `pat`, `expr`, `ty` (type), `ident`, `path`, `matchers` (lhs of the `=>` in macro rules),
`stmt`, `pat`, `expr`, `ty` (type), `ident`, `path`, `matchers` (lhs of the `=>` in macro rules),
`tt` (rhs of the `=>` in macro rules). In the transcriber, the designator is already known, and so only
the name of a matched nonterminal comes after the dollar sign.

Expand Down Expand Up @@ -2196,7 +2196,7 @@ Records and structures can also be pattern-matched and their fields bound to var
When matching fields of a record,
the fields being matched are specified first,
then a placeholder (`_`) represents the remaining fields.

~~~~
# type options = {choose: bool, size: ~str};
# type player = {player: ~str, stats: (), options: options};
Expand Down Expand Up @@ -2726,7 +2726,7 @@ The kinds are:
structural types containing only other sendable types.
`Owned`
: Types of this kind do not contain any borrowed pointers;
this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions).
this can be a useful guarantee for code that breaks borrowing assumptions using [`unsafe` operations](#unsafe-functions).
`Copy`
: This kind includes all types that can be copied. All types with
sendable kind are copyable, as are managed boxes, managed closures,
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,14 @@ impl &SipState : io::Writer {

macro_rules! compress (
($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
{
({
$v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
$v0 = rotl!($v0, 32);
$v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
$v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
$v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
$v2 = rotl!($v2, 32);
}
})
);

let length = msg.len();
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/pipes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ use option::unwrap;
const SPIN_COUNT: uint = 0;

macro_rules! move_it (
{ $x:expr } => { unsafe { let y = move *ptr::addr_of(&($x)); move y } }
{ $x:expr } => ( unsafe { let y = move *ptr::addr_of(&($x)); move y } )
)

#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/task/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use rt::rust_task;
use rt::rust_closure;

macro_rules! move_it (
{ $x:expr } => { unsafe { let y = move *ptr::addr_of(&($x)); move y } }
{ $x:expr } => ( unsafe { let y = move *ptr::addr_of(&($x)); move y } )
)

type TaskSet = send_map::linear::LinearMap<*rust_task,()>;
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
match stmt.node {
ast::stmt_expr(_, _) | ast::stmt_semi(_, _) |
ast::stmt_decl(@{node: ast::decl_local(_), span: _}, _) => true,
ast::stmt_decl(@{node: ast::decl_item(_), span: _}, _) => false
ast::stmt_decl(@{node: ast::decl_item(_), span: _}, _) => false,
ast::stmt_mac(*) => fail ~"unexpanded macro in astencode"
}
};
let blk_sans_items = { stmts: stmts_sans_items,.. blk };
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,10 @@ impl Liveness {
stmt_expr(expr, _) | stmt_semi(expr, _) => {
return self.propagate_through_expr(expr, succ);
}

stmt_mac(*) => {
self.tcx.sess.span_bug(stmt.span, ~"unexpanded macro");
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ fn resolve_stmt(stmt: @ast::stmt, cx: ctxt, visitor: visit::vt<ctxt>) {
expr_cx.parent = Some(stmt_id);
visit::visit_stmt(stmt, expr_cx, visitor);
}
ast::stmt_mac(*) => cx.sess.bug(~"unexpanded macro")
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/alt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,14 +831,14 @@ fn root_pats_as_necessary(bcx: block, m: &[@Match],
// matches should fit that sort of pattern or NONE (however, some of the
// matches may be wildcards like _ or identifiers).
macro_rules! any_pat (
($m:expr, $pattern:pat) => {
($m:expr, $pattern:pat) => (
vec::any($m, |br| {
match br.pats[col].node {
$pattern => true,
_ => false
}
})
}
)
)

fn any_box_pat(m: &[@Match], col: uint) -> bool {
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block {
ast::decl_item(i) => trans_item(cx.fcx.ccx, *i)
}
}
ast::stmt_mac(*) => cx.tcx().sess.bug(~"unexpanded macro")
}

return bcx;
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,7 @@ fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
return id;
}
ast::stmt_mac(*) => fail ~"unexpanded macro in trans"
}
}

Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/typeck/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,7 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool {
node_id = id;
bot = check_expr(fcx, expr, None);
}
ast::stmt_mac(*) => fcx.ccx.tcx.sess.bug(~"unexpanded macro")
}
fcx.write_nil(node_id);
return bot;
Expand Down
2 changes: 1 addition & 1 deletion src/librusti/rusti.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn record(repl: Repl, blk: @ast::blk, intr: @token::ident_interner) -> Repl {
let new_stmts = do with_pp(intr) |pp, writer| {
for blk.node.stmts.each |stmt| {
match stmt.node {
ast::stmt_decl(*) => {
ast::stmt_decl(*) | ast::stmt_mac(*) => {
pprust::print_stmt(pp, **stmt);
writer.write_line(~"");
}
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,9 @@ enum stmt_ {

// expr with trailing semi-colon (may have any type):
stmt_semi(@expr, node_id),

// bool: is there a trailing sem-colon?
stmt_mac(mac, bool),
}

// FIXME (pending discussion of #1697, #2178...): local should really be
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ pure fn stmt_id(s: stmt) -> node_id {
match s.node {
stmt_decl(_, id) => id,
stmt_expr(_, id) => id,
stmt_semi(_, id) => id
stmt_semi(_, id) => id,
stmt_mac(*) => fail ~"attempted to analyze unexpanded stmt",
}
}

Expand Down
30 changes: 17 additions & 13 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ast_util::dummy_sp;
// new-style macro! tt code:
//
// syntax_expander_tt, syntax_expander_tt_item, mac_result,
// expr_tt, item_tt
// normal_tt, item_tt
//
// also note that ast::mac has way too many cases and can probably
// be trimmed down substantially.
Expand Down Expand Up @@ -44,6 +44,7 @@ type syntax_expander_tt_item_
enum mac_result {
mr_expr(@ast::expr),
mr_item(@ast::item),
mr_any(fn@()-> @ast::expr, fn@()-> Option<@ast::item>, fn@()->@ast::stmt),
mr_def(macro_def)
}

Expand All @@ -59,7 +60,10 @@ enum syntax_extension {
item_decorator(item_decorator),

// Token-tree expanders
expr_tt(syntax_expander_tt),
normal_tt(syntax_expander_tt),

// perhaps macro_rules! will lose its odd special identifier argument,
// and this can go away also
item_tt(syntax_expander_tt_item),
}

Expand All @@ -68,8 +72,8 @@ enum syntax_extension {
fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
fn builtin(f: syntax_expander_) -> syntax_extension
{normal({expander: f, span: None})}
fn builtin_expr_tt(f: syntax_expander_tt_) -> syntax_extension {
expr_tt({expander: f, span: None})
fn builtin_normal_tt(f: syntax_expander_tt_) -> syntax_extension {
normal_tt({expander: f, span: None})
}
fn builtin_item_tt(f: syntax_expander_tt_item_) -> syntax_extension {
item_tt({expander: f, span: None})
Expand All @@ -93,7 +97,7 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
syntax_expanders.insert(~"ident_to_str",
builtin(ext::ident_to_str::expand_syntax_ext));
syntax_expanders.insert(~"log_syntax",
builtin_expr_tt(
builtin_normal_tt(
ext::log_syntax::expand_syntax_ext));
syntax_expanders.insert(~"ast",
builtin(ext::qquote::expand_ast));
Expand All @@ -105,18 +109,18 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
ext::deriving::expand_deriving_iter_bytes));

// Quasi-quoting expanders
syntax_expanders.insert(~"quote_tokens",
builtin_expr_tt(ext::quote::expand_quote_tokens));
syntax_expanders.insert(
~"quote_tokens", builtin_normal_tt(ext::quote::expand_quote_tokens));
syntax_expanders.insert(~"quote_expr",
builtin_expr_tt(ext::quote::expand_quote_expr));
builtin_normal_tt(ext::quote::expand_quote_expr));
syntax_expanders.insert(~"quote_type",
builtin_expr_tt(ext::quote::expand_quote_type));
builtin_normal_tt(ext::quote::expand_quote_type));
syntax_expanders.insert(~"quote_item",
builtin_expr_tt(ext::quote::expand_quote_item));
builtin_normal_tt(ext::quote::expand_quote_item));
syntax_expanders.insert(~"quote_pat",
builtin_expr_tt(ext::quote::expand_quote_pat));
builtin_normal_tt(ext::quote::expand_quote_pat));
syntax_expanders.insert(~"quote_stmt",
builtin_expr_tt(ext::quote::expand_quote_stmt));
builtin_normal_tt(ext::quote::expand_quote_stmt));

syntax_expanders.insert(~"line",
builtin(ext::source_util::expand_line));
Expand All @@ -138,7 +142,7 @@ fn syntax_expander_table() -> HashMap<~str, syntax_extension> {
builtin_item_tt(ext::pipes::expand_proto));
syntax_expanders.insert(
~"trace_macros",
builtin_expr_tt(ext::trace_macros::expand_trace_macros));
builtin_normal_tt(ext::trace_macros::expand_trace_macros));
return syntax_expanders;
}

Expand Down
Loading