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