diff options
| author | bors <bors@rust-lang.org> | 2013-08-24 19:21:17 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2013-08-24 19:21:17 -0700 |
| commit | a17c7e4f2c0cfd800ce873b83334e8b17bef2f70 (patch) | |
| tree | dcc5745a47c06dcbed739a2f80ee02cd91cfebea /src/libsyntax | |
| parent | f7f1d896497b10cb56389730e784aff6e513b0e8 (diff) | |
| parent | a3e39b945402475dbe0eae91833981dad4622cb7 (diff) | |
| download | rust-a17c7e4f2c0cfd800ce873b83334e8b17bef2f70.tar.gz rust-a17c7e4f2c0cfd800ce873b83334e8b17bef2f70.zip | |
auto merge of #8637 : alexcrichton/rust/ifmt-less-hax, r=graydon
Recent improvements to `&mut Trait` have made this work possible, and it solidifies that `ifmt` doesn't always have to return a string, but rather it's based around writers.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 62 | ||||
| -rw-r--r-- | src/libsyntax/ext/ifmt.rs | 74 |
3 files changed, 102 insertions, 42 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index dfaffa0c275..6f9585652bd 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -139,8 +139,12 @@ pub fn syntax_expander_table() -> SyntaxEnv { ext::tt::macro_rules::add_new_extension)); syntax_expanders.insert(intern(&"fmt"), builtin_normal_tt(ext::fmt::expand_syntax_ext)); - syntax_expanders.insert(intern(&"ifmt"), - builtin_normal_tt(ext::ifmt::expand_syntax_ext)); + syntax_expanders.insert(intern(&"format"), + builtin_normal_tt(ext::ifmt::expand_format)); + syntax_expanders.insert(intern(&"write"), + builtin_normal_tt(ext::ifmt::expand_write)); + syntax_expanders.insert(intern(&"writeln"), + builtin_normal_tt(ext::ifmt::expand_writeln)); syntax_expanders.insert( intern(&"auto_encode"), @SE(ItemDecorator(ext::auto_encode::expand_auto_encode))); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4bea1dc23e7..7b493e11ef7 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -758,32 +758,32 @@ pub fn std_macros() -> @str { ) ) - // conditionally define debug!, but keep it type checking even - // in non-debug builds. - macro_rules! __debug ( + macro_rules! debug ( ($arg:expr) => ( - __log(4u32, fmt!( \"%?\", $arg )) + if cfg!(debug) { __log(4u32, fmt!( \"%?\", $arg )) } ); ($( $arg:expr ),+) => ( - __log(4u32, fmt!( $($arg),+ )) + if cfg!(debug) { __log(4u32, fmt!( $($arg),+ )) } ) ) - #[cfg(debug)] - #[macro_escape] - mod debug_macro { - macro_rules! debug (($($arg:expr),*) => { - __debug!($($arg),*) - }) - } + macro_rules! error2 ( + ($($arg:tt)*) => ( __log(1u32, format!($($arg)*))) + ) - #[cfg(not(debug))] - #[macro_escape] - mod debug_macro { - macro_rules! debug (($($arg:expr),*) => { - if false { __debug!($($arg),*) } - }) - } + macro_rules! warn2 ( + ($($arg:tt)*) => ( __log(2u32, format!($($arg)*))) + ) + + macro_rules! info2 ( + ($($arg:tt)*) => ( __log(3u32, format!($($arg)*))) + ) + + macro_rules! debug2 ( + ($($arg:tt)*) => ( + if cfg!(debug) { __log(4u32, format!($($arg)*)) } + ) + ) macro_rules! fail( () => ( @@ -797,6 +797,15 @@ pub fn std_macros() -> @str { ) ) + macro_rules! fail2( + () => ( + fail!(\"explicit failure\") + ); + ($($arg:tt)+) => ( + ::std::sys::FailWithCause::fail_with(format!($($arg)+), file!(), line!()) + ) + ) + macro_rules! assert( ($cond:expr) => { if !$cond { @@ -940,6 +949,7 @@ pub fn std_macros() -> @str { ); ) + // NOTE(acrichto): start removing this after the next snapshot macro_rules! printf ( ($arg:expr) => ( print(fmt!(\"%?\", $arg)) @@ -949,6 +959,7 @@ pub fn std_macros() -> @str { ) ) + // NOTE(acrichto): start removing this after the next snapshot macro_rules! printfln ( ($arg:expr) => ( println(fmt!(\"%?\", $arg)) @@ -958,6 +969,19 @@ pub fn std_macros() -> @str { ) ) + // FIXME(#6846) once stdio is redesigned, this shouldn't perform an + // allocation but should rather delegate to an invocation of + // write! instead of format! + macro_rules! print ( + ($($arg:tt)+) => ( ::std::io::print(format!($($arg)+))) + ) + + // FIXME(#6846) once stdio is redesigned, this shouldn't perform an + // allocation but should rather delegate to an io::Writer + macro_rules! println ( + ($($arg:tt)+) => ({ print!($($arg)+); ::std::io::println(\"\"); }) + ) + // NOTE: use this after a snapshot lands to abstract the details // of the TLS interface. macro_rules! local_data_key ( diff --git a/src/libsyntax/ext/ifmt.rs b/src/libsyntax/ext/ifmt.rs index 35be77b95c5..d4274746a4e 100644 --- a/src/libsyntax/ext/ifmt.rs +++ b/src/libsyntax/ext/ifmt.rs @@ -54,20 +54,32 @@ impl Context { /// Parses the arguments from the given list of tokens, returning None if /// there's a parse error so we can continue parsing other fmt! expressions. fn parse_args(&mut self, sp: span, - tts: &[ast::token_tree]) -> Option<@ast::expr> { + leading_expr: bool, + tts: &[ast::token_tree]) -> (Option<@ast::expr>, + Option<@ast::expr>) { let p = rsparse::new_parser_from_tts(self.ecx.parse_sess(), self.ecx.cfg(), tts.to_owned()); + // If we want a leading expression (for ifmtf), parse it here + let extra = if leading_expr { + let e = Some(p.parse_expr()); + if !p.eat(&token::COMMA) { + self.ecx.span_err(sp, "expected token: `,`"); + return (e, None); + } + e + } else { None }; + if *p.token == token::EOF { - self.ecx.span_err(sp, "ifmt! expects at least one argument"); - return None; + self.ecx.span_err(sp, "requires at least a format string argument"); + return (extra, None); } let fmtstr = p.parse_expr(); let mut named = false; while *p.token != token::EOF { if !p.eat(&token::COMMA) { self.ecx.span_err(sp, "expected token: `,`"); - return None; + return (extra, None); } if named || (token::is_ident(p.token) && p.look_ahead(1, |t| *t == token::EQ)) { @@ -81,14 +93,14 @@ impl Context { self.ecx.span_err(*p.span, "expected ident, positional arguments \ cannot follow named arguments"); - return None; + return (extra, None); } _ => { self.ecx.span_err(*p.span, fmt!("expected ident for named \ argument, but found `%s`", p.this_token_to_str())); - return None; + return (extra, None); } }; let name = self.ecx.str_of(ident); @@ -110,7 +122,7 @@ impl Context { self.arg_types.push(None); } } - return Some(fmtstr); + return (extra, Some(fmtstr)); } /// Verifies one piece of a parse string. All errors are not emitted as @@ -530,7 +542,7 @@ impl Context { /// Actually builds the expression which the ifmt! block will be expanded /// to - fn to_expr(&self) -> @ast::expr { + fn to_expr(&self, extra: Option<@ast::expr>, f: &str) -> @ast::expr { let mut lets = ~[]; let mut locals = ~[]; let mut names = vec::from_fn(self.name_positions.len(), |_| None); @@ -596,15 +608,18 @@ impl Context { let args = names.move_iter().map(|a| a.unwrap()); let mut args = locals.move_iter().chain(args); - // Next, build up the actual call to the sprintf function. + let mut fmt_args = match extra { + Some(e) => ~[e], None => ~[] + }; + fmt_args.push(self.ecx.expr_ident(self.fmtsp, static_name)); + fmt_args.push(self.ecx.expr_vec(self.fmtsp, args.collect())); + + // Next, build up the actual call to the {s,f}printf function. let result = self.ecx.expr_call_global(self.fmtsp, ~[ self.ecx.ident_of("std"), self.ecx.ident_of("fmt"), - self.ecx.ident_of("sprintf"), - ], ~[ - self.ecx.expr_ident(self.fmtsp, static_name), - self.ecx.expr_vec(self.fmtsp, args.collect()), - ]); + self.ecx.ident_of(f), + ], fmt_args); // sprintf is unsafe, but we just went through a lot of work to // validate that our call is save, so inject the unsafe block for the @@ -682,8 +697,24 @@ impl Context { } } -pub fn expand_syntax_ext(ecx: @ExtCtxt, sp: span, - tts: &[ast::token_tree]) -> base::MacResult { +pub fn expand_format(ecx: @ExtCtxt, sp: span, + tts: &[ast::token_tree]) -> base::MacResult { + expand_ifmt(ecx, sp, tts, false, false, "format") +} + +pub fn expand_write(ecx: @ExtCtxt, sp: span, + tts: &[ast::token_tree]) -> base::MacResult { + expand_ifmt(ecx, sp, tts, true, false, "write") +} + +pub fn expand_writeln(ecx: @ExtCtxt, sp: span, + tts: &[ast::token_tree]) -> base::MacResult { + expand_ifmt(ecx, sp, tts, true, true, "write") +} + +fn expand_ifmt(ecx: @ExtCtxt, sp: span, tts: &[ast::token_tree], + leading_arg: bool, append_newline: bool, + function: &str) -> base::MacResult { let mut cx = Context { ecx: ecx, args: ~[], @@ -697,13 +728,14 @@ pub fn expand_syntax_ext(ecx: @ExtCtxt, sp: span, method_statics: ~[], fmtsp: sp, }; - let efmt = match cx.parse_args(sp, tts) { - Some(e) => e, - None => { return MRExpr(ecx.expr_uint(sp, 2)); } + let (extra, efmt) = match cx.parse_args(sp, leading_arg, tts) { + (extra, Some(e)) => (extra, e), + (_, None) => { return MRExpr(ecx.expr_uint(sp, 2)); } }; cx.fmtsp = efmt.span; let fmt = expr_to_str(ecx, efmt, - "first argument to ifmt! must be a string literal."); + "format argument must be a string literal."); + let fmt = if append_newline { fmt + "\n" } else { fmt.to_owned() }; let mut err = false; do parse::parse_error::cond.trap(|m| { @@ -734,5 +766,5 @@ pub fn expand_syntax_ext(ecx: @ExtCtxt, sp: span, } } - MRExpr(cx.to_expr()) + MRExpr(cx.to_expr(extra, function)) } |
