]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/build.rs
auto merge of #10226 : nibrahim/rust/docepub, r=alexcrichton
[rust.git] / src / libsyntax / ext / build.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use abi::AbiSet;
12 use ast::Ident;
13 use ast;
14 use ast_util;
15 use codemap::{Span, respan, dummy_sp};
16 use ext::base::ExtCtxt;
17 use ext::quote::rt::*;
18 use fold;
19 use opt_vec;
20 use opt_vec::OptVec;
21
22 pub struct Field {
23     ident: ast::Ident,
24     ex: @ast::Expr
25 }
26
27 // Transitional reexports so qquote can find the paths it is looking for
28 mod syntax {
29     pub use ext;
30     pub use parse;
31 }
32
33 pub trait AstBuilder {
34     // paths
35     fn path(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path;
36     fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path;
37     fn path_global(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path;
38     fn path_all(&self, sp: Span,
39                 global: bool,
40                 idents: ~[ast::Ident],
41                 lifetimes: OptVec<ast::Lifetime>,
42                 types: ~[ast::Ty])
43         -> ast::Path;
44
45     // types
46     fn ty_mt(&self, ty: ast::Ty, mutbl: ast::Mutability) -> ast::mt;
47
48     fn ty(&self, span: Span, ty: ast::ty_) -> ast::Ty;
49     fn ty_path(&self, ast::Path, Option<OptVec<ast::TyParamBound>>) -> ast::Ty;
50     fn ty_ident(&self, span: Span, idents: ast::Ident) -> ast::Ty;
51
52     fn ty_rptr(&self, span: Span,
53                ty: ast::Ty,
54                lifetime: Option<ast::Lifetime>,
55                mutbl: ast::Mutability) -> ast::Ty;
56     fn ty_uniq(&self, span: Span, ty: ast::Ty) -> ast::Ty;
57     fn ty_box(&self, span: Span, ty: ast::Ty, mutbl: ast::Mutability) -> ast::Ty;
58
59     fn ty_option(&self, ty: ast::Ty) -> ast::Ty;
60     fn ty_infer(&self, sp: Span) -> ast::Ty;
61     fn ty_nil(&self) -> ast::Ty;
62
63     fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[ast::Ty];
64     fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[ast::Ty];
65     fn ty_field_imm(&self, span: Span, name: Ident, ty: ast::Ty) -> ast::TypeField;
66     fn strip_bounds(&self, bounds: &Generics) -> Generics;
67
68     fn typaram(&self, id: ast::Ident, bounds: OptVec<ast::TyParamBound>) -> ast::TyParam;
69
70     fn trait_ref(&self, path: ast::Path) -> ast::trait_ref;
71     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
72     fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime;
73
74     // statements
75     fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt;
76     fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt;
77     fn stmt_let_typed(&self,
78                       sp: Span,
79                       mutbl: bool,
80                       ident: ast::Ident,
81                       typ: ast::Ty,
82                       ex: @ast::Expr)
83                       -> @ast::Stmt;
84
85     // blocks
86     fn block(&self, span: Span, stmts: ~[@ast::Stmt], expr: Option<@ast::Expr>) -> ast::Block;
87     fn block_expr(&self, expr: @ast::Expr) -> ast::Block;
88     fn block_all(&self, span: Span,
89                  view_items: ~[ast::view_item],
90                  stmts: ~[@ast::Stmt],
91                  expr: Option<@ast::Expr>) -> ast::Block;
92
93     // expressions
94     fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr;
95     fn expr_path(&self, path: ast::Path) -> @ast::Expr;
96     fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr;
97
98     fn expr_self(&self, span: Span) -> @ast::Expr;
99     fn expr_binary(&self, sp: Span, op: ast::BinOp,
100                    lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr;
101     fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
102     fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr) -> @ast::Expr;
103
104     fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
105     fn expr_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
106     fn expr_mut_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr;
107     fn expr_field_access(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr;
108     fn expr_call(&self, span: Span, expr: @ast::Expr, args: ~[@ast::Expr]) -> @ast::Expr;
109     fn expr_call_ident(&self, span: Span, id: ast::Ident, args: ~[@ast::Expr]) -> @ast::Expr;
110     fn expr_call_global(&self, sp: Span, fn_path: ~[ast::Ident],
111                         args: ~[@ast::Expr]) -> @ast::Expr;
112     fn expr_method_call(&self, span: Span,
113                         expr: @ast::Expr, ident: ast::Ident,
114                         args: ~[@ast::Expr]) -> @ast::Expr;
115     fn expr_block(&self, b: ast::Block) -> @ast::Expr;
116     fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: ast::Ty) -> @ast::Expr;
117
118     fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field;
119     fn expr_struct(&self, span: Span, path: ast::Path, fields: ~[ast::Field]) -> @ast::Expr;
120     fn expr_struct_ident(&self, span: Span, id: ast::Ident, fields: ~[ast::Field]) -> @ast::Expr;
121
122     fn expr_lit(&self, sp: Span, lit: ast::lit_) -> @ast::Expr;
123
124     fn expr_uint(&self, span: Span, i: uint) -> @ast::Expr;
125     fn expr_int(&self, sp: Span, i: int) -> @ast::Expr;
126     fn expr_u8(&self, sp: Span, u: u8) -> @ast::Expr;
127     fn expr_bool(&self, sp: Span, value: bool) -> @ast::Expr;
128
129     fn expr_vstore(&self, sp: Span, expr: @ast::Expr, vst: ast::ExprVstore) -> @ast::Expr;
130     fn expr_vec(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr;
131     fn expr_vec_uniq(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr;
132     fn expr_vec_slice(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr;
133     fn expr_str(&self, sp: Span, s: @str) -> @ast::Expr;
134     fn expr_str_uniq(&self, sp: Span, s: @str) -> @ast::Expr;
135
136     fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr;
137     fn expr_none(&self, sp: Span) -> @ast::Expr;
138
139     fn expr_fail(&self, span: Span, msg: @str) -> @ast::Expr;
140     fn expr_unreachable(&self, span: Span) -> @ast::Expr;
141
142     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat;
143     fn pat_wild(&self, span: Span) -> @ast::Pat;
144     fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat;
145     fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat;
146
147     fn pat_ident_binding_mode(&self,
148                               span: Span,
149                               ident: ast::Ident,
150                               bm: ast::BindingMode) -> @ast::Pat;
151     fn pat_enum(&self, span: Span, path: ast::Path, subpats: ~[@ast::Pat]) -> @ast::Pat;
152     fn pat_struct(&self, span: Span,
153                   path: ast::Path, field_pats: ~[ast::FieldPat]) -> @ast::Pat;
154
155     fn arm(&self, span: Span, pats: ~[@ast::Pat], expr: @ast::Expr) -> ast::Arm;
156     fn arm_unreachable(&self, span: Span) -> ast::Arm;
157
158     fn expr_match(&self, span: Span, arg: @ast::Expr, arms: ~[ast::Arm]) -> @ast::Expr;
159     fn expr_if(&self, span: Span,
160                cond: @ast::Expr, then: @ast::Expr, els: Option<@ast::Expr>) -> @ast::Expr;
161
162     fn lambda_fn_decl(&self, span: Span, fn_decl: ast::fn_decl, blk: ast::Block) -> @ast::Expr;
163
164     fn lambda(&self, span: Span, ids: ~[ast::Ident], blk: ast::Block) -> @ast::Expr;
165     fn lambda0(&self, span: Span, blk: ast::Block) -> @ast::Expr;
166     fn lambda1(&self, span: Span, blk: ast::Block, ident: ast::Ident) -> @ast::Expr;
167
168     fn lambda_expr(&self, span: Span, ids: ~[ast::Ident], blk: @ast::Expr) -> @ast::Expr;
169     fn lambda_expr_0(&self, span: Span, expr: @ast::Expr) -> @ast::Expr;
170     fn lambda_expr_1(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr;
171
172     fn lambda_stmts(&self, span: Span, ids: ~[ast::Ident], blk: ~[@ast::Stmt]) -> @ast::Expr;
173     fn lambda_stmts_0(&self, span: Span, stmts: ~[@ast::Stmt]) -> @ast::Expr;
174     fn lambda_stmts_1(&self, span: Span, stmts: ~[@ast::Stmt], ident: ast::Ident) -> @ast::Expr;
175
176     // items
177     fn item(&self, span: Span,
178             name: Ident, attrs: ~[ast::Attribute], node: ast::item_) -> @ast::item;
179
180     fn arg(&self, span: Span, name: Ident, ty: ast::Ty) -> ast::arg;
181     // XXX unused self
182     fn fn_decl(&self, inputs: ~[ast::arg], output: ast::Ty) -> ast::fn_decl;
183
184     fn item_fn_poly(&self,
185                     span: Span,
186                     name: Ident,
187                     inputs: ~[ast::arg],
188                     output: ast::Ty,
189                     generics: Generics,
190                     body: ast::Block) -> @ast::item;
191     fn item_fn(&self,
192                span: Span,
193                name: Ident,
194                inputs: ~[ast::arg],
195                output: ast::Ty,
196                body: ast::Block) -> @ast::item;
197
198     fn variant(&self, span: Span, name: Ident, tys: ~[ast::Ty]) -> ast::variant;
199     fn item_enum_poly(&self,
200                       span: Span,
201                       name: Ident,
202                       enum_definition: ast::enum_def,
203                       generics: Generics) -> @ast::item;
204     fn item_enum(&self, span: Span, name: Ident, enum_def: ast::enum_def) -> @ast::item;
205
206     fn item_struct_poly(&self,
207                         span: Span,
208                         name: Ident,
209                         struct_def: ast::struct_def,
210                         generics: Generics) -> @ast::item;
211     fn item_struct(&self, span: Span, name: Ident, struct_def: ast::struct_def) -> @ast::item;
212
213     fn item_mod(&self, span: Span,
214                 name: Ident, attrs: ~[ast::Attribute],
215                 vi: ~[ast::view_item], items: ~[@ast::item]) -> @ast::item;
216
217     fn item_ty_poly(&self,
218                     span: Span,
219                     name: Ident,
220                     ty: ast::Ty,
221                     generics: Generics) -> @ast::item;
222     fn item_ty(&self, span: Span, name: Ident, ty: ast::Ty) -> @ast::item;
223
224     fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute;
225
226     fn meta_word(&self, sp: Span, w: @str) -> @ast::MetaItem;
227     fn meta_list(&self, sp: Span, name: @str, mis: ~[@ast::MetaItem]) -> @ast::MetaItem;
228     fn meta_name_value(&self, sp: Span, name: @str, value: ast::lit_) -> @ast::MetaItem;
229
230     fn view_use(&self, sp: Span,
231                 vis: ast::visibility, vp: ~[@ast::view_path]) -> ast::view_item;
232     fn view_use_list(&self, sp: Span, vis: ast::visibility,
233                      path: ~[ast::Ident], imports: &[ast::Ident]) -> ast::view_item;
234     fn view_use_glob(&self, sp: Span,
235                      vis: ast::visibility, path: ~[ast::Ident]) -> ast::view_item;
236 }
237
238 impl AstBuilder for @ExtCtxt {
239     fn path(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path {
240         self.path_all(span, false, strs, opt_vec::Empty, ~[])
241     }
242     fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
243         self.path(span, ~[id])
244     }
245     fn path_global(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path {
246         self.path_all(span, true, strs, opt_vec::Empty, ~[])
247     }
248     fn path_all(&self,
249                 sp: Span,
250                 global: bool,
251                 mut idents: ~[ast::Ident],
252                 lifetimes: OptVec<ast::Lifetime>,
253                 types: ~[ast::Ty])
254                 -> ast::Path {
255         let last_identifier = idents.pop();
256         let mut segments: ~[ast::PathSegment] = idents.move_iter()
257                                                       .map(|ident| {
258             ast::PathSegment {
259                 identifier: ident,
260                 lifetimes: opt_vec::Empty,
261                 types: opt_vec::Empty,
262             }
263         }).collect();
264         segments.push(ast::PathSegment {
265             identifier: last_identifier,
266             lifetimes: lifetimes,
267             types: opt_vec::from(types),
268         });
269         ast::Path {
270             span: sp,
271             global: global,
272             segments: segments,
273         }
274     }
275
276     fn ty_mt(&self, ty: ast::Ty, mutbl: ast::Mutability) -> ast::mt {
277         ast::mt {
278             ty: ~ty,
279             mutbl: mutbl
280         }
281     }
282
283     fn ty(&self, span: Span, ty: ast::ty_) -> ast::Ty {
284         ast::Ty {
285             id: ast::DUMMY_NODE_ID,
286             span: span,
287             node: ty
288         }
289     }
290
291     fn ty_path(&self, path: ast::Path, bounds: Option<OptVec<ast::TyParamBound>>)
292               -> ast::Ty {
293         self.ty(path.span,
294                 ast::ty_path(path, bounds, ast::DUMMY_NODE_ID))
295     }
296
297     // Might need to take bounds as an argument in the future, if you ever want
298     // to generate a bounded existential trait type.
299     fn ty_ident(&self, span: Span, ident: ast::Ident)
300         -> ast::Ty {
301         self.ty_path(self.path_ident(span, ident), None)
302     }
303
304     fn ty_rptr(&self,
305                span: Span,
306                ty: ast::Ty,
307                lifetime: Option<ast::Lifetime>,
308                mutbl: ast::Mutability)
309         -> ast::Ty {
310         self.ty(span,
311                 ast::ty_rptr(lifetime, self.ty_mt(ty, mutbl)))
312     }
313     fn ty_uniq(&self, span: Span, ty: ast::Ty) -> ast::Ty {
314         self.ty(span, ast::ty_uniq(self.ty_mt(ty, ast::MutImmutable)))
315     }
316     fn ty_box(&self, span: Span,
317                  ty: ast::Ty, mutbl: ast::Mutability) -> ast::Ty {
318         self.ty(span, ast::ty_box(self.ty_mt(ty, mutbl)))
319     }
320
321     fn ty_option(&self, ty: ast::Ty) -> ast::Ty {
322         self.ty_path(
323             self.path_all(dummy_sp(),
324                           true,
325                           ~[
326                               self.ident_of("std"),
327                               self.ident_of("option"),
328                               self.ident_of("Option")
329                           ],
330                           opt_vec::Empty,
331                           ~[ ty ]), None)
332     }
333
334     fn ty_field_imm(&self, span: Span, name: Ident, ty: ast::Ty) -> ast::TypeField {
335         ast::TypeField {
336             ident: name,
337             mt: ast::mt { ty: ~ty, mutbl: ast::MutImmutable },
338             span: span,
339         }
340     }
341
342     fn ty_infer(&self, span: Span) -> ast::Ty {
343         self.ty(span, ast::ty_infer)
344     }
345
346     fn ty_nil(&self) -> ast::Ty {
347         ast::Ty {
348             id: ast::DUMMY_NODE_ID,
349             node: ast::ty_nil,
350             span: dummy_sp(),
351         }
352     }
353
354     fn typaram(&self, id: ast::Ident, bounds: OptVec<ast::TyParamBound>) -> ast::TyParam {
355         ast::TyParam { ident: id, id: ast::DUMMY_NODE_ID, bounds: bounds }
356     }
357
358     // these are strange, and probably shouldn't be used outside of
359     // pipes. Specifically, the global version possible generates
360     // incorrect code.
361     fn ty_vars(&self, ty_params: &OptVec<ast::TyParam>) -> ~[ast::Ty] {
362         opt_vec::take_vec(
363             ty_params.map(|p| self.ty_ident(dummy_sp(), p.ident)))
364     }
365
366     fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[ast::Ty] {
367         opt_vec::take_vec(
368             ty_params.map(|p| self.ty_path(
369                 self.path_global(dummy_sp(), ~[p.ident]), None)))
370     }
371
372     fn strip_bounds(&self, generics: &Generics) -> Generics {
373         let new_params = do generics.ty_params.map |ty_param| {
374             ast::TyParam { bounds: opt_vec::Empty, ..*ty_param }
375         };
376         Generics {
377             ty_params: new_params,
378             .. (*generics).clone()
379         }
380     }
381
382     fn trait_ref(&self, path: ast::Path) -> ast::trait_ref {
383         ast::trait_ref {
384             path: path,
385             ref_id: ast::DUMMY_NODE_ID
386         }
387     }
388
389     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
390         ast::TraitTyParamBound(self.trait_ref(path))
391     }
392
393     fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
394         ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, ident: ident }
395     }
396
397     fn stmt_expr(&self, expr: @ast::Expr) -> @ast::Stmt {
398         @respan(expr.span, ast::StmtSemi(expr, ast::DUMMY_NODE_ID))
399     }
400
401     fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: @ast::Expr) -> @ast::Stmt {
402         let pat = if mutbl {
403             self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
404         } else {
405             self.pat_ident(sp, ident)
406         };
407         let local = @ast::Local {
408             ty: self.ty_infer(sp),
409             pat: pat,
410             init: Some(ex),
411             id: ast::DUMMY_NODE_ID,
412             span: sp,
413         };
414         let decl = respan(sp, ast::DeclLocal(local));
415         @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
416     }
417
418     fn stmt_let_typed(&self,
419                       sp: Span,
420                       mutbl: bool,
421                       ident: ast::Ident,
422                       typ: ast::Ty,
423                       ex: @ast::Expr)
424                       -> @ast::Stmt {
425         let pat = if mutbl {
426             self.pat_ident_binding_mode(sp, ident, ast::BindByValue(ast::MutMutable))
427         } else {
428             self.pat_ident(sp, ident)
429         };
430         let local = @ast::Local {
431             ty: typ,
432             pat: pat,
433             init: Some(ex),
434             id: ast::DUMMY_NODE_ID,
435             span: sp,
436         };
437         let decl = respan(sp, ast::DeclLocal(local));
438         @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
439     }
440
441     fn block(&self, span: Span, stmts: ~[@ast::Stmt], expr: Option<@Expr>) -> ast::Block {
442         self.block_all(span, ~[], stmts, expr)
443     }
444
445     fn block_expr(&self, expr: @ast::Expr) -> ast::Block {
446         self.block_all(expr.span, ~[], ~[], Some(expr))
447     }
448     fn block_all(&self,
449                  span: Span,
450                  view_items: ~[ast::view_item],
451                  stmts: ~[@ast::Stmt],
452                  expr: Option<@ast::Expr>) -> ast::Block {
453            ast::Block {
454                view_items: view_items,
455                stmts: stmts,
456                expr: expr,
457                id: ast::DUMMY_NODE_ID,
458                rules: ast::DefaultBlock,
459                span: span,
460            }
461     }
462
463     fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr {
464         @ast::Expr {
465             id: ast::DUMMY_NODE_ID,
466             node: node,
467             span: span,
468         }
469     }
470
471     fn expr_path(&self, path: ast::Path) -> @ast::Expr {
472         self.expr(path.span, ast::ExprPath(path))
473     }
474
475     fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr {
476         self.expr_path(self.path_ident(span, id))
477     }
478     fn expr_self(&self, span: Span) -> @ast::Expr {
479         self.expr(span, ast::ExprSelf)
480     }
481
482     fn expr_binary(&self, sp: Span, op: ast::BinOp,
483                    lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
484         self.expr(sp, ast::ExprBinary(ast::DUMMY_NODE_ID, op, lhs, rhs))
485     }
486
487     fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
488         self.expr_unary(sp, ast::UnDeref, e)
489     }
490     fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr)
491         -> @ast::Expr {
492         self.expr(sp, ast::ExprUnary(ast::DUMMY_NODE_ID, op, e))
493     }
494
495     fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
496         self.expr_unary(sp, ast::UnBox(ast::MutImmutable), e)
497     }
498
499     fn expr_field_access(&self, sp: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
500         self.expr(sp, ast::ExprField(expr, ident, ~[]))
501     }
502     fn expr_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
503         self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e))
504     }
505     fn expr_mut_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
506         self.expr(sp, ast::ExprAddrOf(ast::MutMutable, e))
507     }
508
509     fn expr_call(&self, span: Span, expr: @ast::Expr, args: ~[@ast::Expr]) -> @ast::Expr {
510         self.expr(span, ast::ExprCall(expr, args, ast::NoSugar))
511     }
512     fn expr_call_ident(&self, span: Span, id: ast::Ident, args: ~[@ast::Expr]) -> @ast::Expr {
513         self.expr(span,
514                   ast::ExprCall(self.expr_ident(span, id), args, ast::NoSugar))
515     }
516     fn expr_call_global(&self, sp: Span, fn_path: ~[ast::Ident],
517                       args: ~[@ast::Expr]) -> @ast::Expr {
518         let pathexpr = self.expr_path(self.path_global(sp, fn_path));
519         self.expr_call(sp, pathexpr, args)
520     }
521     fn expr_method_call(&self, span: Span,
522                         expr: @ast::Expr,
523                         ident: ast::Ident,
524                         args: ~[@ast::Expr]) -> @ast::Expr {
525         self.expr(span,
526                   ast::ExprMethodCall(ast::DUMMY_NODE_ID, expr, ident, ~[], args, ast::NoSugar))
527     }
528     fn expr_block(&self, b: ast::Block) -> @ast::Expr {
529         self.expr(b.span, ast::ExprBlock(b))
530     }
531     fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field {
532         ast::Field { ident: respan(span, name), expr: e, span: span }
533     }
534     fn expr_struct(&self, span: Span, path: ast::Path, fields: ~[ast::Field]) -> @ast::Expr {
535         self.expr(span, ast::ExprStruct(path, fields, None))
536     }
537     fn expr_struct_ident(&self, span: Span,
538                          id: ast::Ident, fields: ~[ast::Field]) -> @ast::Expr {
539         self.expr_struct(span, self.path_ident(span, id), fields)
540     }
541
542     fn expr_lit(&self, sp: Span, lit: ast::lit_) -> @ast::Expr {
543         self.expr(sp, ast::ExprLit(@respan(sp, lit)))
544     }
545     fn expr_uint(&self, span: Span, i: uint) -> @ast::Expr {
546         self.expr_lit(span, ast::lit_uint(i as u64, ast::ty_u))
547     }
548     fn expr_int(&self, sp: Span, i: int) -> @ast::Expr {
549         self.expr_lit(sp, ast::lit_int(i as i64, ast::ty_i))
550     }
551     fn expr_u8(&self, sp: Span, u: u8) -> @ast::Expr {
552         self.expr_lit(sp, ast::lit_uint(u as u64, ast::ty_u8))
553     }
554     fn expr_bool(&self, sp: Span, value: bool) -> @ast::Expr {
555         self.expr_lit(sp, ast::lit_bool(value))
556     }
557
558     fn expr_vstore(&self, sp: Span, expr: @ast::Expr, vst: ast::ExprVstore) -> @ast::Expr {
559         self.expr(sp, ast::ExprVstore(expr, vst))
560     }
561     fn expr_vec(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
562         self.expr(sp, ast::ExprVec(exprs, ast::MutImmutable))
563     }
564     fn expr_vec_uniq(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
565         self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreUniq)
566     }
567     fn expr_vec_slice(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
568         self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreSlice)
569     }
570     fn expr_str(&self, sp: Span, s: @str) -> @ast::Expr {
571         self.expr_lit(sp, ast::lit_str(s, ast::CookedStr))
572     }
573     fn expr_str_uniq(&self, sp: Span, s: @str) -> @ast::Expr {
574         self.expr_vstore(sp, self.expr_str(sp, s), ast::ExprVstoreUniq)
575     }
576
577
578     fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: ast::Ty) -> @ast::Expr {
579         self.expr(sp, ast::ExprCast(expr, ty))
580     }
581
582
583     fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
584         let some = ~[
585             self.ident_of("std"),
586             self.ident_of("option"),
587             self.ident_of("Some"),
588         ];
589         self.expr_call_global(sp, some, ~[expr])
590     }
591
592     fn expr_none(&self, sp: Span) -> @ast::Expr {
593         let none = self.path_global(sp, ~[
594             self.ident_of("std"),
595             self.ident_of("option"),
596             self.ident_of("None"),
597         ]);
598         self.expr_path(none)
599     }
600
601     fn expr_fail(&self, span: Span, msg: @str) -> @ast::Expr {
602         let loc = self.codemap().lookup_char_pos(span.lo);
603         self.expr_call_global(
604             span,
605             ~[
606                 self.ident_of("std"),
607                 self.ident_of("rt"),
608                 self.ident_of("task"),
609                 self.ident_of("begin_unwind"),
610             ],
611             ~[
612                 self.expr_str(span, msg),
613                 self.expr_str(span, loc.file.name),
614                 self.expr_uint(span, loc.line),
615             ])
616     }
617
618     fn expr_unreachable(&self, span: Span) -> @ast::Expr {
619         self.expr_fail(span, @"internal error: entered unreachable code")
620     }
621
622
623     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
624         @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
625     }
626     fn pat_wild(&self, span: Span) -> @ast::Pat {
627         self.pat(span, ast::PatWild)
628     }
629     fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat {
630         self.pat(span, ast::PatLit(expr))
631     }
632     fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat {
633         self.pat_ident_binding_mode(span, ident, ast::BindByValue(ast::MutImmutable))
634     }
635
636     fn pat_ident_binding_mode(&self,
637                               span: Span,
638                               ident: ast::Ident,
639                               bm: ast::BindingMode) -> @ast::Pat {
640         let path = self.path_ident(span, ident);
641         let pat = ast::PatIdent(bm, path, None);
642         self.pat(span, pat)
643     }
644     fn pat_enum(&self, span: Span, path: ast::Path, subpats: ~[@ast::Pat]) -> @ast::Pat {
645         let pat = ast::PatEnum(path, Some(subpats));
646         self.pat(span, pat)
647     }
648     fn pat_struct(&self, span: Span,
649                   path: ast::Path, field_pats: ~[ast::FieldPat]) -> @ast::Pat {
650         let pat = ast::PatStruct(path, field_pats, false);
651         self.pat(span, pat)
652     }
653
654     fn arm(&self, _span: Span, pats: ~[@ast::Pat], expr: @ast::Expr) -> ast::Arm {
655         ast::Arm {
656             pats: pats,
657             guard: None,
658             body: self.block_expr(expr)
659         }
660     }
661
662     fn arm_unreachable(&self, span: Span) -> ast::Arm {
663         self.arm(span, ~[self.pat_wild(span)], self.expr_unreachable(span))
664     }
665
666     fn expr_match(&self, span: Span, arg: @ast::Expr, arms: ~[ast::Arm]) -> @Expr {
667         self.expr(span, ast::ExprMatch(arg, arms))
668     }
669
670     fn expr_if(&self, span: Span,
671                cond: @ast::Expr, then: @ast::Expr, els: Option<@ast::Expr>) -> @ast::Expr {
672         let els = els.map(|x| self.expr_block(self.block_expr(x)));
673         self.expr(span, ast::ExprIf(cond, self.block_expr(then), els))
674     }
675
676     fn lambda_fn_decl(&self, span: Span, fn_decl: ast::fn_decl, blk: ast::Block) -> @ast::Expr {
677         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
678     }
679     fn lambda(&self, span: Span, ids: ~[ast::Ident], blk: ast::Block) -> @ast::Expr {
680         let fn_decl = self.fn_decl(
681             ids.map(|id| self.arg(span, *id, self.ty_infer(span))),
682             self.ty_infer(span));
683
684         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
685     }
686     fn lambda0(&self, _span: Span, blk: ast::Block) -> @ast::Expr {
687         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
688         quote_expr!(*self, || $blk_e )
689     }
690
691     fn lambda1(&self, _span: Span, blk: ast::Block, ident: ast::Ident) -> @ast::Expr {
692         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
693         quote_expr!(*self, |$ident| $blk_e )
694     }
695
696     fn lambda_expr(&self, span: Span, ids: ~[ast::Ident], expr: @ast::Expr) -> @ast::Expr {
697         self.lambda(span, ids, self.block_expr(expr))
698     }
699     fn lambda_expr_0(&self, span: Span, expr: @ast::Expr) -> @ast::Expr {
700         self.lambda0(span, self.block_expr(expr))
701     }
702     fn lambda_expr_1(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
703         self.lambda1(span, self.block_expr(expr), ident)
704     }
705
706     fn lambda_stmts(&self, span: Span, ids: ~[ast::Ident], stmts: ~[@ast::Stmt]) -> @ast::Expr {
707         self.lambda(span, ids, self.block(span, stmts, None))
708     }
709     fn lambda_stmts_0(&self, span: Span, stmts: ~[@ast::Stmt]) -> @ast::Expr {
710         self.lambda0(span, self.block(span, stmts, None))
711     }
712     fn lambda_stmts_1(&self, span: Span, stmts: ~[@ast::Stmt], ident: ast::Ident) -> @ast::Expr {
713         self.lambda1(span, self.block(span, stmts, None), ident)
714     }
715
716     fn arg(&self, span: Span, ident: ast::Ident, ty: ast::Ty) -> ast::arg {
717         let arg_pat = self.pat_ident(span, ident);
718         ast::arg {
719             ty: ty,
720             pat: arg_pat,
721             id: ast::DUMMY_NODE_ID
722         }
723     }
724
725     // XXX unused self
726     fn fn_decl(&self, inputs: ~[ast::arg], output: ast::Ty) -> ast::fn_decl {
727         ast::fn_decl {
728             inputs: inputs,
729             output: output,
730             cf: ast::return_val,
731             variadic: false
732         }
733     }
734
735     fn item(&self, span: Span,
736             name: Ident, attrs: ~[ast::Attribute], node: ast::item_) -> @ast::item {
737         // XXX: Would be nice if our generated code didn't violate
738         // Rust coding conventions
739         @ast::item { ident: name,
740                     attrs: attrs,
741                     id: ast::DUMMY_NODE_ID,
742                     node: node,
743                     vis: ast::inherited,
744                     span: span }
745     }
746
747     fn item_fn_poly(&self,
748                     span: Span,
749                     name: Ident,
750                     inputs: ~[ast::arg],
751                     output: ast::Ty,
752                     generics: Generics,
753                     body: ast::Block) -> @ast::item {
754         self.item(span,
755                   name,
756                   ~[],
757                   ast::item_fn(self.fn_decl(inputs, output),
758                                ast::impure_fn,
759                                AbiSet::Rust(),
760                                generics,
761                                body))
762     }
763
764     fn item_fn(&self,
765                span: Span,
766                name: Ident,
767                inputs: ~[ast::arg],
768                output: ast::Ty,
769                body: ast::Block
770               ) -> @ast::item {
771         self.item_fn_poly(
772             span,
773             name,
774             inputs,
775             output,
776             ast_util::empty_generics(),
777             body)
778     }
779
780     fn variant(&self, span: Span, name: Ident, tys: ~[ast::Ty]) -> ast::variant {
781         let args = tys.move_iter().map(|ty| {
782             ast::variant_arg { ty: ty, id: ast::DUMMY_NODE_ID }
783         }).collect();
784
785         respan(span,
786                ast::variant_ {
787                    name: name,
788                    attrs: ~[],
789                    kind: ast::tuple_variant_kind(args),
790                    id: ast::DUMMY_NODE_ID,
791                    disr_expr: None,
792                    vis: ast::public
793                })
794     }
795
796     fn item_enum_poly(&self, span: Span, name: Ident,
797                       enum_definition: ast::enum_def,
798                       generics: Generics) -> @ast::item {
799         self.item(span, name, ~[], ast::item_enum(enum_definition, generics))
800     }
801
802     fn item_enum(&self, span: Span, name: Ident,
803                  enum_definition: ast::enum_def) -> @ast::item {
804         self.item_enum_poly(span, name, enum_definition,
805                             ast_util::empty_generics())
806     }
807
808     fn item_struct(
809         &self,
810         span: Span,
811         name: Ident,
812         struct_def: ast::struct_def
813     ) -> @ast::item {
814         self.item_struct_poly(
815             span,
816             name,
817             struct_def,
818             ast_util::empty_generics()
819         )
820     }
821
822     fn item_struct_poly(
823         &self,
824         span: Span,
825         name: Ident,
826         struct_def: ast::struct_def,
827         generics: Generics
828     ) -> @ast::item {
829         self.item(span, name, ~[], ast::item_struct(@struct_def, generics))
830     }
831
832     fn item_mod(&self, span: Span, name: Ident,
833                 attrs: ~[ast::Attribute],
834                 vi: ~[ast::view_item],
835                 items: ~[@ast::item]) -> @ast::item {
836         self.item(
837             span,
838             name,
839             attrs,
840             ast::item_mod(ast::_mod {
841                 view_items: vi,
842                 items: items,
843             })
844         )
845     }
846
847     fn item_ty_poly(&self, span: Span, name: Ident, ty: ast::Ty,
848                     generics: Generics) -> @ast::item {
849         self.item(span, name, ~[], ast::item_ty(ty, generics))
850     }
851
852     fn item_ty(&self, span: Span, name: Ident, ty: ast::Ty) -> @ast::item {
853         self.item_ty_poly(span, name, ty, ast_util::empty_generics())
854     }
855
856     fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute {
857         respan(sp, ast::Attribute_ {
858             style: ast::AttrOuter,
859             value: mi,
860             is_sugared_doc: false,
861         })
862     }
863
864     fn meta_word(&self, sp: Span, w: @str) -> @ast::MetaItem {
865         @respan(sp, ast::MetaWord(w))
866     }
867     fn meta_list(&self, sp: Span, name: @str, mis: ~[@ast::MetaItem]) -> @ast::MetaItem {
868         @respan(sp, ast::MetaList(name, mis))
869     }
870     fn meta_name_value(&self, sp: Span, name: @str, value: ast::lit_) -> @ast::MetaItem {
871         @respan(sp, ast::MetaNameValue(name, respan(sp, value)))
872     }
873
874     fn view_use(&self, sp: Span,
875                 vis: ast::visibility, vp: ~[@ast::view_path]) -> ast::view_item {
876         ast::view_item {
877             node: ast::view_item_use(vp),
878             attrs: ~[],
879             vis: vis,
880             span: sp
881         }
882     }
883
884     fn view_use_list(&self, sp: Span, vis: ast::visibility,
885                      path: ~[ast::Ident], imports: &[ast::Ident]) -> ast::view_item {
886         let imports = do imports.map |id| {
887             respan(sp, ast::path_list_ident_ { name: *id, id: ast::DUMMY_NODE_ID })
888         };
889
890         self.view_use(sp, vis,
891                       ~[@respan(sp,
892                                 ast::view_path_list(self.path(sp, path),
893                                                     imports,
894                                                     ast::DUMMY_NODE_ID))])
895     }
896
897     fn view_use_glob(&self, sp: Span,
898                      vis: ast::visibility, path: ~[ast::Ident]) -> ast::view_item {
899         self.view_use(sp, vis,
900                       ~[@respan(sp,
901                                 ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))])
902     }
903 }
904
905 struct Duplicator {
906     cx: @ExtCtxt,
907 }
908
909 impl fold::ast_fold for Duplicator {
910     fn new_id(&self, _: NodeId) -> NodeId {
911         ast::DUMMY_NODE_ID
912     }
913 }
914
915 pub trait Duplicate {
916     //
917     // Duplication functions
918     //
919     // These functions just duplicate AST nodes.
920     //
921
922     fn duplicate(&self, cx: @ExtCtxt) -> Self;
923 }
924
925 impl Duplicate for @ast::Expr {
926     fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr {
927         let folder = @Duplicator {
928             cx: cx,
929         } as @fold::ast_fold;
930         folder.fold_expr(*self)
931     }
932 }