mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
syntax/ext/format -- rewrite conflicting closures into methods
This commit is contained in:
parent
b2b4c79b17
commit
ca65c00ef2
@ -21,6 +21,7 @@ use rsparse = parse;
|
|||||||
use std::fmt::parse;
|
use std::fmt::parse;
|
||||||
use std::hashmap::{HashMap, HashSet};
|
use std::hashmap::{HashMap, HashSet};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
enum ArgumentType {
|
enum ArgumentType {
|
||||||
@ -367,157 +368,167 @@ impl<'a> Context<'a> {
|
|||||||
return ~[unnamed, allow_dead_code];
|
return ~[unnamed, allow_dead_code];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translate a `parse::Piece` to a static `rt::Piece`
|
fn parsepath(&self, s: &str) -> ~[ast::Ident] {
|
||||||
fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr {
|
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
||||||
let sp = self.fmtsp;
|
self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
|
||||||
let parsepath = |s: &str| {
|
}
|
||||||
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
|
||||||
self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
|
fn rtpath(&self, s: &str) -> ~[ast::Ident] {
|
||||||
};
|
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
||||||
let rtpath = |s: &str| {
|
self.ecx.ident_of("rt"), self.ecx.ident_of(s)]
|
||||||
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
}
|
||||||
self.ecx.ident_of("rt"), self.ecx.ident_of(s)]
|
|
||||||
};
|
fn ctpath(&self, s: &str) -> ~[ast::Ident] {
|
||||||
let ctpath = |s: &str| {
|
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
||||||
~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
|
self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
|
||||||
self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
|
}
|
||||||
};
|
|
||||||
let none = self.ecx.path_global(sp, ~[
|
fn none(&self) -> @ast::Expr {
|
||||||
|
let none = self.ecx.path_global(self.fmtsp, ~[
|
||||||
self.ecx.ident_of("std"),
|
self.ecx.ident_of("std"),
|
||||||
self.ecx.ident_of("option"),
|
self.ecx.ident_of("option"),
|
||||||
self.ecx.ident_of("None")]);
|
self.ecx.ident_of("None")]);
|
||||||
let none = self.ecx.expr_path(none);
|
self.ecx.expr_path(none)
|
||||||
let some = |e: @ast::Expr| {
|
}
|
||||||
let p = self.ecx.path_global(sp, ~[
|
|
||||||
|
fn some(&self, e: @ast::Expr) -> @ast::Expr {
|
||||||
|
let p = self.ecx.path_global(self.fmtsp, ~[
|
||||||
self.ecx.ident_of("std"),
|
self.ecx.ident_of("std"),
|
||||||
self.ecx.ident_of("option"),
|
self.ecx.ident_of("option"),
|
||||||
self.ecx.ident_of("Some")]);
|
self.ecx.ident_of("Some")]);
|
||||||
let p = self.ecx.expr_path(p);
|
let p = self.ecx.expr_path(p);
|
||||||
self.ecx.expr_call(sp, p, ~[e])
|
self.ecx.expr_call(self.fmtsp, p, ~[e])
|
||||||
};
|
}
|
||||||
let trans_count = |c: parse::Count| {
|
|
||||||
match c {
|
fn trans_count(&self, c: parse::Count) -> @ast::Expr {
|
||||||
parse::CountIs(i) => {
|
let sp = self.fmtsp;
|
||||||
self.ecx.expr_call_global(sp, rtpath("CountIs"),
|
match c {
|
||||||
~[self.ecx.expr_uint(sp, i)])
|
parse::CountIs(i) => {
|
||||||
}
|
self.ecx.expr_call_global(sp, self.rtpath("CountIs"),
|
||||||
parse::CountIsParam(i) => {
|
~[self.ecx.expr_uint(sp, i)])
|
||||||
self.ecx.expr_call_global(sp, rtpath("CountIsParam"),
|
|
||||||
~[self.ecx.expr_uint(sp, i)])
|
|
||||||
}
|
|
||||||
parse::CountImplied => {
|
|
||||||
let path = self.ecx.path_global(sp, rtpath("CountImplied"));
|
|
||||||
self.ecx.expr_path(path)
|
|
||||||
}
|
|
||||||
parse::CountIsNextParam => {
|
|
||||||
let path = self.ecx.path_global(sp, rtpath("CountIsNextParam"));
|
|
||||||
self.ecx.expr_path(path)
|
|
||||||
}
|
|
||||||
parse::CountIsName(n) => {
|
|
||||||
let i = match self.name_positions.find_equiv(&n) {
|
|
||||||
Some(&i) => i,
|
|
||||||
None => 0, // error already emitted elsewhere
|
|
||||||
};
|
|
||||||
let i = i + self.args.len();
|
|
||||||
self.ecx.expr_call_global(sp, rtpath("CountIsParam"),
|
|
||||||
~[self.ecx.expr_uint(sp, i)])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
parse::CountIsParam(i) => {
|
||||||
let trans_method = |method: &parse::Method| {
|
self.ecx.expr_call_global(sp, self.rtpath("CountIsParam"),
|
||||||
let method = match *method {
|
~[self.ecx.expr_uint(sp, i)])
|
||||||
parse::Select(ref arms, ref default) => {
|
}
|
||||||
let arms = arms.iter().map(|arm| {
|
parse::CountImplied => {
|
||||||
let p = self.ecx.path_global(sp, rtpath("SelectArm"));
|
let path = self.ecx.path_global(sp, self.rtpath("CountImplied"));
|
||||||
|
self.ecx.expr_path(path)
|
||||||
|
}
|
||||||
|
parse::CountIsNextParam => {
|
||||||
|
let path = self.ecx.path_global(sp, self.rtpath("CountIsNextParam"));
|
||||||
|
self.ecx.expr_path(path)
|
||||||
|
}
|
||||||
|
parse::CountIsName(n) => {
|
||||||
|
let i = match self.name_positions.find_equiv(&n) {
|
||||||
|
Some(&i) => i,
|
||||||
|
None => 0, // error already emitted elsewhere
|
||||||
|
};
|
||||||
|
let i = i + self.args.len();
|
||||||
|
self.ecx.expr_call_global(sp, self.rtpath("CountIsParam"),
|
||||||
|
~[self.ecx.expr_uint(sp, i)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trans_method(&mut self, method: &parse::Method) -> @ast::Expr {
|
||||||
|
let sp = self.fmtsp;
|
||||||
|
let method = match *method {
|
||||||
|
parse::Select(ref arms, ref default) => {
|
||||||
|
let arms = arms.iter().map(|arm| {
|
||||||
|
let p = self.ecx.path_global(sp, self.rtpath("SelectArm"));
|
||||||
let result = arm.result.iter().map(|p| {
|
let result = arm.result.iter().map(|p| {
|
||||||
self.trans_piece(p)
|
self.trans_piece(p)
|
||||||
}).collect();
|
}).collect();
|
||||||
let s = token::intern_and_get_ident(arm.selector);
|
let s = token::intern_and_get_ident(arm.selector);
|
||||||
let selector = self.ecx.expr_str(sp, s);
|
let selector = self.ecx.expr_str(sp, s);
|
||||||
self.ecx.expr_struct(sp, p, ~[
|
self.ecx.expr_struct(sp, p, ~[
|
||||||
self.ecx.field_imm(sp,
|
self.ecx.field_imm(sp,
|
||||||
self.ecx.ident_of("selector"),
|
self.ecx.ident_of("selector"),
|
||||||
selector),
|
selector),
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
|
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
|
||||||
self.ecx.expr_vec_slice(sp, result)),
|
self.ecx.expr_vec_slice(sp, result)),
|
||||||
])
|
])
|
||||||
}).collect();
|
}).collect();
|
||||||
let default = default.iter().map(|p| {
|
let default = default.iter().map(|p| {
|
||||||
self.trans_piece(p)
|
self.trans_piece(p)
|
||||||
}).collect();
|
}).collect();
|
||||||
self.ecx.expr_call_global(sp, rtpath("Select"), ~[
|
self.ecx.expr_call_global(sp, self.rtpath("Select"), ~[
|
||||||
self.ecx.expr_vec_slice(sp, arms),
|
self.ecx.expr_vec_slice(sp, arms),
|
||||||
self.ecx.expr_vec_slice(sp, default),
|
self.ecx.expr_vec_slice(sp, default),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
parse::Plural(offset, ref arms, ref default) => {
|
parse::Plural(offset, ref arms, ref default) => {
|
||||||
let offset = match offset {
|
let offset = match offset {
|
||||||
Some(i) => { some(self.ecx.expr_uint(sp, i)) }
|
Some(i) => { self.some(self.ecx.expr_uint(sp, i)) }
|
||||||
None => { none.clone() }
|
None => { self.none() }
|
||||||
};
|
};
|
||||||
let arms = arms.iter().map(|arm| {
|
let arms = arms.iter().map(|arm| {
|
||||||
let p = self.ecx.path_global(sp, rtpath("PluralArm"));
|
let p = self.ecx.path_global(sp, self.rtpath("PluralArm"));
|
||||||
let result = arm.result.iter().map(|p| {
|
let result = arm.result.iter().map(|p| {
|
||||||
self.trans_piece(p)
|
self.trans_piece(p)
|
||||||
}).collect();
|
}).collect();
|
||||||
let (lr, selarg) = match arm.selector {
|
let (lr, selarg) = match arm.selector {
|
||||||
parse::Keyword(t) => {
|
parse::Keyword(t) => {
|
||||||
let p = ctpath(format!("{:?}", t));
|
let p = self.ctpath(format!("{:?}", t));
|
||||||
let p = self.ecx.path_global(sp, p);
|
let p = self.ecx.path_global(sp, p);
|
||||||
(rtpath("Keyword"), self.ecx.expr_path(p))
|
(self.rtpath("Keyword"), self.ecx.expr_path(p))
|
||||||
}
|
}
|
||||||
parse::Literal(i) => {
|
parse::Literal(i) => {
|
||||||
(rtpath("Literal"), self.ecx.expr_uint(sp, i))
|
(self.rtpath("Literal"), self.ecx.expr_uint(sp, i))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let selector = self.ecx.expr_call_global(sp,
|
let selector = self.ecx.expr_call_global(sp,
|
||||||
lr, ~[selarg]);
|
lr, ~[selarg]);
|
||||||
self.ecx.expr_struct(sp, p, ~[
|
self.ecx.expr_struct(sp, p, ~[
|
||||||
self.ecx.field_imm(sp,
|
self.ecx.field_imm(sp,
|
||||||
self.ecx.ident_of("selector"),
|
self.ecx.ident_of("selector"),
|
||||||
selector),
|
selector),
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
|
self.ecx.field_imm(sp, self.ecx.ident_of("result"),
|
||||||
self.ecx.expr_vec_slice(sp, result)),
|
self.ecx.expr_vec_slice(sp, result)),
|
||||||
])
|
])
|
||||||
}).collect();
|
}).collect();
|
||||||
let default = default.iter().map(|p| {
|
let default = default.iter().map(|p| {
|
||||||
self.trans_piece(p)
|
self.trans_piece(p)
|
||||||
}).collect();
|
}).collect();
|
||||||
self.ecx.expr_call_global(sp, rtpath("Plural"), ~[
|
self.ecx.expr_call_global(sp, self.rtpath("Plural"), ~[
|
||||||
offset,
|
offset,
|
||||||
self.ecx.expr_vec_slice(sp, arms),
|
self.ecx.expr_vec_slice(sp, arms),
|
||||||
self.ecx.expr_vec_slice(sp, default),
|
self.ecx.expr_vec_slice(sp, default),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let life = self.ecx.lifetime(sp, self.ecx.ident_of("static"));
|
let life = self.ecx.lifetime(sp, self.ecx.ident_of("static"));
|
||||||
let ty = self.ecx.ty_path(self.ecx.path_all(
|
let ty = self.ecx.ty_path(self.ecx.path_all(
|
||||||
sp,
|
sp,
|
||||||
true,
|
true,
|
||||||
rtpath("Method"),
|
self.rtpath("Method"),
|
||||||
opt_vec::with(life),
|
opt_vec::with(life),
|
||||||
~[]
|
~[]
|
||||||
), None);
|
), None);
|
||||||
let st = ast::ItemStatic(ty, ast::MutImmutable, method);
|
let st = ast::ItemStatic(ty, ast::MutImmutable, method);
|
||||||
let static_name = self.ecx.ident_of(format!("__STATIC_METHOD_{}",
|
let static_name = self.ecx.ident_of(format!("__STATIC_METHOD_{}",
|
||||||
self.method_statics.len()));
|
self.method_statics.len()));
|
||||||
let item = self.ecx.item(sp, static_name, self.static_attrs(), st);
|
let item = self.ecx.item(sp, static_name, self.static_attrs(), st);
|
||||||
self.method_statics.push(item);
|
self.method_statics.push(item);
|
||||||
self.ecx.expr_ident(sp, static_name)
|
self.ecx.expr_ident(sp, static_name)
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/// Translate a `parse::Piece` to a static `rt::Piece`
|
||||||
|
fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr {
|
||||||
|
let sp = self.fmtsp;
|
||||||
match *piece {
|
match *piece {
|
||||||
parse::String(s) => {
|
parse::String(s) => {
|
||||||
let s = token::intern_and_get_ident(s);
|
let s = token::intern_and_get_ident(s);
|
||||||
self.ecx.expr_call_global(sp,
|
self.ecx.expr_call_global(sp,
|
||||||
rtpath("String"),
|
self.rtpath("String"),
|
||||||
~[
|
~[
|
||||||
self.ecx.expr_str(sp, s)
|
self.ecx.expr_str(sp, s)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
parse::CurrentArgument => {
|
parse::CurrentArgument => {
|
||||||
let nil = self.ecx.expr_lit(sp, ast::LitNil);
|
let nil = self.ecx.expr_lit(sp, ast::LitNil);
|
||||||
self.ecx.expr_call_global(sp, rtpath("CurrentArgument"), ~[nil])
|
self.ecx.expr_call_global(sp, self.rtpath("CurrentArgument"), ~[nil])
|
||||||
}
|
}
|
||||||
parse::Argument(ref arg) => {
|
parse::Argument(ref arg) => {
|
||||||
// Translate the position
|
// Translate the position
|
||||||
@ -525,11 +536,11 @@ impl<'a> Context<'a> {
|
|||||||
// These two have a direct mapping
|
// These two have a direct mapping
|
||||||
parse::ArgumentNext => {
|
parse::ArgumentNext => {
|
||||||
let path = self.ecx.path_global(sp,
|
let path = self.ecx.path_global(sp,
|
||||||
rtpath("ArgumentNext"));
|
self.rtpath("ArgumentNext"));
|
||||||
self.ecx.expr_path(path)
|
self.ecx.expr_path(path)
|
||||||
}
|
}
|
||||||
parse::ArgumentIs(i) => {
|
parse::ArgumentIs(i) => {
|
||||||
self.ecx.expr_call_global(sp, rtpath("ArgumentIs"),
|
self.ecx.expr_call_global(sp, self.rtpath("ArgumentIs"),
|
||||||
~[self.ecx.expr_uint(sp, i)])
|
~[self.ecx.expr_uint(sp, i)])
|
||||||
}
|
}
|
||||||
// Named arguments are converted to positional arguments at
|
// Named arguments are converted to positional arguments at
|
||||||
@ -540,7 +551,7 @@ impl<'a> Context<'a> {
|
|||||||
None => 0, // error already emitted elsewhere
|
None => 0, // error already emitted elsewhere
|
||||||
};
|
};
|
||||||
let i = i + self.args.len();
|
let i = i + self.args.len();
|
||||||
self.ecx.expr_call_global(sp, rtpath("ArgumentIs"),
|
self.ecx.expr_call_global(sp, self.rtpath("ArgumentIs"),
|
||||||
~[self.ecx.expr_uint(sp, i)])
|
~[self.ecx.expr_uint(sp, i)])
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -550,20 +561,20 @@ impl<'a> Context<'a> {
|
|||||||
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
|
let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
|
||||||
let align = match arg.format.align {
|
let align = match arg.format.align {
|
||||||
parse::AlignLeft => {
|
parse::AlignLeft => {
|
||||||
self.ecx.path_global(sp, parsepath("AlignLeft"))
|
self.ecx.path_global(sp, self.parsepath("AlignLeft"))
|
||||||
}
|
}
|
||||||
parse::AlignRight => {
|
parse::AlignRight => {
|
||||||
self.ecx.path_global(sp, parsepath("AlignRight"))
|
self.ecx.path_global(sp, self.parsepath("AlignRight"))
|
||||||
}
|
}
|
||||||
parse::AlignUnknown => {
|
parse::AlignUnknown => {
|
||||||
self.ecx.path_global(sp, parsepath("AlignUnknown"))
|
self.ecx.path_global(sp, self.parsepath("AlignUnknown"))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let align = self.ecx.expr_path(align);
|
let align = self.ecx.expr_path(align);
|
||||||
let flags = self.ecx.expr_uint(sp, arg.format.flags);
|
let flags = self.ecx.expr_uint(sp, arg.format.flags);
|
||||||
let prec = trans_count(arg.format.precision);
|
let prec = self.trans_count(arg.format.precision);
|
||||||
let width = trans_count(arg.format.width);
|
let width = self.trans_count(arg.format.width);
|
||||||
let path = self.ecx.path_global(sp, rtpath("FormatSpec"));
|
let path = self.ecx.path_global(sp, self.rtpath("FormatSpec"));
|
||||||
let fmt = self.ecx.expr_struct(sp, path, ~[
|
let fmt = self.ecx.expr_struct(sp, path, ~[
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
|
self.ecx.field_imm(sp, self.ecx.ident_of("fill"), fill),
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
|
self.ecx.field_imm(sp, self.ecx.ident_of("align"), align),
|
||||||
@ -574,19 +585,19 @@ impl<'a> Context<'a> {
|
|||||||
|
|
||||||
// Translate the method (if any)
|
// Translate the method (if any)
|
||||||
let method = match arg.method {
|
let method = match arg.method {
|
||||||
None => { none.clone() }
|
None => { self.none() }
|
||||||
Some(ref m) => {
|
Some(ref m) => {
|
||||||
let m = trans_method(*m);
|
let m = self.trans_method(*m);
|
||||||
some(self.ecx.expr_addr_of(sp, m))
|
self.some(self.ecx.expr_addr_of(sp, m))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let path = self.ecx.path_global(sp, rtpath("Argument"));
|
let path = self.ecx.path_global(sp, self.rtpath("Argument"));
|
||||||
let s = self.ecx.expr_struct(sp, path, ~[
|
let s = self.ecx.expr_struct(sp, path, ~[
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
|
self.ecx.field_imm(sp, self.ecx.ident_of("position"), pos),
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
|
self.ecx.field_imm(sp, self.ecx.ident_of("format"), fmt),
|
||||||
self.ecx.field_imm(sp, self.ecx.ident_of("method"), method),
|
self.ecx.field_imm(sp, self.ecx.ident_of("method"), method),
|
||||||
]);
|
]);
|
||||||
self.ecx.expr_call_global(sp, rtpath("Argument"), ~[s])
|
self.ecx.expr_call_global(sp, self.rtpath("Argument"), ~[s])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user