diff options
Diffstat (limited to 'src/libsyntax/ext/fmt.rs')
| -rw-r--r-- | src/libsyntax/ext/fmt.rs | 317 |
1 files changed, 8 insertions, 309 deletions
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 8258048a04d..5e3e4e15d8e 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -8,320 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/* - * The compiler code necessary to support the fmt! extension. Eventually this - * should all get sucked into either the standard library extfmt module or the - * compiler syntax extension plugin interface. - */ +/// Deprecated fmt! syntax extension use ast; use codemap::Span; -use ext::base::*; use ext::base; use ext::build::AstBuilder; -use std::option; -use std::unstable::extfmt::ct::*; -use parse::token::{str_to_ident}; +pub fn expand_syntax_ext(ecx: @base::ExtCtxt, sp: Span, + _tts: &[ast::token_tree]) -> base::MacResult { + ecx.span_err(sp, "`fmt!` is deprecated, use `format!` instead"); + ecx.parse_sess.span_diagnostic.span_note(sp, + "see http://static.rust-lang.org/doc/master/std/fmt/index.html \ + for documentation"); -pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree]) - -> base::MacResult { - let args = get_exprs_from_tts(cx, sp, tts); - if args.len() == 0 { - cx.span_fatal(sp, "fmt! takes at least 1 argument."); - } - let (fmt, _fmt_str_style) = - expr_to_str(cx, args[0], - "first argument to fmt! must be a string literal."); - let fmtspan = args[0].span; - debug2!("Format string: {}", fmt); - fn parse_fmt_err_(cx: @ExtCtxt, sp: Span, msg: &str) -> ! { - cx.span_fatal(sp, msg); - } - let parse_fmt_err: &fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s); - let pieces = parse_fmt_string(fmt, parse_fmt_err); - MRExpr(pieces_to_expr(cx, sp, pieces, args)) -} - -// FIXME (#2249): A lot of these functions for producing expressions can -// probably be factored out in common with other code that builds -// expressions. Also: Cleanup the naming of these functions. -// Note: Moved many of the common ones to build.rs --kevina -fn pieces_to_expr(cx: @ExtCtxt, sp: Span, - pieces: ~[Piece], args: ~[@ast::Expr]) - -> @ast::Expr { - fn make_path_vec(ident: &str) -> ~[ast::Ident] { - return ~[str_to_ident("std"), - str_to_ident("unstable"), - str_to_ident("extfmt"), - str_to_ident("rt"), - str_to_ident(ident)]; - } - fn make_rt_path_expr(cx: @ExtCtxt, sp: Span, nm: &str) -> @ast::Expr { - let path = make_path_vec(nm); - cx.expr_path(cx.path_global(sp, path)) - } - // Produces an AST expression that represents a RT::conv record, - // which tells the RT::conv* functions how to perform the conversion - - fn make_rt_conv_expr(cx: @ExtCtxt, sp: Span, cnv: &Conv) -> @ast::Expr { - fn make_flags(cx: @ExtCtxt, sp: Span, flags: &[Flag]) -> @ast::Expr { - let mut tmp_expr = make_rt_path_expr(cx, sp, "flag_none"); - for f in flags.iter() { - let fstr = match *f { - FlagLeftJustify => "flag_left_justify", - FlagLeftZeroPad => "flag_left_zero_pad", - FlagSpaceForSign => "flag_space_for_sign", - FlagSignAlways => "flag_sign_always", - FlagAlternate => "flag_alternate" - }; - tmp_expr = cx.expr_binary(sp, ast::BiBitOr, tmp_expr, - make_rt_path_expr(cx, sp, fstr)); - } - return tmp_expr; - } - fn make_count(cx: @ExtCtxt, sp: Span, cnt: Count) -> @ast::Expr { - match cnt { - CountImplied => { - return make_rt_path_expr(cx, sp, "CountImplied"); - } - CountIs(c) => { - let count_lit = cx.expr_uint(sp, c as uint); - let count_is_path = make_path_vec("CountIs"); - let count_is_args = ~[count_lit]; - return cx.expr_call_global(sp, count_is_path, count_is_args); - } - _ => cx.span_unimpl(sp, "unimplemented fmt! conversion") - } - } - fn make_ty(cx: @ExtCtxt, sp: Span, t: Ty) -> @ast::Expr { - let rt_type = match t { - TyHex(c) => match c { - CaseUpper => "TyHexUpper", - CaseLower => "TyHexLower" - }, - TyBits => "TyBits", - TyOctal => "TyOctal", - _ => "TyDefault" - }; - return make_rt_path_expr(cx, sp, rt_type); - } - fn make_conv_struct(cx: @ExtCtxt, sp: Span, flags_expr: @ast::Expr, - width_expr: @ast::Expr, precision_expr: @ast::Expr, - ty_expr: @ast::Expr) -> @ast::Expr { - cx.expr_struct( - sp, - cx.path_global(sp, make_path_vec("Conv")), - ~[ - cx.field_imm(sp, str_to_ident("flags"), flags_expr), - cx.field_imm(sp, str_to_ident("width"), width_expr), - cx.field_imm(sp, str_to_ident("precision"), precision_expr), - cx.field_imm(sp, str_to_ident("ty"), ty_expr) - ] - ) - } - let rt_conv_flags = make_flags(cx, sp, cnv.flags); - let rt_conv_width = make_count(cx, sp, cnv.width); - let rt_conv_precision = make_count(cx, sp, cnv.precision); - let rt_conv_ty = make_ty(cx, sp, cnv.ty); - make_conv_struct(cx, sp, rt_conv_flags, rt_conv_width, - rt_conv_precision, rt_conv_ty) - } - fn make_conv_call(cx: @ExtCtxt, sp: Span, conv_type: &str, cnv: &Conv, - arg: @ast::Expr, buf: @ast::Expr) -> @ast::Expr { - let fname = ~"conv_" + conv_type; - let path = make_path_vec(fname); - let cnv_expr = make_rt_conv_expr(cx, sp, cnv); - let args = ~[cnv_expr, arg, buf]; - cx.expr_call_global(arg.span, path, args) - } - - fn make_new_conv(cx: @ExtCtxt, sp: Span, cnv: &Conv, - arg: @ast::Expr, buf: @ast::Expr) -> @ast::Expr { - fn is_signed_type(cnv: &Conv) -> bool { - match cnv.ty { - TyInt(s) => match s { - Signed => return true, - Unsigned => return false - }, - TyFloat => return true, - _ => return false - } - } - let unsupported = ~"conversion not supported in fmt! string"; - match cnv.param { - option::None => (), - _ => cx.span_unimpl(sp, unsupported) - } - for f in cnv.flags.iter() { - match *f { - FlagLeftJustify => (), - FlagSignAlways => { - if !is_signed_type(cnv) { - cx.span_fatal(sp, - "+ flag only valid in \ - signed fmt! conversion"); - } - } - FlagSpaceForSign => { - if !is_signed_type(cnv) { - cx.span_fatal(sp, - "space flag only valid in \ - signed fmt! conversions"); - } - } - FlagLeftZeroPad => (), - _ => cx.span_unimpl(sp, unsupported) - } - } - match cnv.width { - CountImplied => (), - CountIs(_) => (), - _ => cx.span_unimpl(sp, unsupported) - } - match cnv.precision { - CountImplied => (), - CountIs(_) => (), - _ => cx.span_unimpl(sp, unsupported) - } - let (name, actual_arg) = match cnv.ty { - TyStr => ("str", arg), - TyInt(Signed) => ("int", arg), - TyBool => ("bool", arg), - TyChar => ("char", arg), - TyBits | TyOctal | TyHex(_) | TyInt(Unsigned) => ("uint", arg), - TyFloat => ("float", arg), - TyPointer => ("pointer", arg), - TyPoly => ("poly", cx.expr_addr_of(sp, arg)) - }; - return make_conv_call(cx, arg.span, name, cnv, actual_arg, - cx.expr_mut_addr_of(arg.span, buf)); - } - fn log_conv(c: &Conv) { - debug2!("Building conversion:"); - match c.param { - Some(p) => { debug2!("param: {}", p.to_str()); } - _ => debug2!("param: none") - } - for f in c.flags.iter() { - match *f { - FlagLeftJustify => debug2!("flag: left justify"), - FlagLeftZeroPad => debug2!("flag: left zero pad"), - FlagSpaceForSign => debug2!("flag: left space pad"), - FlagSignAlways => debug2!("flag: sign always"), - FlagAlternate => debug2!("flag: alternate") - } - } - match c.width { - CountIs(i) => - debug2!("width: count is {}", i.to_str()), - CountIsParam(i) => - debug2!("width: count is param {}", i.to_str()), - CountIsNextParam => debug2!("width: count is next param"), - CountImplied => debug2!("width: count is implied") - } - match c.precision { - CountIs(i) => - debug2!("prec: count is {}", i.to_str()), - CountIsParam(i) => - debug2!("prec: count is param {}", i.to_str()), - CountIsNextParam => debug2!("prec: count is next param"), - CountImplied => debug2!("prec: count is implied") - } - match c.ty { - TyBool => debug2!("type: bool"), - TyStr => debug2!("type: str"), - TyChar => debug2!("type: char"), - TyInt(s) => match s { - Signed => debug2!("type: signed"), - Unsigned => debug2!("type: unsigned") - }, - TyBits => debug2!("type: bits"), - TyHex(cs) => match cs { - CaseUpper => debug2!("type: uhex"), - CaseLower => debug2!("type: lhex"), - }, - TyOctal => debug2!("type: octal"), - TyFloat => debug2!("type: float"), - TyPointer => debug2!("type: pointer"), - TyPoly => debug2!("type: poly") - } - } - - /* Short circuit an easy case up front (won't work otherwise) */ - if pieces.len() == 0 { - return cx.expr_str_uniq(args[0].span, @""); - } - - let fmt_sp = args[0].span; - let mut n = 0u; - let nargs = args.len(); - - /* 'ident' is the local buffer building up the result of fmt! */ - let ident = str_to_ident("__fmtbuf"); - let buf = || cx.expr_ident(fmt_sp, ident); - let core_ident = str_to_ident("std"); - let str_ident = str_to_ident("str"); - let push_ident = str_to_ident("push_str"); - let mut stms = ~[]; - - /* Translate each piece (portion of the fmt expression) by invoking the - corresponding function in std::unstable::extfmt. Each function takes a - buffer to insert data into along with the data being formatted. */ - let npieces = pieces.len(); - for (i, pc) in pieces.move_iter().enumerate() { - match pc { - /* Raw strings get appended via str::push_str */ - PieceString(s) => { - /* If this is the first portion, then initialize the local - buffer with it directly. If it's actually the only piece, - then there's no need for it to be mutable */ - if i == 0 { - stms.push(cx.stmt_let(fmt_sp, npieces > 1, - ident, cx.expr_str_uniq(fmt_sp, s.to_managed()))); - } else { - // we call the push_str function because the - // bootstrap doesnt't seem to work if we call the - // method. - let args = ~[cx.expr_mut_addr_of(fmt_sp, buf()), - cx.expr_str(fmt_sp, s.to_managed())]; - let call = cx.expr_call_global(fmt_sp, - ~[core_ident, - str_ident, - push_ident], - args); - stms.push(cx.stmt_expr(call)); - } - } - - /* Invoke the correct conv function in extfmt */ - PieceConv(ref conv) => { - n += 1u; - if n >= nargs { - cx.span_fatal(sp, - "not enough arguments to fmt! \ - for the given format string"); - } - - log_conv(conv); - /* If the first portion is a conversion, then the local buffer - must be initialized as an empty string */ - if i == 0 { - stms.push(cx.stmt_let(fmt_sp, true, ident, - cx.expr_str_uniq(fmt_sp, @""))); - } - stms.push(cx.stmt_expr(make_new_conv(cx, fmt_sp, conv, - args[n], buf()))); - } - } - } - - let expected_nargs = n + 1u; // n conversions + the fmt string - if expected_nargs < nargs { - cx.span_fatal - (sp, format!("too many arguments to fmt!. found {}, expected {}", - nargs, expected_nargs)); - } - - cx.expr_block(cx.block(fmt_sp, stms, Some(buf()))) + base::MRExpr(ecx.expr_uint(sp, 2)) } |
