summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-02-07 14:45:46 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-02-11 16:55:23 -0500
commitca65c00ef2e1fb7373c97085315703887ee4d53c (patch)
tree41d860ac965ee934c5c4d888ffc8cba5cc345325 /src/libsyntax
parentb2b4c79b179413d4a5e1d706844b11dfca8226c8 (diff)
downloadrust-ca65c00ef2e1fb7373c97085315703887ee4d53c.tar.gz
rust-ca65c00ef2e1fb7373c97085315703887ee4d53c.zip
syntax/ext/format -- rewrite conflicting closures into methods
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/format.rs243
1 files changed, 127 insertions, 116 deletions
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 4bc3b804c7f..35d2adbead5 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -21,6 +21,7 @@ use rsparse = parse;
 use std::fmt::parse;
 use std::hashmap::{HashMap, HashSet};
 use std::vec;
+use std::cell::RefCell;
 
 #[deriving(Eq)]
 enum ArgumentType {
@@ -367,157 +368,167 @@ impl<'a> Context<'a> {
         return ~[unnamed, allow_dead_code];
     }
 
-    /// Translate a `parse::Piece` to a static `rt::Piece`
-    fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr {
-        let sp = self.fmtsp;
-        let parsepath = |s: &str| {
-            ~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
-              self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
-        };
-        let rtpath = |s: &str| {
-            ~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
-              self.ecx.ident_of("rt"), self.ecx.ident_of(s)]
-        };
-        let ctpath = |s: &str| {
-            ~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
-              self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
-        };
-        let none = self.ecx.path_global(sp, ~[
+    fn parsepath(&self, s: &str) -> ~[ast::Ident] {
+        ~[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"),
+          self.ecx.ident_of("rt"), self.ecx.ident_of(s)]
+    }
+
+    fn ctpath(&self, s: &str) -> ~[ast::Ident] {
+        ~[self.ecx.ident_of("std"), self.ecx.ident_of("fmt"),
+          self.ecx.ident_of("parse"), self.ecx.ident_of(s)]
+    }
+
+    fn none(&self) -> @ast::Expr {
+        let none = self.ecx.path_global(self.fmtsp, ~[
                 self.ecx.ident_of("std"),
                 self.ecx.ident_of("option"),
                 self.ecx.ident_of("None")]);
-        let none = self.ecx.expr_path(none);
-        let some = |e: @ast::Expr| {
-            let p = self.ecx.path_global(sp, ~[
+        self.ecx.expr_path(none)
+    }
+
+    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("option"),
                 self.ecx.ident_of("Some")]);
-            let p = self.ecx.expr_path(p);
-            self.ecx.expr_call(sp, p, ~[e])
-        };
-        let trans_count = |c: parse::Count| {
-            match c {
-                parse::CountIs(i) => {
-                    self.ecx.expr_call_global(sp, rtpath("CountIs"),
-                                              ~[self.ecx.expr_uint(sp, i)])
-                }
-                parse::CountIsParam(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)])
-                }
+        let p = self.ecx.expr_path(p);
+        self.ecx.expr_call(self.fmtsp, p, ~[e])
+    }
+
+    fn trans_count(&self, c: parse::Count) -> @ast::Expr {
+        let sp = self.fmtsp;
+        match c {
+            parse::CountIs(i) => {
+                self.ecx.expr_call_global(sp, self.rtpath("CountIs"),
+                                          ~[self.ecx.expr_uint(sp, i)])
             }
-        };
-        let trans_method = |method: &parse::Method| {
-            let method = match *method {
-                parse::Select(ref arms, ref default) => {
-                    let arms = arms.iter().map(|arm| {
-                        let p = self.ecx.path_global(sp, rtpath("SelectArm"));
+            parse::CountIsParam(i) => {
+                self.ecx.expr_call_global(sp, self.rtpath("CountIsParam"),
+                                          ~[self.ecx.expr_uint(sp, i)])
+            }
+            parse::CountImplied => {
+                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| {
                             self.trans_piece(p)
                         }).collect();
                         let s = token::intern_and_get_ident(arm.selector);
                         let selector = self.ecx.expr_str(sp, s);
                         self.ecx.expr_struct(sp, p, ~[
-                            self.ecx.field_imm(sp,
-                                               self.ecx.ident_of("selector"),
-                                               selector),
-                            self.ecx.field_imm(sp, self.ecx.ident_of("result"),
-                                               self.ecx.expr_vec_slice(sp, result)),
-                        ])
+                                self.ecx.field_imm(sp,
+                                                   self.ecx.ident_of("selector"),
+                                                   selector),
+                                self.ecx.field_imm(sp, self.ecx.ident_of("result"),
+                                                   self.ecx.expr_vec_slice(sp, result)),
+                                ])
                     }).collect();
-                    let default = default.iter().map(|p| {
+                let default = default.iter().map(|p| {
                         self.trans_piece(p)
                     }).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, default),
-                    ])
-                }
-                parse::Plural(offset, ref arms, ref default) => {
-                    let offset = match offset {
-                        Some(i) => { some(self.ecx.expr_uint(sp, i)) }
-                        None => { none.clone() }
-                    };
-                    let arms = arms.iter().map(|arm| {
-                        let p = self.ecx.path_global(sp, rtpath("PluralArm"));
+                        ])
+            }
+            parse::Plural(offset, ref arms, ref default) => {
+                let offset = match offset {
+                    Some(i) => { self.some(self.ecx.expr_uint(sp, i)) }
+                    None => { self.none() }
+                };
+                let arms = arms.iter().map(|arm| {
+                        let p = self.ecx.path_global(sp, self.rtpath("PluralArm"));
                         let result = arm.result.iter().map(|p| {
-                            self.trans_piece(p)
-                        }).collect();
+                                self.trans_piece(p)
+                            }).collect();
                         let (lr, selarg) = match arm.selector {
                             parse::Keyword(t) => {
-                                let p = ctpath(format!("{:?}", t));
+                                let p = self.ctpath(format!("{:?}", t));
                                 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) => {
-                                (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,
-                                lr, ~[selarg]);
+                                                                 lr, ~[selarg]);
                         self.ecx.expr_struct(sp, p, ~[
-                            self.ecx.field_imm(sp,
-                                               self.ecx.ident_of("selector"),
-                                               selector),
-                            self.ecx.field_imm(sp, self.ecx.ident_of("result"),
-                                               self.ecx.expr_vec_slice(sp, result)),
-                        ])
+                                self.ecx.field_imm(sp,
+                                                   self.ecx.ident_of("selector"),
+                                                   selector),
+                                self.ecx.field_imm(sp, self.ecx.ident_of("result"),
+                                                   self.ecx.expr_vec_slice(sp, result)),
+                                ])
                     }).collect();
-                    let default = default.iter().map(|p| {
+                let default = default.iter().map(|p| {
                         self.trans_piece(p)
                     }).collect();
-                    self.ecx.expr_call_global(sp, rtpath("Plural"), ~[
+                self.ecx.expr_call_global(sp, self.rtpath("Plural"), ~[
                         offset,
                         self.ecx.expr_vec_slice(sp, arms),
                         self.ecx.expr_vec_slice(sp, default),
-                    ])
-                }
-            };
-            let life = self.ecx.lifetime(sp, self.ecx.ident_of("static"));
-            let ty = self.ecx.ty_path(self.ecx.path_all(
+                        ])
+            }
+        };
+        let life = self.ecx.lifetime(sp, self.ecx.ident_of("static"));
+        let ty = self.ecx.ty_path(self.ecx.path_all(
                 sp,
                 true,
-                rtpath("Method"),
+                self.rtpath("Method"),
                 opt_vec::with(life),
                 ~[]
-            ), None);
-            let st = ast::ItemStatic(ty, ast::MutImmutable, method);
-            let static_name = self.ecx.ident_of(format!("__STATIC_METHOD_{}",
-                                                     self.method_statics.len()));
-            let item = self.ecx.item(sp, static_name, self.static_attrs(), st);
-            self.method_statics.push(item);
-            self.ecx.expr_ident(sp, static_name)
-        };
+                    ), None);
+        let st = ast::ItemStatic(ty, ast::MutImmutable, method);
+        let static_name = self.ecx.ident_of(format!("__STATIC_METHOD_{}",
+                                                    self.method_statics.len()));
+        let item = self.ecx.item(sp, static_name, self.static_attrs(), st);
+        self.method_statics.push(item);
+        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 {
             parse::String(s) => {
                 let s = token::intern_and_get_ident(s);
                 self.ecx.expr_call_global(sp,
-                                          rtpath("String"),
+                                          self.rtpath("String"),
                                           ~[
                     self.ecx.expr_str(sp, s)
                 ])
             }
             parse::CurrentArgument => {
                 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) => {
                 // Translate the position
@@ -525,11 +536,11 @@ impl<'a> Context<'a> {
                     // These two have a direct mapping
                     parse::ArgumentNext => {
                         let path = self.ecx.path_global(sp,
-                                                        rtpath("ArgumentNext"));
+                                                        self.rtpath("ArgumentNext"));
                         self.ecx.expr_path(path)
                     }
                     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)])
                     }
                     // Named arguments are converted to positional arguments at
@@ -540,7 +551,7 @@ impl<'a> Context<'a> {
                             None => 0, // error already emitted elsewhere
                         };
                         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)])
                     }
                 };
@@ -550,20 +561,20 @@ impl<'a> Context<'a> {
                 let fill = self.ecx.expr_lit(sp, ast::LitChar(fill as u32));
                 let align = match arg.format.align {
                     parse::AlignLeft => {
-                        self.ecx.path_global(sp, parsepath("AlignLeft"))
+                        self.ecx.path_global(sp, self.parsepath("AlignLeft"))
                     }
                     parse::AlignRight => {
-                        self.ecx.path_global(sp, parsepath("AlignRight"))
+                        self.ecx.path_global(sp, self.parsepath("AlignRight"))
                     }
                     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 flags = self.ecx.expr_uint(sp, arg.format.flags);
-                let prec = trans_count(arg.format.precision);
-                let width = trans_count(arg.format.width);
-                let path = self.ecx.path_global(sp, rtpath("FormatSpec"));
+                let prec = self.trans_count(arg.format.precision);
+                let width = self.trans_count(arg.format.width);
+                let path = self.ecx.path_global(sp, self.rtpath("FormatSpec"));
                 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("align"), align),
@@ -574,19 +585,19 @@ impl<'a> Context<'a> {
 
                 // Translate the method (if any)
                 let method = match arg.method {
-                    None => { none.clone() }
+                    None => { self.none() }
                     Some(ref m) => {
-                        let m = trans_method(*m);
-                        some(self.ecx.expr_addr_of(sp, m))
+                        let m = self.trans_method(*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, ~[
                     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("method"), method),
                 ]);
-                self.ecx.expr_call_global(sp, rtpath("Argument"), ~[s])
+                self.ecx.expr_call_global(sp, self.rtpath("Argument"), ~[s])
             }
         }
     }