]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/ext/build.rs
auto merge of #9664 : alexcrichton/rust/logging, r=huonw
[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                 rp: Option<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, None, ~[])
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, None, ~[])
247     }
248     fn path_all(&self,
249                 sp: Span,
250                 global: bool,
251                 mut idents: ~[ast::Ident],
252                 rp: Option<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                 lifetime: None,
261                 types: opt_vec::Empty,
262             }
263         }).collect();
264         segments.push(ast::PathSegment {
265             identifier: last_identifier,
266             lifetime: rp,
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                           None,
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 = self.pat_ident(sp, ident);
403         let local = @ast::Local {
404             is_mutbl: mutbl,
405             ty: self.ty_infer(sp),
406             pat: pat,
407             init: Some(ex),
408             id: ast::DUMMY_NODE_ID,
409             span: sp,
410         };
411         let decl = respan(sp, ast::DeclLocal(local));
412         @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
413     }
414
415     fn stmt_let_typed(&self,
416                       sp: Span,
417                       mutbl: bool,
418                       ident: ast::Ident,
419                       typ: ast::Ty,
420                       ex: @ast::Expr)
421                       -> @ast::Stmt {
422         let pat = self.pat_ident(sp, ident);
423         let local = @ast::Local {
424             is_mutbl: mutbl,
425             ty: typ,
426             pat: pat,
427             init: Some(ex),
428             id: ast::DUMMY_NODE_ID,
429             span: sp,
430         };
431         let decl = respan(sp, ast::DeclLocal(local));
432         @respan(sp, ast::StmtDecl(@decl, ast::DUMMY_NODE_ID))
433     }
434
435     fn block(&self, span: Span, stmts: ~[@ast::Stmt], expr: Option<@Expr>) -> ast::Block {
436         self.block_all(span, ~[], stmts, expr)
437     }
438
439     fn block_expr(&self, expr: @ast::Expr) -> ast::Block {
440         self.block_all(expr.span, ~[], ~[], Some(expr))
441     }
442     fn block_all(&self,
443                  span: Span,
444                  view_items: ~[ast::view_item],
445                  stmts: ~[@ast::Stmt],
446                  expr: Option<@ast::Expr>) -> ast::Block {
447            ast::Block {
448                view_items: view_items,
449                stmts: stmts,
450                expr: expr,
451                id: ast::DUMMY_NODE_ID,
452                rules: ast::DefaultBlock,
453                span: span,
454            }
455     }
456
457     fn expr(&self, span: Span, node: ast::Expr_) -> @ast::Expr {
458         @ast::Expr {
459             id: ast::DUMMY_NODE_ID,
460             node: node,
461             span: span,
462         }
463     }
464
465     fn expr_path(&self, path: ast::Path) -> @ast::Expr {
466         self.expr(path.span, ast::ExprPath(path))
467     }
468
469     fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr {
470         self.expr_path(self.path_ident(span, id))
471     }
472     fn expr_self(&self, span: Span) -> @ast::Expr {
473         self.expr(span, ast::ExprSelf)
474     }
475
476     fn expr_binary(&self, sp: Span, op: ast::BinOp,
477                    lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
478         self.expr(sp, ast::ExprBinary(ast::DUMMY_NODE_ID, op, lhs, rhs))
479     }
480
481     fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
482         self.expr_unary(sp, ast::UnDeref, e)
483     }
484     fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr)
485         -> @ast::Expr {
486         self.expr(sp, ast::ExprUnary(ast::DUMMY_NODE_ID, op, e))
487     }
488
489     fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
490         self.expr_unary(sp, ast::UnBox(ast::MutImmutable), e)
491     }
492
493     fn expr_field_access(&self, sp: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
494         self.expr(sp, ast::ExprField(expr, ident, ~[]))
495     }
496     fn expr_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
497         self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e))
498     }
499     fn expr_mut_addr_of(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
500         self.expr(sp, ast::ExprAddrOf(ast::MutMutable, e))
501     }
502
503     fn expr_call(&self, span: Span, expr: @ast::Expr, args: ~[@ast::Expr]) -> @ast::Expr {
504         self.expr(span, ast::ExprCall(expr, args, ast::NoSugar))
505     }
506     fn expr_call_ident(&self, span: Span, id: ast::Ident, args: ~[@ast::Expr]) -> @ast::Expr {
507         self.expr(span,
508                   ast::ExprCall(self.expr_ident(span, id), args, ast::NoSugar))
509     }
510     fn expr_call_global(&self, sp: Span, fn_path: ~[ast::Ident],
511                       args: ~[@ast::Expr]) -> @ast::Expr {
512         let pathexpr = self.expr_path(self.path_global(sp, fn_path));
513         self.expr_call(sp, pathexpr, args)
514     }
515     fn expr_method_call(&self, span: Span,
516                         expr: @ast::Expr,
517                         ident: ast::Ident,
518                         args: ~[@ast::Expr]) -> @ast::Expr {
519         self.expr(span,
520                   ast::ExprMethodCall(ast::DUMMY_NODE_ID, expr, ident, ~[], args, ast::NoSugar))
521     }
522     fn expr_block(&self, b: ast::Block) -> @ast::Expr {
523         self.expr(b.span, ast::ExprBlock(b))
524     }
525     fn field_imm(&self, span: Span, name: Ident, e: @ast::Expr) -> ast::Field {
526         ast::Field { ident: name, expr: e, span: span }
527     }
528     fn expr_struct(&self, span: Span, path: ast::Path, fields: ~[ast::Field]) -> @ast::Expr {
529         self.expr(span, ast::ExprStruct(path, fields, None))
530     }
531     fn expr_struct_ident(&self, span: Span,
532                          id: ast::Ident, fields: ~[ast::Field]) -> @ast::Expr {
533         self.expr_struct(span, self.path_ident(span, id), fields)
534     }
535
536     fn expr_lit(&self, sp: Span, lit: ast::lit_) -> @ast::Expr {
537         self.expr(sp, ast::ExprLit(@respan(sp, lit)))
538     }
539     fn expr_uint(&self, span: Span, i: uint) -> @ast::Expr {
540         self.expr_lit(span, ast::lit_uint(i as u64, ast::ty_u))
541     }
542     fn expr_int(&self, sp: Span, i: int) -> @ast::Expr {
543         self.expr_lit(sp, ast::lit_int(i as i64, ast::ty_i))
544     }
545     fn expr_u8(&self, sp: Span, u: u8) -> @ast::Expr {
546         self.expr_lit(sp, ast::lit_uint(u as u64, ast::ty_u8))
547     }
548     fn expr_bool(&self, sp: Span, value: bool) -> @ast::Expr {
549         self.expr_lit(sp, ast::lit_bool(value))
550     }
551
552     fn expr_vstore(&self, sp: Span, expr: @ast::Expr, vst: ast::ExprVstore) -> @ast::Expr {
553         self.expr(sp, ast::ExprVstore(expr, vst))
554     }
555     fn expr_vec(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
556         self.expr(sp, ast::ExprVec(exprs, ast::MutImmutable))
557     }
558     fn expr_vec_uniq(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
559         self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreUniq)
560     }
561     fn expr_vec_slice(&self, sp: Span, exprs: ~[@ast::Expr]) -> @ast::Expr {
562         self.expr_vstore(sp, self.expr_vec(sp, exprs), ast::ExprVstoreSlice)
563     }
564     fn expr_str(&self, sp: Span, s: @str) -> @ast::Expr {
565         self.expr_lit(sp, ast::lit_str(s, ast::CookedStr))
566     }
567     fn expr_str_uniq(&self, sp: Span, s: @str) -> @ast::Expr {
568         self.expr_vstore(sp, self.expr_str(sp, s), ast::ExprVstoreUniq)
569     }
570
571
572     fn expr_cast(&self, sp: Span, expr: @ast::Expr, ty: ast::Ty) -> @ast::Expr {
573         self.expr(sp, ast::ExprCast(expr, ty))
574     }
575
576
577     fn expr_some(&self, sp: Span, expr: @ast::Expr) -> @ast::Expr {
578         let some = ~[
579             self.ident_of("std"),
580             self.ident_of("option"),
581             self.ident_of("Some"),
582         ];
583         self.expr_call_global(sp, some, ~[expr])
584     }
585
586     fn expr_none(&self, sp: Span) -> @ast::Expr {
587         let none = self.path_global(sp, ~[
588             self.ident_of("std"),
589             self.ident_of("option"),
590             self.ident_of("None"),
591         ]);
592         self.expr_path(none)
593     }
594
595     fn expr_fail(&self, span: Span, msg: @str) -> @ast::Expr {
596         let loc = self.codemap().lookup_char_pos(span.lo);
597         self.expr_call_global(
598             span,
599             ~[
600                 self.ident_of("std"),
601                 self.ident_of("sys"),
602                 self.ident_of("FailWithCause"),
603                 self.ident_of("fail_with"),
604             ],
605             ~[
606                 self.expr_str(span, msg),
607                 self.expr_str(span, loc.file.name),
608                 self.expr_uint(span, loc.line),
609             ])
610     }
611
612     fn expr_unreachable(&self, span: Span) -> @ast::Expr {
613         self.expr_fail(span, @"internal error: entered unreachable code")
614     }
615
616
617     fn pat(&self, span: Span, pat: ast::Pat_) -> @ast::Pat {
618         @ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }
619     }
620     fn pat_wild(&self, span: Span) -> @ast::Pat {
621         self.pat(span, ast::PatWild)
622     }
623     fn pat_lit(&self, span: Span, expr: @ast::Expr) -> @ast::Pat {
624         self.pat(span, ast::PatLit(expr))
625     }
626     fn pat_ident(&self, span: Span, ident: ast::Ident) -> @ast::Pat {
627         self.pat_ident_binding_mode(span, ident, ast::BindInfer)
628     }
629
630     fn pat_ident_binding_mode(&self,
631                               span: Span,
632                               ident: ast::Ident,
633                               bm: ast::BindingMode) -> @ast::Pat {
634         let path = self.path_ident(span, ident);
635         let pat = ast::PatIdent(bm, path, None);
636         self.pat(span, pat)
637     }
638     fn pat_enum(&self, span: Span, path: ast::Path, subpats: ~[@ast::Pat]) -> @ast::Pat {
639         let pat = ast::PatEnum(path, Some(subpats));
640         self.pat(span, pat)
641     }
642     fn pat_struct(&self, span: Span,
643                   path: ast::Path, field_pats: ~[ast::FieldPat]) -> @ast::Pat {
644         let pat = ast::PatStruct(path, field_pats, false);
645         self.pat(span, pat)
646     }
647
648     fn arm(&self, _span: Span, pats: ~[@ast::Pat], expr: @ast::Expr) -> ast::Arm {
649         ast::Arm {
650             pats: pats,
651             guard: None,
652             body: self.block_expr(expr)
653         }
654     }
655
656     fn arm_unreachable(&self, span: Span) -> ast::Arm {
657         self.arm(span, ~[self.pat_wild(span)], self.expr_unreachable(span))
658     }
659
660     fn expr_match(&self, span: Span, arg: @ast::Expr, arms: ~[ast::Arm]) -> @Expr {
661         self.expr(span, ast::ExprMatch(arg, arms))
662     }
663
664     fn expr_if(&self, span: Span,
665                cond: @ast::Expr, then: @ast::Expr, els: Option<@ast::Expr>) -> @ast::Expr {
666         let els = els.map(|x| self.expr_block(self.block_expr(x)));
667         self.expr(span, ast::ExprIf(cond, self.block_expr(then), els))
668     }
669
670     fn lambda_fn_decl(&self, span: Span, fn_decl: ast::fn_decl, blk: ast::Block) -> @ast::Expr {
671         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
672     }
673     fn lambda(&self, span: Span, ids: ~[ast::Ident], blk: ast::Block) -> @ast::Expr {
674         let fn_decl = self.fn_decl(
675             ids.map(|id| self.arg(span, *id, self.ty_infer(span))),
676             self.ty_infer(span));
677
678         self.expr(span, ast::ExprFnBlock(fn_decl, blk))
679     }
680     fn lambda0(&self, _span: Span, blk: ast::Block) -> @ast::Expr {
681         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
682         quote_expr!(*self, || $blk_e )
683     }
684
685     fn lambda1(&self, _span: Span, blk: ast::Block, ident: ast::Ident) -> @ast::Expr {
686         let blk_e = self.expr(blk.span, ast::ExprBlock(blk.clone()));
687         quote_expr!(*self, |$ident| $blk_e )
688     }
689
690     fn lambda_expr(&self, span: Span, ids: ~[ast::Ident], expr: @ast::Expr) -> @ast::Expr {
691         self.lambda(span, ids, self.block_expr(expr))
692     }
693     fn lambda_expr_0(&self, span: Span, expr: @ast::Expr) -> @ast::Expr {
694         self.lambda0(span, self.block_expr(expr))
695     }
696     fn lambda_expr_1(&self, span: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
697         self.lambda1(span, self.block_expr(expr), ident)
698     }
699
700     fn lambda_stmts(&self, span: Span, ids: ~[ast::Ident], stmts: ~[@ast::Stmt]) -> @ast::Expr {
701         self.lambda(span, ids, self.block(span, stmts, None))
702     }
703     fn lambda_stmts_0(&self, span: Span, stmts: ~[@ast::Stmt]) -> @ast::Expr {
704         self.lambda0(span, self.block(span, stmts, None))
705     }
706     fn lambda_stmts_1(&self, span: Span, stmts: ~[@ast::Stmt], ident: ast::Ident) -> @ast::Expr {
707         self.lambda1(span, self.block(span, stmts, None), ident)
708     }
709
710     fn arg(&self, span: Span, ident: ast::Ident, ty: ast::Ty) -> ast::arg {
711         let arg_pat = self.pat_ident(span, ident);
712         ast::arg {
713             is_mutbl: false,
714             ty: ty,
715             pat: arg_pat,
716             id: ast::DUMMY_NODE_ID
717         }
718     }
719
720     // XXX unused self
721     fn fn_decl(&self, inputs: ~[ast::arg], output: ast::Ty) -> ast::fn_decl {
722         ast::fn_decl {
723             inputs: inputs,
724             output: output,
725             cf: ast::return_val,
726         }
727     }
728
729     fn item(&self, span: Span,
730             name: Ident, attrs: ~[ast::Attribute], node: ast::item_) -> @ast::item {
731         // XXX: Would be nice if our generated code didn't violate
732         // Rust coding conventions
733         @ast::item { ident: name,
734                     attrs: attrs,
735                     id: ast::DUMMY_NODE_ID,
736                     node: node,
737                     vis: ast::inherited,
738                     span: span }
739     }
740
741     fn item_fn_poly(&self,
742                     span: Span,
743                     name: Ident,
744                     inputs: ~[ast::arg],
745                     output: ast::Ty,
746                     generics: Generics,
747                     body: ast::Block) -> @ast::item {
748         self.item(span,
749                   name,
750                   ~[],
751                   ast::item_fn(self.fn_decl(inputs, output),
752                                ast::impure_fn,
753                                AbiSet::Rust(),
754                                generics,
755                                body))
756     }
757
758     fn item_fn(&self,
759                span: Span,
760                name: Ident,
761                inputs: ~[ast::arg],
762                output: ast::Ty,
763                body: ast::Block
764               ) -> @ast::item {
765         self.item_fn_poly(
766             span,
767             name,
768             inputs,
769             output,
770             ast_util::empty_generics(),
771             body)
772     }
773
774     fn variant(&self, span: Span, name: Ident, tys: ~[ast::Ty]) -> ast::variant {
775         let args = tys.move_iter().map(|ty| {
776             ast::variant_arg { ty: ty, id: ast::DUMMY_NODE_ID }
777         }).collect();
778
779         respan(span,
780                ast::variant_ {
781                    name: name,
782                    attrs: ~[],
783                    kind: ast::tuple_variant_kind(args),
784                    id: ast::DUMMY_NODE_ID,
785                    disr_expr: None,
786                    vis: ast::public
787                })
788     }
789
790     fn item_enum_poly(&self, span: Span, name: Ident,
791                       enum_definition: ast::enum_def,
792                       generics: Generics) -> @ast::item {
793         self.item(span, name, ~[], ast::item_enum(enum_definition, generics))
794     }
795
796     fn item_enum(&self, span: Span, name: Ident,
797                  enum_definition: ast::enum_def) -> @ast::item {
798         self.item_enum_poly(span, name, enum_definition,
799                             ast_util::empty_generics())
800     }
801
802     fn item_struct(
803         &self,
804         span: Span,
805         name: Ident,
806         struct_def: ast::struct_def
807     ) -> @ast::item {
808         self.item_struct_poly(
809             span,
810             name,
811             struct_def,
812             ast_util::empty_generics()
813         )
814     }
815
816     fn item_struct_poly(
817         &self,
818         span: Span,
819         name: Ident,
820         struct_def: ast::struct_def,
821         generics: Generics
822     ) -> @ast::item {
823         self.item(span, name, ~[], ast::item_struct(@struct_def, generics))
824     }
825
826     fn item_mod(&self, span: Span, name: Ident,
827                 attrs: ~[ast::Attribute],
828                 vi: ~[ast::view_item],
829                 items: ~[@ast::item]) -> @ast::item {
830         self.item(
831             span,
832             name,
833             attrs,
834             ast::item_mod(ast::_mod {
835                 view_items: vi,
836                 items: items,
837             })
838         )
839     }
840
841     fn item_ty_poly(&self, span: Span, name: Ident, ty: ast::Ty,
842                     generics: Generics) -> @ast::item {
843         self.item(span, name, ~[], ast::item_ty(ty, generics))
844     }
845
846     fn item_ty(&self, span: Span, name: Ident, ty: ast::Ty) -> @ast::item {
847         self.item_ty_poly(span, name, ty, ast_util::empty_generics())
848     }
849
850     fn attribute(&self, sp: Span, mi: @ast::MetaItem) -> ast::Attribute {
851         respan(sp, ast::Attribute_ {
852             style: ast::AttrOuter,
853             value: mi,
854             is_sugared_doc: false,
855         })
856     }
857
858     fn meta_word(&self, sp: Span, w: @str) -> @ast::MetaItem {
859         @respan(sp, ast::MetaWord(w))
860     }
861     fn meta_list(&self, sp: Span, name: @str, mis: ~[@ast::MetaItem]) -> @ast::MetaItem {
862         @respan(sp, ast::MetaList(name, mis))
863     }
864     fn meta_name_value(&self, sp: Span, name: @str, value: ast::lit_) -> @ast::MetaItem {
865         @respan(sp, ast::MetaNameValue(name, respan(sp, value)))
866     }
867
868     fn view_use(&self, sp: Span,
869                 vis: ast::visibility, vp: ~[@ast::view_path]) -> ast::view_item {
870         ast::view_item {
871             node: ast::view_item_use(vp),
872             attrs: ~[],
873             vis: vis,
874             span: sp
875         }
876     }
877
878     fn view_use_list(&self, sp: Span, vis: ast::visibility,
879                      path: ~[ast::Ident], imports: &[ast::Ident]) -> ast::view_item {
880         let imports = do imports.map |id| {
881             respan(sp, ast::path_list_ident_ { name: *id, id: ast::DUMMY_NODE_ID })
882         };
883
884         self.view_use(sp, vis,
885                       ~[@respan(sp,
886                                 ast::view_path_list(self.path(sp, path),
887                                                     imports,
888                                                     ast::DUMMY_NODE_ID))])
889     }
890
891     fn view_use_glob(&self, sp: Span,
892                      vis: ast::visibility, path: ~[ast::Ident]) -> ast::view_item {
893         self.view_use(sp, vis,
894                       ~[@respan(sp,
895                                 ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))])
896     }
897 }
898
899 struct Duplicator {
900     cx: @ExtCtxt,
901 }
902
903 impl fold::ast_fold for Duplicator {
904     fn new_id(&self, _: NodeId) -> NodeId {
905         ast::DUMMY_NODE_ID
906     }
907 }
908
909 pub trait Duplicate {
910     //
911     // Duplication functions
912     //
913     // These functions just duplicate AST nodes.
914     //
915
916     fn duplicate(&self, cx: @ExtCtxt) -> Self;
917 }
918
919 impl Duplicate for @ast::Expr {
920     fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr {
921         let folder = @Duplicator {
922             cx: cx,
923         } as @fold::ast_fold;
924         folder.fold_expr(*self)
925     }
926 }