about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2013-05-17 23:51:25 +1000
committerHuon Wilson <dbau.pp+github@gmail.com>2013-05-22 00:04:10 +1000
commit8c15a0ec4cf023a08078d74ed615ecef0cc10a66 (patch)
tree2a2f9d23e845713d92080b3b7616c8c14ed3e14b /src/libsyntax
parent4045da9f4f7290b02bee52caa42504e4ce5406f7 (diff)
downloadrust-8c15a0ec4cf023a08078d74ed615ecef0cc10a66.tar.gz
rust-8c15a0ec4cf023a08078d74ed615ecef0cc10a66.zip
syntax/ext: collect the ast building traits into a single trait.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/build.rs488
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs382
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs38
-rw-r--r--src/libsyntax/ext/pipes/proto.rs5
4 files changed, 420 insertions, 493 deletions
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index e28c04d198a..a2d88c1f23a 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -8,13 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use abi::AbiSet;
+use ast::ident;
 use ast;
+use ast_util;
 use codemap;
-use codemap::span;
+use codemap::{span, respan, dummy_sp, spanned};
 use fold;
 use ext::base::ExtCtxt;
-use ext::build;
-
+use ext::quote::rt::*;
+use opt_vec;
 use opt_vec::OptVec;
 
 pub struct Field {
@@ -547,14 +550,8 @@ mod syntax {
     pub use parse;
 }
 
-trait ExtCtxtMethods {
-    fn bind_path(&self,
-                 span: span,
-                 ident: ast::ident,
-                 path: @ast::Path,
-                 bounds: @OptVec<ast::TyParamBound>)
-                 -> ast::TyParam;
-    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
+pub trait AstBuilder {
+    // paths
     fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
     fn path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::Path;
     fn path_tps(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
@@ -564,16 +561,35 @@ trait ExtCtxtMethods {
                        strs: ~[ast::ident],
                        tps: ~[@ast::Ty])
                        -> @ast::Path;
-    fn ty_path(&self, span: span, strs: ~[ast::ident], tps: ~[@ast::Ty])
-               -> @ast::Ty;
-    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat;
-    fn stmt(&self, expr: @ast::expr) -> @ast::stmt;
+
+    // types
+    fn ty_path(&self, @ast::Path) -> @ast::Ty;
+
+    fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
+        -> ast::TyParam;
+    fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
+    fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
+    fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field;
+    fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty;
+    fn ty_infer(&self) -> @ast::Ty;
+    fn ty_nil_ast_builder(&self) -> @ast::Ty;
+    fn strip_bounds(&self, bounds: &Generics) -> Generics;
+
+
+    // statements
+    fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt;
+    fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt;
+
+    // literals
     fn lit_str(&self, span: span, s: @~str) -> @ast::expr;
     fn lit_uint(&self, span: span, i: uint) -> @ast::expr;
-    fn lambda0(&self, blk: ast::blk) -> @ast::expr;
-    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr;
-    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk;
-    fn expr_blk(&self, expr: @ast::expr) -> ast::blk;
+
+    // blocks
+    fn blk(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@ast::expr>) -> ast::blk;
+    fn blk_expr(&self, expr: @ast::expr) -> ast::blk;
+
+    // expressions
+    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr;
     fn expr_path(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
     fn expr_path_global(&self, span: span, strs: ~[ast::ident]) -> @ast::expr;
     fn expr_var(&self, span: span, var: &str) -> @ast::expr;
@@ -588,6 +604,13 @@ trait ExtCtxtMethods {
                         ident: ast::ident,
                         args: ~[@ast::expr])
                         -> @ast::expr;
+    fn expr_blk(&self, b: ast::blk) -> @ast::expr;
+    fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field;
+    fn expr_struct(&self,
+                   path: @ast::Path,
+                   fields: ~[ast::field]) -> @ast::expr;
+    fn lambda0(&self, blk: ast::blk) -> @ast::expr;
+    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr;
     fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr;
     fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
                     -> @ast::expr;
@@ -597,37 +620,64 @@ trait ExtCtxtMethods {
                       stmts: ~[@ast::stmt],
                       ident: ast::ident)
                       -> @ast::expr;
-}
 
-impl ExtCtxtMethods for @ExtCtxt {
-    fn bind_path(
-        &self,
-        _span: span,
-        ident: ast::ident,
-        path: @ast::Path,
-        bounds: @OptVec<ast::TyParamBound>
-    ) -> ast::TyParam {
-        let bound = ast::TraitTyParamBound(@ast::trait_ref {
-            ref_id: self.next_id(),
-            path: path
-        });
+    // items
+    fn item(&self, name: ident, span: span, node: ast::item_) -> @ast::item;
 
-        ast::TyParam {
-            ident: ident,
-            id: self.next_id(),
-            bounds: @bounds.prepend(bound)
-        }
-    }
+    fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg;
+    fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
 
-    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr {
-        @ast::expr {
-            id: self.next_id(),
-            callee_id: self.next_id(),
-            node: node,
-            span: span,
-        }
-    }
+    fn item_fn_poly(&self,
+                    ame: ident,
+                    inputs: ~[ast::arg],
+                    output: @ast::Ty,
+                    generics: Generics,
+                    body: ast::blk) -> @ast::item;
+    fn item_fn(&self,
+               name: ident,
+               inputs: ~[ast::arg],
+               output: @ast::Ty,
+               body: ast::blk) -> @ast::item;
+
+    fn variant(&self,
+               name: ident,
+               span: span,
+               tys: ~[@ast::Ty]) -> ast::variant;
+    fn item_enum_poly(&self,
+                      name: ident,
+                      span: span,
+                      enum_definition: ast::enum_def,
+                      generics: Generics) -> @ast::item;
+    fn item_enum(&self,
+                 name: ident,
+                 span: span,
+                 enum_definition: ast::enum_def) -> @ast::item;
+
+    fn item_struct_poly(&self,
+                        name: ident,
+                        span: span,
+                        struct_def: ast::struct_def,
+                        generics: Generics) -> @ast::item;
+    fn item_struct(&self,
+                   name: ident,
+                   span: span,
+                   struct_def: ast::struct_def) -> @ast::item;
+
+    fn item_mod(&self,
+                name: ident,
+                span: span,
+                items: ~[@ast::item]) -> @ast::item;
+
+    fn item_ty_poly(&self,
+                    name: ident,
+                    span: span,
+                    ty: @ast::Ty,
+                    generics: Generics) -> @ast::item;
+    fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item;
+
+}
 
+impl AstBuilder for @ExtCtxt {
     fn path(&self, span: span, strs: ~[ast::ident]) -> @ast::Path {
         @ast::Path {
             span: span,
@@ -678,37 +728,89 @@ impl ExtCtxtMethods for @ExtCtxt {
         }
     }
 
-    fn ty_path(
-        &self,
-        span: span,
-        strs: ~[ast::ident],
-        tps: ~[@ast::Ty]
-    ) -> @ast::Ty {
+    fn ty_path(&self, path: @ast::Path) -> @ast::Ty {
+        build::mk_ty(*self, path.span,
+                     ast::ty_path(path, self.next_id()))
+    }
+
+    fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty {
+        self.ty_path(
+            self.path_tps_global(dummy_sp(),
+                                 ~[
+                                     self.ident_of("core"),
+                                     self.ident_of("option"),
+                                     self.ident_of("Option")
+                                 ],
+                                 ~[ ty ]))
+    }
+
+    fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field {
+        spanned {
+            node: ast::ty_field_ {
+                ident: name,
+                mt: ast::mt { ty: ty, mutbl: ast::m_imm },
+            },
+            span: dummy_sp(),
+        }
+    }
+
+    fn ty_infer(&self) -> @ast::Ty {
         @ast::Ty {
             id: self.next_id(),
-            node: ast::ty_path(
-                self.path_tps(span, strs, tps),
-                self.next_id()),
-            span: span,
+            node: ast::ty_infer,
+            span: dummy_sp(),
         }
     }
 
-    fn binder_pat(&self, span: span, nm: ast::ident) -> @ast::pat {
-        @ast::pat {
+    fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
+        -> ast::TyParam
+    {
+        ast::TyParam { ident: id, id: self.next_id(), bounds: bounds }
+    }
+
+    fn ty_nil_ast_builder(&self) -> @ast::Ty {
+        @ast::Ty {
             id: self.next_id(),
-            node: ast::pat_ident(
-                ast::bind_by_ref(ast::m_imm),
-                self.path(span, ~[nm]),
-                None),
-            span: span,
+            node: ast::ty_nil,
+            span: dummy_sp(),
+        }
+    }
+
+    fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
+        opt_vec::take_vec(
+            ty_params.map(|p| self.ty_path(
+                mk_raw_path(dummy_sp(), ~[p.ident]))))
+    }
+
+    fn ty_vars_global(&self,
+                      ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
+        opt_vec::take_vec(
+            ty_params.map(|p| self.ty_path(
+                mk_raw_path(dummy_sp(), ~[p.ident]))))
+    }
+
+    fn strip_bounds(&self, generics: &Generics) -> Generics {
+        let no_bounds = @opt_vec::Empty;
+        let new_params = do generics.ty_params.map |ty_param| {
+            ast::TyParam { bounds: no_bounds, ..copy *ty_param }
+        };
+        Generics {
+            ty_params: new_params,
+            .. copy *generics
         }
     }
 
-    fn stmt(&self, expr: @ast::expr) -> @ast::stmt {
+
+    fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt {
         @codemap::spanned { node: ast::stmt_semi(expr, self.next_id()),
                        span: expr.span }
     }
 
+    fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt {
+        let ext_cx = *self;
+        quote_stmt!( let $ident = $e; )
+    }
+
     fn lit_str(&self, span: span, s: @~str) -> @ast::expr {
         self.expr(
             span,
@@ -729,24 +831,12 @@ impl ExtCtxtMethods for @ExtCtxt {
                                 span: span}))
     }
 
-    fn lambda0(&self, blk: ast::blk) -> @ast::expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
-        quote_expr!( || $blk_e )
-    }
-
-    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr {
-        let ext_cx = *self;
-        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
-        quote_expr!( |$ident| $blk_e )
-    }
-
-    fn blk(&self, span: span, stmts: ~[@ast::stmt]) -> ast::blk {
+    fn blk(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@expr>) -> ast::blk {
         codemap::spanned {
             node: ast::blk_ {
                 view_items: ~[],
                 stmts: stmts,
-                expr: None,
+                expr: expr,
                 id: self.next_id(),
                 rules: ast::default_blk,
             },
@@ -754,16 +844,16 @@ impl ExtCtxtMethods for @ExtCtxt {
         }
     }
 
-    fn expr_blk(&self, expr: @ast::expr) -> ast::blk {
-        codemap::spanned {
-            node: ast::blk_ {
-                view_items: ~[],
-                stmts: ~[],
-                expr: Some(expr),
-                id: self.next_id(),
-                rules: ast::default_blk,
-            },
-            span: expr.span,
+    fn blk_expr(&self, expr: @ast::expr) -> ast::blk {
+        self.blk(expr.span, ~[], Some(expr))
+    }
+
+    fn expr(&self, span: span, node: ast::expr_) -> @ast::expr {
+        @ast::expr {
+            id: self.next_id(),
+            callee_id: self.next_id(),
+            node: node,
+            span: span,
         }
     }
 
@@ -815,18 +905,49 @@ impl ExtCtxtMethods for @ExtCtxt {
         self.expr(span,
                   ast::expr_method_call(expr, ident, ~[], args, ast::NoSugar))
     }
+    fn expr_blk(&self, b: ast::blk) -> @ast::expr {
+        self.expr(dummy_sp(), ast::expr_block(b))
+    }
+    fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field {
+        spanned {
+            node: ast::field_ { mutbl: ast::m_imm, ident: name, expr: e },
+            span: dummy_sp(),
+        }
+    }
+    fn expr_struct(&self, path: @ast::Path,
+                   fields: ~[ast::field]) -> @ast::expr {
+        @ast::expr {
+            id: self.next_id(),
+            callee_id: self.next_id(),
+            node: ast::expr_struct(path, fields, None),
+            span: dummy_sp()
+        }
+    }
+
+
+    fn lambda0(&self, blk: ast::blk) -> @ast::expr {
+        let ext_cx = *self;
+        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
+        quote_expr!( || $blk_e )
+    }
+
+    fn lambda1(&self, blk: ast::blk, ident: ast::ident) -> @ast::expr {
+        let ext_cx = *self;
+        let blk_e = self.expr(copy blk.span, ast::expr_block(copy blk));
+        quote_expr!( |$ident| $blk_e )
+    }
 
     fn lambda_expr_0(&self, expr: @ast::expr) -> @ast::expr {
-        self.lambda0(self.expr_blk(expr))
+        self.lambda0(self.blk_expr(expr))
     }
 
     fn lambda_expr_1(&self, expr: @ast::expr, ident: ast::ident)
                     -> @ast::expr {
-        self.lambda1(self.expr_blk(expr), ident)
+        self.lambda1(self.blk_expr(expr), ident)
     }
 
     fn lambda_stmts_0(&self, span: span, stmts: ~[@ast::stmt]) -> @ast::expr {
-        self.lambda0(self.blk(span, stmts))
+        self.lambda0(self.blk(span, stmts, None))
     }
 
     fn lambda_stmts_1(&self,
@@ -834,6 +955,189 @@ impl ExtCtxtMethods for @ExtCtxt {
                       stmts: ~[@ast::stmt],
                       ident: ast::ident)
                       -> @ast::expr {
-        self.lambda1(self.blk(span, stmts), ident)
+        self.lambda1(self.blk(span, stmts, None), ident)
+    }
+
+
+    fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg {
+        ast::arg {
+            is_mutbl: false,
+            ty: ty,
+            pat: @ast::pat {
+                id: self.next_id(),
+                node: ast::pat_ident(
+                    ast::bind_by_copy,
+                    ast_util::ident_to_path(dummy_sp(), name),
+                    None),
+                span: dummy_sp(),
+            },
+            id: self.next_id(),
+        }
     }
+
+    fn fn_decl(&self, inputs: ~[ast::arg],
+               output: @ast::Ty) -> ast::fn_decl {
+        ast::fn_decl {
+            inputs: inputs,
+            output: output,
+            cf: ast::return_val,
+        }
+    }
+
+    fn item(&self, name: ident, span: span,
+            node: ast::item_) -> @ast::item {
+
+        // XXX: Would be nice if our generated code didn't violate
+        // Rust coding conventions
+        let non_camel_case_attribute = respan(dummy_sp(), ast::attribute_ {
+            style: ast::attr_outer,
+            value: @respan(dummy_sp(),
+                          ast::meta_list(@~"allow", ~[
+                              @respan(dummy_sp(),
+                                      ast::meta_word(
+                                         @~"non_camel_case_types"))
+                          ])),
+            is_sugared_doc: false
+        });
+
+        @ast::item { ident: name,
+                     attrs: ~[non_camel_case_attribute],
+                     id: self.next_id(),
+                     node: node,
+                     vis: ast::public,
+                     span: span }
+    }
+
+    fn item_fn_poly(&self, name: ident,
+                    inputs: ~[ast::arg],
+                    output: @ast::Ty,
+                    generics: Generics,
+                    body: ast::blk) -> @ast::item {
+        self.item(name,
+                  dummy_sp(),
+                  ast::item_fn(self.fn_decl(inputs, output),
+                               ast::impure_fn,
+                               AbiSet::Rust(),
+                               generics,
+                               body))
+    }
+
+    fn item_fn(&self,
+               name: ident,
+               inputs: ~[ast::arg],
+               output: @ast::Ty,
+               body: ast::blk
+    ) -> @ast::item {
+        self.item_fn_poly(
+            name,
+            inputs,
+            output,
+            ast_util::empty_generics(),
+            body
+        )
+    }
+
+    fn variant(&self, name: ident, span: span,
+               tys: ~[@ast::Ty]) -> ast::variant {
+        let args = do tys.map |ty| {
+            ast::variant_arg { ty: *ty, id: self.next_id() }
+        };
+
+        spanned {
+            node: ast::variant_ {
+                name: name,
+                attrs: ~[],
+                kind: ast::tuple_variant_kind(args),
+                id: self.next_id(),
+                disr_expr: None,
+                vis: ast::public
+            },
+            span: span,
+        }
+    }
+
+    fn item_enum_poly(&self, name: ident, span: span,
+                      enum_definition: ast::enum_def,
+                      generics: Generics) -> @ast::item {
+        self.item(name, span, ast::item_enum(enum_definition, generics))
+    }
+
+    fn item_enum(&self, name: ident, span: span,
+                 enum_definition: ast::enum_def) -> @ast::item {
+        self.item_enum_poly(name, span, enum_definition,
+                            ast_util::empty_generics())
+    }
+
+    fn item_struct(
+        &self, name: ident,
+        span: span,
+        struct_def: ast::struct_def
+    ) -> @ast::item {
+        self.item_struct_poly(
+            name,
+            span,
+            struct_def,
+            ast_util::empty_generics()
+        )
+    }
+
+    fn item_struct_poly(
+        &self,
+        name: ident,
+        span: span,
+        struct_def: ast::struct_def,
+        generics: Generics
+    ) -> @ast::item {
+        self.item(name, span, ast::item_struct(@struct_def, generics))
+    }
+
+    fn item_mod(&self, name: ident, span: span,
+                items: ~[@ast::item]) -> @ast::item {
+
+        // XXX: Total hack: import `core::kinds::Owned` to work around a
+        // parser bug whereby `fn f<T:::kinds::Owned>` doesn't parse.
+        let vi = ast::view_item_use(~[
+            @codemap::spanned {
+                node: ast::view_path_simple(
+                    self.ident_of("Owned"),
+                    mk_raw_path(
+                        codemap::dummy_sp(),
+                        ~[
+                            self.ident_of("core"),
+                            self.ident_of("kinds"),
+                            self.ident_of("Owned")
+                        ]
+                    ),
+                    self.next_id()
+                ),
+                span: codemap::dummy_sp()
+            }
+        ]);
+        let vi = @ast::view_item {
+            node: vi,
+            attrs: ~[],
+            vis: ast::private,
+            span: codemap::dummy_sp()
+        };
+
+        self.item(
+            name,
+            span,
+            ast::item_mod(ast::_mod {
+                view_items: ~[vi],
+                items: items,
+            })
+        )
+    }
+
+    fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty,
+                    generics: Generics) -> @ast::item {
+        self.item(name, span, ast::item_ty(ty, generics))
+    }
+
+    fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item {
+        self.item_ty_poly(name, span, ty, ast_util::empty_generics())
+    }
+
+
 }
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index 1f38b14efbe..44f47c0d588 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -13,16 +13,10 @@
 // To start with, it will be use dummy spans, but it might someday do
 // something smarter.
 
-use abi::AbiSet;
 use ast::ident;
 use ast;
-use ast_util;
-use codemap::{span, respan, dummy_sp, spanned};
-use codemap;
-use ext::base::ExtCtxt;
+use codemap::span;
 use ext::quote::rt::*;
-use opt_vec;
-use opt_vec::OptVec;
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
@@ -66,377 +60,3 @@ impl append_types for @ast::Path {
         }
     }
 }
-
-pub trait ext_ctxt_ast_builder {
-    fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-        -> ast::TyParam;
-    fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg;
-    fn expr_block(&self, e: @ast::expr) -> ast::blk;
-    fn fn_decl(&self, inputs: ~[ast::arg], output: @ast::Ty) -> ast::fn_decl;
-    fn item(&self, name: ident, span: span, node: ast::item_) -> @ast::item;
-    fn item_fn_poly(&self,
-                    ame: ident,
-                    inputs: ~[ast::arg],
-                    output: @ast::Ty,
-                    generics: Generics,
-                    body: ast::blk) -> @ast::item;
-    fn item_fn(&self,
-               name: ident,
-               inputs: ~[ast::arg],
-               output: @ast::Ty,
-               body: ast::blk) -> @ast::item;
-    fn item_enum_poly(&self,
-                      name: ident,
-                      span: span,
-                      enum_definition: ast::enum_def,
-                      generics: Generics) -> @ast::item;
-    fn item_enum(&self,
-                 name: ident,
-                 span: span,
-                 enum_definition: ast::enum_def) -> @ast::item;
-    fn item_struct_poly(&self,
-                        name: ident,
-                        span: span,
-                        struct_def: ast::struct_def,
-                        generics: Generics) -> @ast::item;
-    fn item_struct(&self,
-                   name: ident,
-                   span: span,
-                   struct_def: ast::struct_def) -> @ast::item;
-    fn struct_expr(&self,
-                   path: @ast::Path,
-                   fields: ~[ast::field]) -> @ast::expr;
-    fn variant(&self,
-               name: ident,
-               span: span,
-               tys: ~[@ast::Ty]) -> ast::variant;
-    fn item_mod(&self,
-                name: ident,
-                span: span,
-                items: ~[@ast::item]) -> @ast::item;
-    fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty;
-    fn item_ty_poly(&self,
-                    name: ident,
-                    span: span,
-                    ty: @ast::Ty,
-                    generics: Generics) -> @ast::item;
-    fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item;
-    fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
-    fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty];
-    fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field;
-    fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field;
-    fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk;
-    fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt;
-    fn stmt_expr(&self, e: @ast::expr) -> @ast::stmt;
-    fn block_expr(&self, b: ast::blk) -> @ast::expr;
-    fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty;
-    fn ty_infer(&self) -> @ast::Ty;
-    fn ty_nil_ast_builder(&self) -> @ast::Ty;
-    fn strip_bounds(&self, bounds: &Generics) -> Generics;
-}
-
-impl ext_ctxt_ast_builder for @ExtCtxt {
-    fn ty_option(&self, ty: @ast::Ty) -> @ast::Ty {
-        self.ty_path_ast_builder(path_global(~[
-            self.ident_of("core"),
-            self.ident_of("option"),
-            self.ident_of("Option")
-        ], dummy_sp()).add_ty(ty))
-    }
-
-    fn block_expr(&self, b: ast::blk) -> @ast::expr {
-        @expr {
-            id: self.next_id(),
-            callee_id: self.next_id(),
-            node: ast::expr_block(b),
-            span: dummy_sp(),
-        }
-    }
-
-    fn stmt_expr(&self, e: @ast::expr) -> @ast::stmt {
-        @spanned { node: ast::stmt_expr(e, self.next_id()),
-                   span: dummy_sp()}
-    }
-
-    fn stmt_let(&self, ident: ident, e: @ast::expr) -> @ast::stmt {
-        let ext_cx = *self;
-        quote_stmt!( let $ident = $e; )
-    }
-
-    fn field_imm(&self, name: ident, e: @ast::expr) -> ast::field {
-        spanned {
-            node: ast::field_ { mutbl: ast::m_imm, ident: name, expr: e },
-            span: dummy_sp(),
-        }
-    }
-
-    fn ty_field_imm(&self, name: ident, ty: @ast::Ty) -> ast::ty_field {
-        spanned {
-            node: ast::ty_field_ {
-                ident: name,
-                mt: ast::mt { ty: ty, mutbl: ast::m_imm },
-            },
-            span: dummy_sp(),
-        }
-    }
-
-    fn ty_infer(&self) -> @ast::Ty {
-        @ast::Ty {
-            id: self.next_id(),
-            node: ast::ty_infer,
-            span: dummy_sp(),
-        }
-    }
-
-    fn ty_param(&self, id: ast::ident, bounds: @OptVec<ast::TyParamBound>)
-        -> ast::TyParam
-    {
-        ast::TyParam { ident: id, id: self.next_id(), bounds: bounds }
-    }
-
-    fn arg(&self, name: ident, ty: @ast::Ty) -> ast::arg {
-        ast::arg {
-            is_mutbl: false,
-            ty: ty,
-            pat: @ast::pat {
-                id: self.next_id(),
-                node: ast::pat_ident(
-                    ast::bind_by_copy,
-                    ast_util::ident_to_path(dummy_sp(), name),
-                    None),
-                span: dummy_sp(),
-            },
-            id: self.next_id(),
-        }
-    }
-
-    fn block(&self, stmts: ~[@ast::stmt], e: @ast::expr) -> ast::blk {
-        let blk = ast::blk_ {
-            view_items: ~[],
-            stmts: stmts,
-            expr: Some(e),
-            id: self.next_id(),
-            rules: ast::default_blk,
-        };
-
-        spanned { node: blk, span: dummy_sp() }
-    }
-
-    fn expr_block(&self, e: @ast::expr) -> ast::blk {
-        self.block(~[], e)
-    }
-
-    fn fn_decl(&self, inputs: ~[ast::arg],
-               output: @ast::Ty) -> ast::fn_decl {
-        ast::fn_decl {
-            inputs: inputs,
-            output: output,
-            cf: ast::return_val,
-        }
-    }
-
-    fn item(&self, name: ident, span: span,
-            node: ast::item_) -> @ast::item {
-
-        // XXX: Would be nice if our generated code didn't violate
-        // Rust coding conventions
-        let non_camel_case_attribute = respan(dummy_sp(), ast::attribute_ {
-            style: ast::attr_outer,
-            value: @respan(dummy_sp(),
-                          ast::meta_list(@~"allow", ~[
-                              @respan(dummy_sp(),
-                                      ast::meta_word(
-                                         @~"non_camel_case_types"))
-                          ])),
-            is_sugared_doc: false
-        });
-
-        @ast::item { ident: name,
-                     attrs: ~[non_camel_case_attribute],
-                     id: self.next_id(),
-                     node: node,
-                     vis: ast::public,
-                     span: span }
-    }
-
-    fn item_fn_poly(&self, name: ident,
-                    inputs: ~[ast::arg],
-                    output: @ast::Ty,
-                    generics: Generics,
-                    body: ast::blk) -> @ast::item {
-        self.item(name,
-                  dummy_sp(),
-                  ast::item_fn(self.fn_decl(inputs, output),
-                               ast::impure_fn,
-                               AbiSet::Rust(),
-                               generics,
-                               body))
-    }
-
-    fn item_fn(&self,
-               name: ident,
-               inputs: ~[ast::arg],
-               output: @ast::Ty,
-               body: ast::blk
-    ) -> @ast::item {
-        self.item_fn_poly(
-            name,
-            inputs,
-            output,
-            ast_util::empty_generics(),
-            body
-        )
-    }
-
-    fn item_enum_poly(&self, name: ident, span: span,
-                      enum_definition: ast::enum_def,
-                      generics: Generics) -> @ast::item {
-        self.item(name, span, ast::item_enum(enum_definition, generics))
-    }
-
-    fn item_enum(&self, name: ident, span: span,
-                 enum_definition: ast::enum_def) -> @ast::item {
-        self.item_enum_poly(name, span, enum_definition,
-                            ast_util::empty_generics())
-    }
-
-    fn item_struct(
-        &self, name: ident,
-        span: span,
-        struct_def: ast::struct_def
-    ) -> @ast::item {
-        self.item_struct_poly(
-            name,
-            span,
-            struct_def,
-            ast_util::empty_generics()
-        )
-    }
-
-    fn item_struct_poly(
-        &self,
-        name: ident,
-        span: span,
-        struct_def: ast::struct_def,
-        generics: Generics
-    ) -> @ast::item {
-        self.item(name, span, ast::item_struct(@struct_def, generics))
-    }
-
-    fn struct_expr(&self, path: @ast::Path,
-                   fields: ~[ast::field]) -> @ast::expr {
-        @ast::expr {
-            id: self.next_id(),
-            callee_id: self.next_id(),
-            node: ast::expr_struct(path, fields, None),
-            span: dummy_sp()
-        }
-    }
-
-    fn variant(&self, name: ident, span: span,
-               tys: ~[@ast::Ty]) -> ast::variant {
-        let args = do tys.map |ty| {
-            ast::variant_arg { ty: *ty, id: self.next_id() }
-        };
-
-        spanned {
-            node: ast::variant_ {
-                name: name,
-                attrs: ~[],
-                kind: ast::tuple_variant_kind(args),
-                id: self.next_id(),
-                disr_expr: None,
-                vis: ast::public
-            },
-            span: span,
-        }
-    }
-
-    fn item_mod(&self, name: ident, span: span,
-                items: ~[@ast::item]) -> @ast::item {
-
-        // XXX: Total hack: import `core::kinds::Owned` to work around a
-        // parser bug whereby `fn f<T:::kinds::Owned>` doesn't parse.
-        let vi = ast::view_item_use(~[
-            @codemap::spanned {
-                node: ast::view_path_simple(
-                    self.ident_of("Owned"),
-                    path(
-                        ~[
-                            self.ident_of("core"),
-                            self.ident_of("kinds"),
-                            self.ident_of("Owned")
-                        ],
-                        codemap::dummy_sp()
-                    ),
-                    self.next_id()
-                ),
-                span: codemap::dummy_sp()
-            }
-        ]);
-        let vi = @ast::view_item {
-            node: vi,
-            attrs: ~[],
-            vis: ast::private,
-            span: codemap::dummy_sp()
-        };
-
-        self.item(
-            name,
-            span,
-            ast::item_mod(ast::_mod {
-                view_items: ~[vi],
-                items: items,
-            })
-        )
-    }
-
-    fn ty_path_ast_builder(&self, path: @ast::Path) -> @ast::Ty {
-        @ast::Ty {
-            id: self.next_id(),
-            node: ast::ty_path(path, self.next_id()),
-            span: path.span,
-        }
-    }
-
-    fn ty_nil_ast_builder(&self) -> @ast::Ty {
-        @ast::Ty {
-            id: self.next_id(),
-            node: ast::ty_nil,
-            span: dummy_sp(),
-        }
-    }
-
-    fn strip_bounds(&self, generics: &Generics) -> Generics {
-        let no_bounds = @opt_vec::Empty;
-        let new_params = do generics.ty_params.map |ty_param| {
-            ast::TyParam { bounds: no_bounds, ..copy *ty_param }
-        };
-        Generics {
-            ty_params: new_params,
-            .. copy *generics
-        }
-    }
-
-    fn item_ty_poly(&self, name: ident, span: span, ty: @ast::Ty,
-                    generics: Generics) -> @ast::item {
-        self.item(name, span, ast::item_ty(ty, generics))
-    }
-
-    fn item_ty(&self, name: ident, span: span, ty: @ast::Ty) -> @ast::item {
-        self.item_ty_poly(name, span, ty, ast_util::empty_generics())
-    }
-
-    fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
-        opt_vec::take_vec(
-            ty_params.map(|p| self.ty_path_ast_builder(
-                path(~[p.ident], dummy_sp()))))
-    }
-
-    fn ty_vars_global(&self,
-                      ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] {
-        opt_vec::take_vec(
-            ty_params.map(|p| self.ty_path_ast_builder(
-                path(~[p.ident], dummy_sp()))))
-    }
-}
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index 83b3572c85f..43626993783 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -13,7 +13,8 @@
 use ast;
 use codemap::{dummy_sp, spanned};
 use ext::base::ExtCtxt;
-use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path};
+use ext::build::AstBuilder;
+use ext::pipes::ast_builder::{append_types, path};
 use ext::pipes::ast_builder::{path_global};
 use ext::pipes::proto::*;
 use ext::quote::rt::*;
@@ -54,7 +55,7 @@ impl gen_send for message {
             let arg_names = tys.mapi(|i, _ty| cx.ident_of(~"x_"+i.to_str()));
             let args_ast = vec::map_zip(arg_names, *tys, |n, t| cx.arg(*n, *t));
 
-            let pipe_ty = cx.ty_path_ast_builder(
+            let pipe_ty = cx.ty_path(
                 path(~[this.data_name()], span)
                 .add_tys(cx.ty_vars_global(&this.generics.ty_params)));
             let args_ast = vec::append(
@@ -111,7 +112,7 @@ impl gen_send for message {
 
             let body = cx.parse_expr(body);
 
-            let mut rty = cx.ty_path_ast_builder(path(~[next.data_name()],
+            let mut rty = cx.ty_path(path(~[next.data_name()],
                                                       span)
                                                .add_tys(copy next_state.tys));
             if try {
@@ -124,7 +125,7 @@ impl gen_send for message {
                             args_ast,
                             rty,
                             self.get_generics(),
-                            cx.expr_block(body))
+                            cx.blk_expr(body))
           }
 
             message(ref _id, span, ref tys, this, None) => {
@@ -137,7 +138,7 @@ impl gen_send for message {
 
                 let args_ast = vec::append(
                     ~[cx.arg(cx.ident_of("pipe"),
-                             cx.ty_path_ast_builder(
+                             cx.ty_path(
                                  path(~[this.data_name()], span)
                                  .add_tys(cx.ty_vars_global(
                                      &this.generics.ty_params))))],
@@ -179,13 +180,13 @@ impl gen_send for message {
                                     cx.ty_nil_ast_builder()
                                 },
                                 self.get_generics(),
-                                cx.expr_block(body))
+                                cx.blk_expr(body))
             }
           }
         }
 
     fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty {
-        cx.ty_path_ast_builder(path(~[cx.ident_of(self.name())], self.span())
+        cx.ty_path(path(~[cx.ident_of(self.name())], self.span())
           .add_tys(cx.ty_vars_global(&self.get_generics().ty_params)))
     }
 }
@@ -217,7 +218,7 @@ impl to_type_decls for state {
                 };
 
                 vec::append_one(tys,
-                                cx.ty_path_ast_builder(
+                                cx.ty_path(
                                     path(~[cx.ident_of(dir),
                                            cx.ident_of(next_name)], span)
                                     .add_tys(copy next_state.tys)))
@@ -264,12 +265,12 @@ impl to_type_decls for state {
                 cx.item_ty_poly(
                     self.data_name(),
                     self.span,
-                    cx.ty_path_ast_builder(
+                    cx.ty_path(
                         path_global(~[cx.ident_of("core"),
                                       cx.ident_of("pipes"),
                                       cx.ident_of(dir.to_str() + "Packet")],
                              dummy_sp())
-                        .add_ty(cx.ty_path_ast_builder(
+                        .add_ty(cx.ty_path(
                             path(~[cx.ident_of("super"),
                                    self.data_name()],
                                  dummy_sp())
@@ -282,13 +283,13 @@ impl to_type_decls for state {
                 cx.item_ty_poly(
                     self.data_name(),
                     self.span,
-                    cx.ty_path_ast_builder(
+                    cx.ty_path(
                         path_global(~[cx.ident_of("core"),
                                       cx.ident_of("pipes"),
                                       cx.ident_of(dir.to_str()
                                                   + "PacketBuffered")],
                              dummy_sp())
-                        .add_tys(~[cx.ty_path_ast_builder(
+                        .add_tys(~[cx.ty_path(
                             path(~[cx.ident_of("super"),
                                    self.data_name()],
                                         dummy_sp())
@@ -341,7 +342,7 @@ impl gen_init for protocol {
     }
 
     fn gen_buffer_init(&self, ext_cx: @ExtCtxt) -> @ast::expr {
-        ext_cx.struct_expr(path(~[ext_cx.ident_of("__Buffer")],
+        ext_cx.expr_struct(path(~[ext_cx.ident_of("__Buffer")],
                                 dummy_sp()),
                       self.states.map_to_vec(|s| {
             let fty = s.to_ty(ext_cx);
@@ -360,15 +361,16 @@ impl gen_init for protocol {
             data: $buffer_fields,
         });
 
-        let entangle_body = ext_cx.block_expr(
-            ext_cx.block(
+        let entangle_body = ext_cx.expr_blk(
+            ext_cx.blk(
+                dummy_sp(),
                 self.states.map_to_vec(
                     |s| ext_cx.parse_stmt(
                         fmt!("data.%s.set_buffer(buffer)",
                              s.name))),
-                ext_cx.parse_expr(fmt!(
+                Some(ext_cx.parse_expr(fmt!(
                     "::core::ptr::to_mut_unsafe_ptr(&mut (data.%s))",
-                    self.states[0].name))));
+                    self.states[0].name)))));
 
         quote_expr!({
             let buffer = $buffer;
@@ -389,7 +391,7 @@ impl gen_init for protocol {
             }
         }
 
-        cx.ty_path_ast_builder(path(~[cx.ident_of("super"),
+        cx.ty_path(path(~[cx.ident_of("super"),
                                       cx.ident_of("__Buffer")],
                                     copy self.span)
                                .add_tys(cx.ty_vars_global(&params)))
diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs
index 12a0a0a24d6..4471c5bb9b8 100644
--- a/src/libsyntax/ext/pipes/proto.rs
+++ b/src/libsyntax/ext/pipes/proto.rs
@@ -11,7 +11,8 @@
 use ast;
 use codemap::span;
 use ext::base::ExtCtxt;
-use ext::pipes::ast_builder::{append_types, ext_ctxt_ast_builder, path};
+use ext::build::AstBuilder;
+use ext::pipes::ast_builder::{append_types, path};
 
 #[deriving(Eq)]
 pub enum direction { send, recv }
@@ -93,7 +94,7 @@ pub impl state_ {
 
     /// Returns the type that is used for the messages.
     fn to_ty(&self, cx: @ExtCtxt) -> @ast::Ty {
-        cx.ty_path_ast_builder
+        cx.ty_path
             (path(~[cx.ident_of(self.name)],self.span).add_tys(
                 cx.ty_vars(&self.generics.ty_params)))
     }