]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | ||
7453a54e SL |
11 | use abi::Abi; |
12 | use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind}; | |
1a4d82fc JJ |
13 | use attr; |
14 | use codemap::{Span, respan, Spanned, DUMMY_SP, Pos}; | |
970d7e83 | 15 | use ext::base::ExtCtxt; |
1a4d82fc JJ |
16 | use parse::token::special_idents; |
17 | use parse::token::InternedString; | |
18 | use parse::token; | |
19 | use ptr::P; | |
223e47cc | 20 | |
970d7e83 LB |
21 | // Transitional reexports so qquote can find the paths it is looking for |
22 | mod syntax { | |
23 | pub use ext; | |
24 | pub use parse; | |
223e47cc LB |
25 | } |
26 | ||
970d7e83 LB |
27 | pub trait AstBuilder { |
28 | // paths | |
1a4d82fc JJ |
29 | fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; |
30 | fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path; | |
31 | fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; | |
32 | fn path_all(&self, sp: Span, | |
970d7e83 | 33 | global: bool, |
1a4d82fc JJ |
34 | idents: Vec<ast::Ident> , |
35 | lifetimes: Vec<ast::Lifetime>, | |
36 | types: Vec<P<ast::Ty>>, | |
7453a54e | 37 | bindings: Vec<ast::TypeBinding> ) |
1a4d82fc | 38 | -> ast::Path; |
970d7e83 | 39 | |
85aaf69f | 40 | fn qpath(&self, self_type: P<ast::Ty>, |
c34b1796 AL |
41 | trait_path: ast::Path, |
42 | ident: ast::Ident) | |
43 | -> (ast::QSelf, ast::Path); | |
85aaf69f | 44 | fn qpath_all(&self, self_type: P<ast::Ty>, |
c34b1796 | 45 | trait_path: ast::Path, |
85aaf69f SL |
46 | ident: ast::Ident, |
47 | lifetimes: Vec<ast::Lifetime>, | |
48 | types: Vec<P<ast::Ty>>, | |
7453a54e | 49 | bindings: Vec<ast::TypeBinding>) |
c34b1796 | 50 | -> (ast::QSelf, ast::Path); |
85aaf69f | 51 | |
970d7e83 | 52 | // types |
1a4d82fc JJ |
53 | fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy; |
54 | ||
7453a54e | 55 | fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty>; |
1a4d82fc | 56 | fn ty_path(&self, ast::Path) -> P<ast::Ty>; |
9cc50fc6 | 57 | fn ty_sum(&self, ast::Path, ast::TyParamBounds) -> P<ast::Ty>; |
1a4d82fc JJ |
58 | fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>; |
59 | ||
60 | fn ty_rptr(&self, span: Span, | |
61 | ty: P<ast::Ty>, | |
62 | lifetime: Option<ast::Lifetime>, | |
63 | mutbl: ast::Mutability) -> P<ast::Ty>; | |
64 | fn ty_ptr(&self, span: Span, | |
65 | ty: P<ast::Ty>, | |
66 | mutbl: ast::Mutability) -> P<ast::Ty>; | |
67 | ||
68 | fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>; | |
69 | fn ty_infer(&self, sp: Span) -> P<ast::Ty>; | |
70 | ||
9cc50fc6 SL |
71 | fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> ; |
72 | fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> ; | |
1a4d82fc JJ |
73 | |
74 | fn typaram(&self, | |
75 | span: Span, | |
76 | id: ast::Ident, | |
9cc50fc6 | 77 | bounds: ast::TyParamBounds, |
1a4d82fc JJ |
78 | default: Option<P<ast::Ty>>) -> ast::TyParam; |
79 | ||
80 | fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; | |
85aaf69f | 81 | fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef; |
1a4d82fc JJ |
82 | fn typarambound(&self, path: ast::Path) -> ast::TyParamBound; |
83 | fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime; | |
84 | fn lifetime_def(&self, | |
85 | span: Span, | |
86 | name: ast::Name, | |
87 | bounds: Vec<ast::Lifetime>) | |
88 | -> ast::LifetimeDef; | |
970d7e83 LB |
89 | |
90 | // statements | |
7453a54e SL |
91 | fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt; |
92 | fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P<ast::Expr>) -> ast::Stmt; | |
1a4d82fc JJ |
93 | fn stmt_let_typed(&self, |
94 | sp: Span, | |
95 | mutbl: bool, | |
96 | ident: ast::Ident, | |
97 | typ: P<ast::Ty>, | |
98 | ex: P<ast::Expr>) | |
99 | -> P<ast::Stmt>; | |
7453a54e | 100 | fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt; |
970d7e83 LB |
101 | |
102 | // blocks | |
7453a54e | 103 | fn block(&self, span: Span, stmts: Vec<ast::Stmt>, |
1a4d82fc JJ |
104 | expr: Option<P<ast::Expr>>) -> P<ast::Block>; |
105 | fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>; | |
106 | fn block_all(&self, span: Span, | |
7453a54e | 107 | stmts: Vec<ast::Stmt>, |
1a4d82fc | 108 | expr: Option<P<ast::Expr>>) -> P<ast::Block>; |
970d7e83 LB |
109 | |
110 | // expressions | |
7453a54e | 111 | fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr>; |
1a4d82fc | 112 | fn expr_path(&self, path: ast::Path) -> P<ast::Expr>; |
c34b1796 | 113 | fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr>; |
1a4d82fc JJ |
114 | fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>; |
115 | ||
116 | fn expr_self(&self, span: Span) -> P<ast::Expr>; | |
7453a54e | 117 | fn expr_binary(&self, sp: Span, op: ast::BinOpKind, |
1a4d82fc JJ |
118 | lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr>; |
119 | fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>; | |
120 | fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr>; | |
121 | ||
122 | fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>; | |
123 | fn expr_mut_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>; | |
124 | fn expr_field_access(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>; | |
125 | fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, | |
85aaf69f | 126 | idx: usize) -> P<ast::Expr>; |
1a4d82fc JJ |
127 | fn expr_call(&self, span: Span, expr: P<ast::Expr>, args: Vec<P<ast::Expr>>) -> P<ast::Expr>; |
128 | fn expr_call_ident(&self, span: Span, id: ast::Ident, args: Vec<P<ast::Expr>>) -> P<ast::Expr>; | |
129 | fn expr_call_global(&self, sp: Span, fn_path: Vec<ast::Ident>, | |
130 | args: Vec<P<ast::Expr>> ) -> P<ast::Expr>; | |
131 | fn expr_method_call(&self, span: Span, | |
132 | expr: P<ast::Expr>, ident: ast::Ident, | |
133 | args: Vec<P<ast::Expr>> ) -> P<ast::Expr>; | |
134 | fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr>; | |
135 | fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr>; | |
136 | ||
137 | fn field_imm(&self, span: Span, name: Ident, e: P<ast::Expr>) -> ast::Field; | |
138 | fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field>) -> P<ast::Expr>; | |
139 | fn expr_struct_ident(&self, span: Span, id: ast::Ident, | |
140 | fields: Vec<ast::Field>) -> P<ast::Expr>; | |
141 | ||
7453a54e | 142 | fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P<ast::Expr>; |
1a4d82fc | 143 | |
85aaf69f | 144 | fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr>; |
d9579d0f | 145 | fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr>; |
1a4d82fc | 146 | fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr>; |
c34b1796 | 147 | fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr>; |
1a4d82fc JJ |
148 | fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr>; |
149 | ||
150 | fn expr_vec(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>; | |
151 | fn expr_vec_ng(&self, sp: Span) -> P<ast::Expr>; | |
152 | fn expr_vec_slice(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>; | |
153 | fn expr_str(&self, sp: Span, s: InternedString) -> P<ast::Expr>; | |
154 | ||
155 | fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr>; | |
156 | fn expr_none(&self, sp: Span) -> P<ast::Expr>; | |
157 | ||
158 | fn expr_break(&self, sp: Span) -> P<ast::Expr>; | |
159 | ||
160 | fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>; | |
161 | ||
162 | fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr>; | |
163 | fn expr_unreachable(&self, span: Span) -> P<ast::Expr>; | |
164 | ||
165 | fn expr_ok(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>; | |
166 | fn expr_err(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>; | |
167 | fn expr_try(&self, span: Span, head: P<ast::Expr>) -> P<ast::Expr>; | |
168 | ||
7453a54e | 169 | fn pat(&self, span: Span, pat: PatKind) -> P<ast::Pat>; |
1a4d82fc JJ |
170 | fn pat_wild(&self, span: Span) -> P<ast::Pat>; |
171 | fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat>; | |
172 | fn pat_ident(&self, span: Span, ident: ast::Ident) -> P<ast::Pat>; | |
970d7e83 LB |
173 | |
174 | fn pat_ident_binding_mode(&self, | |
1a4d82fc JJ |
175 | span: Span, |
176 | ident: ast::Ident, | |
177 | bm: ast::BindingMode) -> P<ast::Pat>; | |
178 | fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>> ) -> P<ast::Pat>; | |
179 | fn pat_struct(&self, span: Span, | |
180 | path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>> ) -> P<ast::Pat>; | |
181 | fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat>; | |
182 | ||
183 | fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>; | |
184 | fn pat_none(&self, span: Span) -> P<ast::Pat>; | |
185 | ||
186 | fn pat_ok(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>; | |
187 | fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>; | |
970d7e83 | 188 | |
1a4d82fc JJ |
189 | fn arm(&self, span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm; |
190 | fn arm_unreachable(&self, span: Span) -> ast::Arm; | |
970d7e83 | 191 | |
1a4d82fc JJ |
192 | fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm> ) -> P<ast::Expr>; |
193 | fn expr_if(&self, span: Span, | |
194 | cond: P<ast::Expr>, then: P<ast::Expr>, els: Option<P<ast::Expr>>) -> P<ast::Expr>; | |
195 | fn expr_loop(&self, span: Span, block: P<ast::Block>) -> P<ast::Expr>; | |
970d7e83 | 196 | |
1a4d82fc JJ |
197 | fn lambda_fn_decl(&self, span: Span, |
198 | fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr>; | |
970d7e83 | 199 | |
1a4d82fc JJ |
200 | fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> P<ast::Expr>; |
201 | fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr>; | |
202 | fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr>; | |
970d7e83 | 203 | |
1a4d82fc JJ |
204 | fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Expr>) -> P<ast::Expr>; |
205 | fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>; | |
206 | fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>; | |
970d7e83 | 207 | |
1a4d82fc | 208 | fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident>, |
7453a54e SL |
209 | blk: Vec<ast::Stmt>) -> P<ast::Expr>; |
210 | fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr>; | |
211 | fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, | |
1a4d82fc | 212 | ident: ast::Ident) -> P<ast::Expr>; |
970d7e83 LB |
213 | |
214 | // items | |
1a4d82fc | 215 | fn item(&self, span: Span, |
7453a54e | 216 | name: Ident, attrs: Vec<ast::Attribute> , node: ast::ItemKind) -> P<ast::Item>; |
970d7e83 | 217 | |
1a4d82fc JJ |
218 | fn arg(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::Arg; |
219 | // FIXME unused self | |
220 | fn fn_decl(&self, inputs: Vec<ast::Arg> , output: P<ast::Ty>) -> P<ast::FnDecl>; | |
970d7e83 LB |
221 | |
222 | fn item_fn_poly(&self, | |
1a4d82fc JJ |
223 | span: Span, |
224 | name: Ident, | |
225 | inputs: Vec<ast::Arg> , | |
226 | output: P<ast::Ty>, | |
970d7e83 | 227 | generics: Generics, |
1a4d82fc | 228 | body: P<ast::Block>) -> P<ast::Item>; |
970d7e83 | 229 | fn item_fn(&self, |
1a4d82fc JJ |
230 | span: Span, |
231 | name: Ident, | |
232 | inputs: Vec<ast::Arg> , | |
233 | output: P<ast::Ty>, | |
234 | body: P<ast::Block>) -> P<ast::Item>; | |
970d7e83 | 235 | |
1a4d82fc | 236 | fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant; |
970d7e83 | 237 | fn item_enum_poly(&self, |
1a4d82fc JJ |
238 | span: Span, |
239 | name: Ident, | |
240 | enum_definition: ast::EnumDef, | |
241 | generics: Generics) -> P<ast::Item>; | |
242 | fn item_enum(&self, span: Span, name: Ident, enum_def: ast::EnumDef) -> P<ast::Item>; | |
970d7e83 LB |
243 | |
244 | fn item_struct_poly(&self, | |
1a4d82fc JJ |
245 | span: Span, |
246 | name: Ident, | |
b039eaaf | 247 | struct_def: ast::VariantData, |
1a4d82fc | 248 | generics: Generics) -> P<ast::Item>; |
b039eaaf | 249 | fn item_struct(&self, span: Span, name: Ident, struct_def: ast::VariantData) -> P<ast::Item>; |
1a4d82fc JJ |
250 | |
251 | fn item_mod(&self, span: Span, inner_span: Span, | |
252 | name: Ident, attrs: Vec<ast::Attribute>, | |
85aaf69f | 253 | items: Vec<P<ast::Item>>) -> P<ast::Item>; |
1a4d82fc JJ |
254 | |
255 | fn item_static(&self, | |
256 | span: Span, | |
257 | name: Ident, | |
258 | ty: P<ast::Ty>, | |
259 | mutbl: ast::Mutability, | |
260 | expr: P<ast::Expr>) | |
261 | -> P<ast::Item>; | |
262 | ||
263 | fn item_const(&self, | |
264 | span: Span, | |
265 | name: Ident, | |
266 | ty: P<ast::Ty>, | |
267 | expr: P<ast::Expr>) | |
268 | -> P<ast::Item>; | |
970d7e83 LB |
269 | |
270 | fn item_ty_poly(&self, | |
1a4d82fc JJ |
271 | span: Span, |
272 | name: Ident, | |
273 | ty: P<ast::Ty>, | |
274 | generics: Generics) -> P<ast::Item>; | |
275 | fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> P<ast::Item>; | |
276 | ||
277 | fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute; | |
278 | ||
279 | fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem>; | |
280 | fn meta_list(&self, | |
281 | sp: Span, | |
282 | name: InternedString, | |
283 | mis: Vec<P<ast::MetaItem>> ) | |
284 | -> P<ast::MetaItem>; | |
285 | fn meta_name_value(&self, | |
286 | sp: Span, | |
287 | name: InternedString, | |
7453a54e | 288 | value: ast::LitKind) |
1a4d82fc JJ |
289 | -> P<ast::MetaItem>; |
290 | ||
85aaf69f SL |
291 | fn item_use(&self, sp: Span, |
292 | vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item>; | |
293 | fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>; | |
294 | fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, | |
295 | ident: ast::Ident, path: ast::Path) -> P<ast::Item>; | |
296 | fn item_use_list(&self, sp: Span, vis: ast::Visibility, | |
297 | path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>; | |
298 | fn item_use_glob(&self, sp: Span, | |
299 | vis: ast::Visibility, path: Vec<ast::Ident>) -> P<ast::Item>; | |
223e47cc | 300 | } |
970d7e83 | 301 | |
1a4d82fc JJ |
302 | impl<'a> AstBuilder for ExtCtxt<'a> { |
303 | fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { | |
304 | self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) | |
223e47cc | 305 | } |
1a4d82fc JJ |
306 | fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { |
307 | self.path(span, vec!(id)) | |
970d7e83 | 308 | } |
1a4d82fc JJ |
309 | fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { |
310 | self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) | |
970d7e83 | 311 | } |
1a4d82fc JJ |
312 | fn path_all(&self, |
313 | sp: Span, | |
970d7e83 | 314 | global: bool, |
1a4d82fc JJ |
315 | mut idents: Vec<ast::Ident> , |
316 | lifetimes: Vec<ast::Lifetime>, | |
317 | types: Vec<P<ast::Ty>>, | |
7453a54e | 318 | bindings: Vec<ast::TypeBinding> ) |
1a4d82fc JJ |
319 | -> ast::Path { |
320 | let last_identifier = idents.pop().unwrap(); | |
321 | let mut segments: Vec<ast::PathSegment> = idents.into_iter() | |
322 | .map(|ident| { | |
323 | ast::PathSegment { | |
324 | identifier: ident, | |
325 | parameters: ast::PathParameters::none(), | |
326 | } | |
327 | }).collect(); | |
328 | segments.push(ast::PathSegment { | |
329 | identifier: last_identifier, | |
9cc50fc6 | 330 | parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { |
1a4d82fc | 331 | lifetimes: lifetimes, |
9cc50fc6 SL |
332 | types: P::from_vec(types), |
333 | bindings: P::from_vec(bindings), | |
1a4d82fc JJ |
334 | }) |
335 | }); | |
336 | ast::Path { | |
970d7e83 LB |
337 | span: sp, |
338 | global: global, | |
1a4d82fc | 339 | segments: segments, |
970d7e83 LB |
340 | } |
341 | } | |
342 | ||
85aaf69f SL |
343 | /// Constructs a qualified path. |
344 | /// | |
c34b1796 | 345 | /// Constructs a path like `<self_type as trait_path>::ident`. |
85aaf69f SL |
346 | fn qpath(&self, |
347 | self_type: P<ast::Ty>, | |
c34b1796 | 348 | trait_path: ast::Path, |
85aaf69f | 349 | ident: ast::Ident) |
c34b1796 AL |
350 | -> (ast::QSelf, ast::Path) { |
351 | self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) | |
85aaf69f SL |
352 | } |
353 | ||
354 | /// Constructs a qualified path. | |
355 | /// | |
c34b1796 | 356 | /// Constructs a path like `<self_type as trait_path>::ident<'a, T, A=Bar>`. |
85aaf69f SL |
357 | fn qpath_all(&self, |
358 | self_type: P<ast::Ty>, | |
c34b1796 | 359 | trait_path: ast::Path, |
85aaf69f SL |
360 | ident: ast::Ident, |
361 | lifetimes: Vec<ast::Lifetime>, | |
362 | types: Vec<P<ast::Ty>>, | |
7453a54e | 363 | bindings: Vec<ast::TypeBinding>) |
c34b1796 AL |
364 | -> (ast::QSelf, ast::Path) { |
365 | let mut path = trait_path; | |
366 | path.segments.push(ast::PathSegment { | |
85aaf69f | 367 | identifier: ident, |
9cc50fc6 | 368 | parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData { |
85aaf69f | 369 | lifetimes: lifetimes, |
9cc50fc6 SL |
370 | types: P::from_vec(types), |
371 | bindings: P::from_vec(bindings), | |
85aaf69f | 372 | }) |
c34b1796 | 373 | }); |
85aaf69f | 374 | |
c34b1796 AL |
375 | (ast::QSelf { |
376 | ty: self_type, | |
377 | position: path.segments.len() - 1 | |
378 | }, path) | |
85aaf69f SL |
379 | } |
380 | ||
1a4d82fc JJ |
381 | fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy { |
382 | ast::MutTy { | |
223e47cc | 383 | ty: ty, |
970d7e83 LB |
384 | mutbl: mutbl |
385 | } | |
386 | } | |
387 | ||
7453a54e | 388 | fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty> { |
1a4d82fc JJ |
389 | P(ast::Ty { |
390 | id: ast::DUMMY_NODE_ID, | |
970d7e83 LB |
391 | span: span, |
392 | node: ty | |
1a4d82fc JJ |
393 | }) |
394 | } | |
395 | ||
396 | fn ty_path(&self, path: ast::Path) -> P<ast::Ty> { | |
7453a54e | 397 | self.ty(path.span, ast::TyKind::Path(None, path)) |
970d7e83 LB |
398 | } |
399 | ||
9cc50fc6 | 400 | fn ty_sum(&self, path: ast::Path, bounds: ast::TyParamBounds) -> P<ast::Ty> { |
970d7e83 | 401 | self.ty(path.span, |
7453a54e | 402 | ast::TyKind::ObjectSum(self.ty_path(path), |
1a4d82fc | 403 | bounds)) |
970d7e83 LB |
404 | } |
405 | ||
406 | // Might need to take bounds as an argument in the future, if you ever want | |
407 | // to generate a bounded existential trait type. | |
1a4d82fc JJ |
408 | fn ty_ident(&self, span: Span, ident: ast::Ident) |
409 | -> P<ast::Ty> { | |
410 | self.ty_path(self.path_ident(span, ident)) | |
970d7e83 LB |
411 | } |
412 | ||
413 | fn ty_rptr(&self, | |
1a4d82fc JJ |
414 | span: Span, |
415 | ty: P<ast::Ty>, | |
416 | lifetime: Option<ast::Lifetime>, | |
417 | mutbl: ast::Mutability) | |
418 | -> P<ast::Ty> { | |
970d7e83 | 419 | self.ty(span, |
7453a54e | 420 | ast::TyKind::Rptr(lifetime, self.ty_mt(ty, mutbl))) |
970d7e83 | 421 | } |
1a4d82fc JJ |
422 | |
423 | fn ty_ptr(&self, | |
424 | span: Span, | |
425 | ty: P<ast::Ty>, | |
426 | mutbl: ast::Mutability) | |
427 | -> P<ast::Ty> { | |
428 | self.ty(span, | |
7453a54e | 429 | ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) |
970d7e83 LB |
430 | } |
431 | ||
1a4d82fc | 432 | fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> { |
970d7e83 | 433 | self.ty_path( |
1a4d82fc | 434 | self.path_all(DUMMY_SP, |
970d7e83 | 435 | true, |
e9174d1e | 436 | self.std_path(&["option", "Option"]), |
1a4d82fc JJ |
437 | Vec::new(), |
438 | vec!( ty ), | |
439 | Vec::new())) | |
970d7e83 LB |
440 | } |
441 | ||
1a4d82fc | 442 | fn ty_infer(&self, span: Span) -> P<ast::Ty> { |
7453a54e | 443 | self.ty(span, ast::TyKind::Infer) |
970d7e83 LB |
444 | } |
445 | ||
1a4d82fc JJ |
446 | fn typaram(&self, |
447 | span: Span, | |
448 | id: ast::Ident, | |
9cc50fc6 | 449 | bounds: ast::TyParamBounds, |
1a4d82fc JJ |
450 | default: Option<P<ast::Ty>>) -> ast::TyParam { |
451 | ast::TyParam { | |
452 | ident: id, | |
453 | id: ast::DUMMY_NODE_ID, | |
454 | bounds: bounds, | |
455 | default: default, | |
456 | span: span | |
970d7e83 LB |
457 | } |
458 | } | |
459 | ||
970d7e83 LB |
460 | // these are strange, and probably shouldn't be used outside of |
461 | // pipes. Specifically, the global version possible generates | |
462 | // incorrect code. | |
9cc50fc6 | 463 | fn ty_vars(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> { |
1a4d82fc | 464 | ty_params.iter().map(|p| self.ty_ident(DUMMY_SP, p.ident)).collect() |
970d7e83 LB |
465 | } |
466 | ||
9cc50fc6 | 467 | fn ty_vars_global(&self, ty_params: &P<[ast::TyParam]>) -> Vec<P<ast::Ty>> { |
1a4d82fc JJ |
468 | ty_params |
469 | .iter() | |
470 | .map(|p| self.ty_path(self.path_global(DUMMY_SP, vec!(p.ident)))) | |
471 | .collect() | |
970d7e83 LB |
472 | } |
473 | ||
1a4d82fc JJ |
474 | fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { |
475 | ast::TraitRef { | |
476 | path: path, | |
477 | ref_id: ast::DUMMY_NODE_ID, | |
970d7e83 LB |
478 | } |
479 | } | |
480 | ||
85aaf69f | 481 | fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { |
1a4d82fc JJ |
482 | ast::PolyTraitRef { |
483 | bound_lifetimes: Vec::new(), | |
85aaf69f SL |
484 | trait_ref: self.trait_ref(path), |
485 | span: span, | |
970d7e83 LB |
486 | } |
487 | } | |
488 | ||
1a4d82fc | 489 | fn typarambound(&self, path: ast::Path) -> ast::TyParamBound { |
85aaf69f | 490 | ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None) |
970d7e83 LB |
491 | } |
492 | ||
1a4d82fc JJ |
493 | fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime { |
494 | ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name } | |
970d7e83 LB |
495 | } |
496 | ||
1a4d82fc JJ |
497 | fn lifetime_def(&self, |
498 | span: Span, | |
499 | name: ast::Name, | |
500 | bounds: Vec<ast::Lifetime>) | |
501 | -> ast::LifetimeDef { | |
502 | ast::LifetimeDef { | |
503 | lifetime: self.lifetime(span, name), | |
504 | bounds: bounds | |
505 | } | |
506 | } | |
507 | ||
7453a54e SL |
508 | fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt { |
509 | respan(expr.span, ast::StmtKind::Semi(expr, ast::DUMMY_NODE_ID)) | |
1a4d82fc JJ |
510 | } |
511 | ||
512 | fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, | |
7453a54e | 513 | ex: P<ast::Expr>) -> ast::Stmt { |
1a4d82fc | 514 | let pat = if mutbl { |
7453a54e SL |
515 | let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); |
516 | self.pat_ident_binding_mode(sp, ident, binding_mode) | |
1a4d82fc JJ |
517 | } else { |
518 | self.pat_ident(sp, ident) | |
519 | }; | |
520 | let local = P(ast::Local { | |
521 | pat: pat, | |
522 | ty: None, | |
523 | init: Some(ex), | |
524 | id: ast::DUMMY_NODE_ID, | |
525 | span: sp, | |
92a42be0 | 526 | attrs: None, |
1a4d82fc | 527 | }); |
7453a54e SL |
528 | let decl = respan(sp, ast::DeclKind::Local(local)); |
529 | respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) | |
1a4d82fc JJ |
530 | } |
531 | ||
532 | fn stmt_let_typed(&self, | |
533 | sp: Span, | |
534 | mutbl: bool, | |
535 | ident: ast::Ident, | |
536 | typ: P<ast::Ty>, | |
537 | ex: P<ast::Expr>) | |
538 | -> P<ast::Stmt> { | |
539 | let pat = if mutbl { | |
7453a54e SL |
540 | let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Mutable); |
541 | self.pat_ident_binding_mode(sp, ident, binding_mode) | |
1a4d82fc JJ |
542 | } else { |
543 | self.pat_ident(sp, ident) | |
544 | }; | |
545 | let local = P(ast::Local { | |
546 | pat: pat, | |
547 | ty: Some(typ), | |
548 | init: Some(ex), | |
549 | id: ast::DUMMY_NODE_ID, | |
550 | span: sp, | |
92a42be0 | 551 | attrs: None, |
1a4d82fc | 552 | }); |
7453a54e SL |
553 | let decl = respan(sp, ast::DeclKind::Local(local)); |
554 | P(respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))) | |
970d7e83 LB |
555 | } |
556 | ||
7453a54e | 557 | fn block(&self, span: Span, stmts: Vec<ast::Stmt>, |
1a4d82fc | 558 | expr: Option<P<Expr>>) -> P<ast::Block> { |
85aaf69f | 559 | self.block_all(span, stmts, expr) |
970d7e83 LB |
560 | } |
561 | ||
7453a54e SL |
562 | fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt { |
563 | let decl = respan(sp, ast::DeclKind::Item(item)); | |
564 | respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)) | |
970d7e83 LB |
565 | } |
566 | ||
1a4d82fc | 567 | fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> { |
85aaf69f | 568 | self.block_all(expr.span, Vec::new(), Some(expr)) |
970d7e83 | 569 | } |
1a4d82fc JJ |
570 | fn block_all(&self, |
571 | span: Span, | |
7453a54e | 572 | stmts: Vec<ast::Stmt>, |
1a4d82fc JJ |
573 | expr: Option<P<ast::Expr>>) -> P<ast::Block> { |
574 | P(ast::Block { | |
1a4d82fc JJ |
575 | stmts: stmts, |
576 | expr: expr, | |
577 | id: ast::DUMMY_NODE_ID, | |
7453a54e | 578 | rules: BlockCheckMode::Default, |
970d7e83 | 579 | span: span, |
1a4d82fc | 580 | }) |
970d7e83 LB |
581 | } |
582 | ||
7453a54e | 583 | fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr> { |
1a4d82fc JJ |
584 | P(ast::Expr { |
585 | id: ast::DUMMY_NODE_ID, | |
970d7e83 LB |
586 | node: node, |
587 | span: span, | |
92a42be0 | 588 | attrs: None, |
1a4d82fc | 589 | }) |
970d7e83 LB |
590 | } |
591 | ||
1a4d82fc | 592 | fn expr_path(&self, path: ast::Path) -> P<ast::Expr> { |
7453a54e | 593 | self.expr(path.span, ast::ExprKind::Path(None, path)) |
970d7e83 LB |
594 | } |
595 | ||
85aaf69f | 596 | /// Constructs a QPath expression. |
c34b1796 | 597 | fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr> { |
7453a54e | 598 | self.expr(span, ast::ExprKind::Path(Some(qself), path)) |
85aaf69f SL |
599 | } |
600 | ||
1a4d82fc | 601 | fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> { |
970d7e83 LB |
602 | self.expr_path(self.path_ident(span, id)) |
603 | } | |
1a4d82fc JJ |
604 | fn expr_self(&self, span: Span) -> P<ast::Expr> { |
605 | self.expr_ident(span, special_idents::self_) | |
970d7e83 LB |
606 | } |
607 | ||
7453a54e | 608 | fn expr_binary(&self, sp: Span, op: ast::BinOpKind, |
1a4d82fc | 609 | lhs: P<ast::Expr>, rhs: P<ast::Expr>) -> P<ast::Expr> { |
7453a54e | 610 | self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs)) |
970d7e83 LB |
611 | } |
612 | ||
1a4d82fc | 613 | fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { |
7453a54e | 614 | self.expr_unary(sp, UnOp::Deref, e) |
970d7e83 | 615 | } |
1a4d82fc | 616 | fn expr_unary(&self, sp: Span, op: ast::UnOp, e: P<ast::Expr>) -> P<ast::Expr> { |
7453a54e | 617 | self.expr(sp, ast::ExprKind::Unary(op, e)) |
970d7e83 LB |
618 | } |
619 | ||
1a4d82fc | 620 | fn expr_field_access(&self, sp: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> { |
1a4d82fc | 621 | let field_span = Span { |
c1a9b12d | 622 | lo: sp.lo - Pos::from_usize(ident.name.as_str().len()), |
1a4d82fc JJ |
623 | hi: sp.hi, |
624 | expn_id: sp.expn_id, | |
625 | }; | |
626 | ||
627 | let id = Spanned { node: ident, span: field_span }; | |
7453a54e | 628 | self.expr(sp, ast::ExprKind::Field(expr, id)) |
970d7e83 | 629 | } |
85aaf69f | 630 | fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> { |
1a4d82fc | 631 | let field_span = Span { |
85aaf69f | 632 | lo: sp.lo - Pos::from_usize(idx.to_string().len()), |
1a4d82fc JJ |
633 | hi: sp.hi, |
634 | expn_id: sp.expn_id, | |
635 | }; | |
970d7e83 | 636 | |
1a4d82fc | 637 | let id = Spanned { node: idx, span: field_span }; |
7453a54e | 638 | self.expr(sp, ast::ExprKind::TupField(expr, id)) |
970d7e83 | 639 | } |
1a4d82fc | 640 | fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { |
7453a54e | 641 | self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e)) |
970d7e83 | 642 | } |
1a4d82fc | 643 | fn expr_mut_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { |
7453a54e | 644 | self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Mutable, e)) |
970d7e83 LB |
645 | } |
646 | ||
1a4d82fc | 647 | fn expr_call(&self, span: Span, expr: P<ast::Expr>, args: Vec<P<ast::Expr>>) -> P<ast::Expr> { |
7453a54e | 648 | self.expr(span, ast::ExprKind::Call(expr, args)) |
970d7e83 | 649 | } |
1a4d82fc JJ |
650 | fn expr_call_ident(&self, span: Span, id: ast::Ident, |
651 | args: Vec<P<ast::Expr>>) -> P<ast::Expr> { | |
7453a54e | 652 | self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args)) |
970d7e83 | 653 | } |
1a4d82fc JJ |
654 | fn expr_call_global(&self, sp: Span, fn_path: Vec<ast::Ident> , |
655 | args: Vec<P<ast::Expr>> ) -> P<ast::Expr> { | |
970d7e83 LB |
656 | let pathexpr = self.expr_path(self.path_global(sp, fn_path)); |
657 | self.expr_call(sp, pathexpr, args) | |
658 | } | |
1a4d82fc JJ |
659 | fn expr_method_call(&self, span: Span, |
660 | expr: P<ast::Expr>, | |
661 | ident: ast::Ident, | |
662 | mut args: Vec<P<ast::Expr>> ) -> P<ast::Expr> { | |
663 | let id = Spanned { node: ident, span: span }; | |
664 | args.insert(0, expr); | |
7453a54e | 665 | self.expr(span, ast::ExprKind::MethodCall(id, Vec::new(), args)) |
970d7e83 | 666 | } |
1a4d82fc | 667 | fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> { |
7453a54e | 668 | self.expr(b.span, ast::ExprKind::Block(b)) |
970d7e83 | 669 | } |
1a4d82fc JJ |
670 | fn field_imm(&self, span: Span, name: Ident, e: P<ast::Expr>) -> ast::Field { |
671 | ast::Field { ident: respan(span, name), expr: e, span: span } | |
970d7e83 | 672 | } |
1a4d82fc | 673 | fn expr_struct(&self, span: Span, path: ast::Path, fields: Vec<ast::Field>) -> P<ast::Expr> { |
7453a54e | 674 | self.expr(span, ast::ExprKind::Struct(path, fields, None)) |
970d7e83 | 675 | } |
1a4d82fc JJ |
676 | fn expr_struct_ident(&self, span: Span, |
677 | id: ast::Ident, fields: Vec<ast::Field>) -> P<ast::Expr> { | |
970d7e83 LB |
678 | self.expr_struct(span, self.path_ident(span, id), fields) |
679 | } | |
680 | ||
7453a54e SL |
681 | fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P<ast::Expr> { |
682 | self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit)))) | |
970d7e83 | 683 | } |
85aaf69f | 684 | fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> { |
7453a54e | 685 | self.expr_lit(span, ast::LitKind::Int(i as u64, ast::LitIntType::Unsigned(ast::UintTy::Us))) |
970d7e83 | 686 | } |
d9579d0f | 687 | fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> { |
7453a54e SL |
688 | if i < 0 { |
689 | let i = (-i) as u64; | |
690 | let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is); | |
691 | let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty)); | |
692 | self.expr_unary(sp, ast::UnOp::Neg, lit) | |
693 | } else { | |
694 | self.expr_lit(sp, ast::LitKind::Int(i as u64, ast::LitIntType::Signed(ast::IntTy::Is))) | |
695 | } | |
970d7e83 | 696 | } |
c34b1796 | 697 | fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> { |
7453a54e | 698 | self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U32))) |
c34b1796 | 699 | } |
1a4d82fc | 700 | fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> { |
7453a54e | 701 | self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U8))) |
970d7e83 | 702 | } |
1a4d82fc | 703 | fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> { |
7453a54e | 704 | self.expr_lit(sp, ast::LitKind::Bool(value)) |
970d7e83 LB |
705 | } |
706 | ||
1a4d82fc | 707 | fn expr_vec(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { |
7453a54e | 708 | self.expr(sp, ast::ExprKind::Vec(exprs)) |
970d7e83 | 709 | } |
1a4d82fc | 710 | fn expr_vec_ng(&self, sp: Span) -> P<ast::Expr> { |
e9174d1e | 711 | self.expr_call_global(sp, self.std_path(&["vec", "Vec", "new"]), |
1a4d82fc | 712 | Vec::new()) |
970d7e83 | 713 | } |
1a4d82fc JJ |
714 | fn expr_vec_slice(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { |
715 | self.expr_addr_of(sp, self.expr_vec(sp, exprs)) | |
970d7e83 | 716 | } |
1a4d82fc | 717 | fn expr_str(&self, sp: Span, s: InternedString) -> P<ast::Expr> { |
7453a54e | 718 | self.expr_lit(sp, ast::LitKind::Str(s, ast::StrStyle::Cooked)) |
970d7e83 | 719 | } |
1a4d82fc JJ |
720 | |
721 | fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> { | |
7453a54e | 722 | self.expr(sp, ast::ExprKind::Cast(expr, ty)) |
1a4d82fc JJ |
723 | } |
724 | ||
725 | ||
726 | fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { | |
e9174d1e | 727 | let some = self.std_path(&["option", "Option", "Some"]); |
1a4d82fc JJ |
728 | self.expr_call_global(sp, some, vec!(expr)) |
729 | } | |
730 | ||
731 | fn expr_none(&self, sp: Span) -> P<ast::Expr> { | |
e9174d1e SL |
732 | let none = self.std_path(&["option", "Option", "None"]); |
733 | let none = self.path_global(sp, none); | |
1a4d82fc | 734 | self.expr_path(none) |
970d7e83 | 735 | } |
1a4d82fc JJ |
736 | |
737 | ||
738 | fn expr_break(&self, sp: Span) -> P<ast::Expr> { | |
7453a54e | 739 | self.expr(sp, ast::ExprKind::Break(None)) |
970d7e83 LB |
740 | } |
741 | ||
742 | ||
1a4d82fc | 743 | fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> { |
7453a54e | 744 | self.expr(sp, ast::ExprKind::Tup(exprs)) |
1a4d82fc JJ |
745 | } |
746 | ||
747 | fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr> { | |
970d7e83 | 748 | let loc = self.codemap().lookup_char_pos(span.lo); |
1a4d82fc | 749 | let expr_file = self.expr_str(span, |
c34b1796 | 750 | token::intern_and_get_ident(&loc.file.name)); |
9346a6ac | 751 | let expr_line = self.expr_u32(span, loc.line as u32); |
1a4d82fc JJ |
752 | let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line)); |
753 | let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); | |
970d7e83 LB |
754 | self.expr_call_global( |
755 | span, | |
e9174d1e | 756 | self.std_path(&["rt", "begin_unwind"]), |
1a4d82fc JJ |
757 | vec!( |
758 | self.expr_str(span, msg), | |
759 | expr_file_line_ptr)) | |
760 | } | |
761 | ||
762 | fn expr_unreachable(&self, span: Span) -> P<ast::Expr> { | |
763 | self.expr_fail(span, | |
764 | InternedString::new( | |
765 | "internal error: entered unreachable code")) | |
766 | } | |
767 | ||
768 | fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { | |
e9174d1e | 769 | let ok = self.std_path(&["result", "Result", "Ok"]); |
1a4d82fc JJ |
770 | self.expr_call_global(sp, ok, vec!(expr)) |
771 | } | |
772 | ||
773 | fn expr_err(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { | |
e9174d1e | 774 | let err = self.std_path(&["result", "Result", "Err"]); |
1a4d82fc JJ |
775 | self.expr_call_global(sp, err, vec!(expr)) |
776 | } | |
777 | ||
778 | fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> { | |
e9174d1e | 779 | let ok = self.std_path(&["result", "Result", "Ok"]); |
85aaf69f | 780 | let ok_path = self.path_global(sp, ok); |
e9174d1e | 781 | let err = self.std_path(&["result", "Result", "Err"]); |
85aaf69f | 782 | let err_path = self.path_global(sp, err); |
1a4d82fc JJ |
783 | |
784 | let binding_variable = self.ident_of("__try_var"); | |
785 | let binding_pat = self.pat_ident(sp, binding_variable); | |
786 | let binding_expr = self.expr_ident(sp, binding_variable); | |
787 | ||
788 | // Ok(__try_var) pattern | |
789 | let ok_pat = self.pat_enum(sp, ok_path, vec!(binding_pat.clone())); | |
790 | ||
791 | // Err(__try_var) (pattern and expression resp.) | |
85aaf69f SL |
792 | let err_pat = self.pat_enum(sp, err_path.clone(), vec!(binding_pat)); |
793 | let err_inner_expr = self.expr_call(sp, self.expr_path(err_path), | |
794 | vec!(binding_expr.clone())); | |
1a4d82fc | 795 | // return Err(__try_var) |
7453a54e | 796 | let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); |
1a4d82fc JJ |
797 | |
798 | // Ok(__try_var) => __try_var | |
799 | let ok_arm = self.arm(sp, vec!(ok_pat), binding_expr); | |
800 | // Err(__try_var) => return Err(__try_var) | |
801 | let err_arm = self.arm(sp, vec!(err_pat), err_expr); | |
802 | ||
803 | // match head { Ok() => ..., Err() => ... } | |
804 | self.expr_match(sp, head, vec!(ok_arm, err_arm)) | |
970d7e83 LB |
805 | } |
806 | ||
807 | ||
7453a54e | 808 | fn pat(&self, span: Span, pat: PatKind) -> P<ast::Pat> { |
1a4d82fc | 809 | P(ast::Pat { id: ast::DUMMY_NODE_ID, node: pat, span: span }) |
970d7e83 | 810 | } |
1a4d82fc | 811 | fn pat_wild(&self, span: Span) -> P<ast::Pat> { |
7453a54e | 812 | self.pat(span, PatKind::Wild) |
970d7e83 | 813 | } |
1a4d82fc | 814 | fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> { |
7453a54e | 815 | self.pat(span, PatKind::Lit(expr)) |
970d7e83 | 816 | } |
1a4d82fc | 817 | fn pat_ident(&self, span: Span, ident: ast::Ident) -> P<ast::Pat> { |
7453a54e SL |
818 | let binding_mode = ast::BindingMode::ByValue(ast::Mutability::Immutable); |
819 | self.pat_ident_binding_mode(span, ident, binding_mode) | |
970d7e83 LB |
820 | } |
821 | ||
822 | fn pat_ident_binding_mode(&self, | |
1a4d82fc JJ |
823 | span: Span, |
824 | ident: ast::Ident, | |
825 | bm: ast::BindingMode) -> P<ast::Pat> { | |
7453a54e | 826 | let pat = PatKind::Ident(bm, Spanned{span: span, node: ident}, None); |
970d7e83 LB |
827 | self.pat(span, pat) |
828 | } | |
1a4d82fc | 829 | fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> { |
7453a54e SL |
830 | let pat = if subpats.is_empty() { |
831 | PatKind::Path(path) | |
832 | } else { | |
833 | PatKind::TupleStruct(path, Some(subpats)) | |
834 | }; | |
970d7e83 LB |
835 | self.pat(span, pat) |
836 | } | |
1a4d82fc JJ |
837 | fn pat_struct(&self, span: Span, |
838 | path: ast::Path, field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> { | |
7453a54e | 839 | let pat = PatKind::Struct(path, field_pats, false); |
970d7e83 LB |
840 | self.pat(span, pat) |
841 | } | |
1a4d82fc | 842 | fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> { |
7453a54e | 843 | self.pat(span, PatKind::Tup(pats)) |
1a4d82fc JJ |
844 | } |
845 | ||
846 | fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> { | |
e9174d1e | 847 | let some = self.std_path(&["option", "Option", "Some"]); |
1a4d82fc JJ |
848 | let path = self.path_global(span, some); |
849 | self.pat_enum(span, path, vec!(pat)) | |
850 | } | |
851 | ||
852 | fn pat_none(&self, span: Span) -> P<ast::Pat> { | |
e9174d1e | 853 | let some = self.std_path(&["option", "Option", "None"]); |
1a4d82fc JJ |
854 | let path = self.path_global(span, some); |
855 | self.pat_enum(span, path, vec!()) | |
856 | } | |
857 | ||
858 | fn pat_ok(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> { | |
e9174d1e | 859 | let some = self.std_path(&["result", "Result", "Ok"]); |
1a4d82fc JJ |
860 | let path = self.path_global(span, some); |
861 | self.pat_enum(span, path, vec!(pat)) | |
862 | } | |
863 | ||
864 | fn pat_err(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> { | |
e9174d1e | 865 | let some = self.std_path(&["result", "Result", "Err"]); |
1a4d82fc JJ |
866 | let path = self.path_global(span, some); |
867 | self.pat_enum(span, path, vec!(pat)) | |
868 | } | |
869 | ||
870 | fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm { | |
871 | ast::Arm { | |
872 | attrs: vec!(), | |
970d7e83 LB |
873 | pats: pats, |
874 | guard: None, | |
1a4d82fc | 875 | body: expr |
970d7e83 LB |
876 | } |
877 | } | |
878 | ||
1a4d82fc JJ |
879 | fn arm_unreachable(&self, span: Span) -> ast::Arm { |
880 | self.arm(span, vec!(self.pat_wild(span)), self.expr_unreachable(span)) | |
881 | } | |
882 | ||
883 | fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> { | |
7453a54e | 884 | self.expr(span, ast::ExprKind::Match(arg, arms)) |
970d7e83 LB |
885 | } |
886 | ||
1a4d82fc JJ |
887 | fn expr_if(&self, span: Span, cond: P<ast::Expr>, |
888 | then: P<ast::Expr>, els: Option<P<ast::Expr>>) -> P<ast::Expr> { | |
889 | let els = els.map(|x| self.expr_block(self.block_expr(x))); | |
7453a54e | 890 | self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els)) |
970d7e83 LB |
891 | } |
892 | ||
1a4d82fc | 893 | fn expr_loop(&self, span: Span, block: P<ast::Block>) -> P<ast::Expr> { |
7453a54e | 894 | self.expr(span, ast::ExprKind::Loop(block, None)) |
970d7e83 LB |
895 | } |
896 | ||
1a4d82fc JJ |
897 | fn lambda_fn_decl(&self, span: Span, |
898 | fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr> { | |
7453a54e | 899 | self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk)) |
970d7e83 | 900 | } |
1a4d82fc | 901 | fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr> { |
970d7e83 | 902 | let fn_decl = self.fn_decl( |
1a4d82fc | 903 | ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), |
970d7e83 LB |
904 | self.ty_infer(span)); |
905 | ||
7453a54e | 906 | self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk)) |
970d7e83 | 907 | } |
1a4d82fc JJ |
908 | fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> { |
909 | self.lambda(span, Vec::new(), blk) | |
970d7e83 LB |
910 | } |
911 | ||
1a4d82fc JJ |
912 | fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr> { |
913 | self.lambda(span, vec!(ident), blk) | |
970d7e83 LB |
914 | } |
915 | ||
1a4d82fc JJ |
916 | fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident>, |
917 | expr: P<ast::Expr>) -> P<ast::Expr> { | |
918 | self.lambda(span, ids, self.block_expr(expr)) | |
970d7e83 | 919 | } |
1a4d82fc JJ |
920 | fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr> { |
921 | self.lambda0(span, self.block_expr(expr)) | |
970d7e83 | 922 | } |
1a4d82fc JJ |
923 | fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> { |
924 | self.lambda1(span, self.block_expr(expr), ident) | |
970d7e83 LB |
925 | } |
926 | ||
1a4d82fc JJ |
927 | fn lambda_stmts(&self, |
928 | span: Span, | |
929 | ids: Vec<ast::Ident>, | |
7453a54e | 930 | stmts: Vec<ast::Stmt>) |
1a4d82fc JJ |
931 | -> P<ast::Expr> { |
932 | self.lambda(span, ids, self.block(span, stmts, None)) | |
970d7e83 | 933 | } |
7453a54e | 934 | fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr> { |
1a4d82fc | 935 | self.lambda0(span, self.block(span, stmts, None)) |
970d7e83 | 936 | } |
7453a54e | 937 | fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, |
1a4d82fc JJ |
938 | ident: ast::Ident) -> P<ast::Expr> { |
939 | self.lambda1(span, self.block(span, stmts, None), ident) | |
970d7e83 LB |
940 | } |
941 | ||
1a4d82fc | 942 | fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg { |
970d7e83 | 943 | let arg_pat = self.pat_ident(span, ident); |
1a4d82fc | 944 | ast::Arg { |
970d7e83 LB |
945 | ty: ty, |
946 | pat: arg_pat, | |
1a4d82fc | 947 | id: ast::DUMMY_NODE_ID |
970d7e83 LB |
948 | } |
949 | } | |
950 | ||
1a4d82fc JJ |
951 | // FIXME unused self |
952 | fn fn_decl(&self, inputs: Vec<ast::Arg>, output: P<ast::Ty>) -> P<ast::FnDecl> { | |
953 | P(ast::FnDecl { | |
970d7e83 | 954 | inputs: inputs, |
7453a54e | 955 | output: ast::FunctionRetTy::Ty(output), |
1a4d82fc JJ |
956 | variadic: false |
957 | }) | |
970d7e83 LB |
958 | } |
959 | ||
1a4d82fc | 960 | fn item(&self, span: Span, name: Ident, |
7453a54e | 961 | attrs: Vec<ast::Attribute>, node: ast::ItemKind) -> P<ast::Item> { |
1a4d82fc | 962 | // FIXME: Would be nice if our generated code didn't violate |
970d7e83 | 963 | // Rust coding conventions |
1a4d82fc JJ |
964 | P(ast::Item { |
965 | ident: name, | |
966 | attrs: attrs, | |
967 | id: ast::DUMMY_NODE_ID, | |
968 | node: node, | |
7453a54e | 969 | vis: ast::Visibility::Inherited, |
1a4d82fc JJ |
970 | span: span |
971 | }) | |
970d7e83 LB |
972 | } |
973 | ||
974 | fn item_fn_poly(&self, | |
1a4d82fc JJ |
975 | span: Span, |
976 | name: Ident, | |
977 | inputs: Vec<ast::Arg> , | |
978 | output: P<ast::Ty>, | |
970d7e83 | 979 | generics: Generics, |
1a4d82fc | 980 | body: P<ast::Block>) -> P<ast::Item> { |
970d7e83 LB |
981 | self.item(span, |
982 | name, | |
1a4d82fc | 983 | Vec::new(), |
7453a54e | 984 | ast::ItemKind::Fn(self.fn_decl(inputs, output), |
1a4d82fc | 985 | ast::Unsafety::Normal, |
62682a34 | 986 | ast::Constness::NotConst, |
7453a54e | 987 | Abi::Rust, |
1a4d82fc JJ |
988 | generics, |
989 | body)) | |
970d7e83 LB |
990 | } |
991 | ||
992 | fn item_fn(&self, | |
1a4d82fc JJ |
993 | span: Span, |
994 | name: Ident, | |
995 | inputs: Vec<ast::Arg> , | |
996 | output: P<ast::Ty>, | |
997 | body: P<ast::Block> | |
998 | ) -> P<ast::Item> { | |
970d7e83 LB |
999 | self.item_fn_poly( |
1000 | span, | |
1001 | name, | |
1002 | inputs, | |
1003 | output, | |
9cc50fc6 | 1004 | Generics::default(), |
970d7e83 LB |
1005 | body) |
1006 | } | |
1007 | ||
1a4d82fc | 1008 | fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant { |
b039eaaf | 1009 | let fields: Vec<_> = tys.into_iter().map(|ty| { |
54a0048b SL |
1010 | ast::StructField { |
1011 | span: ty.span, | |
b039eaaf | 1012 | ty: ty, |
54a0048b SL |
1013 | ident: None, |
1014 | vis: ast::Visibility::Inherited, | |
b039eaaf SL |
1015 | attrs: Vec::new(), |
1016 | id: ast::DUMMY_NODE_ID, | |
54a0048b | 1017 | } |
1a4d82fc | 1018 | }).collect(); |
970d7e83 | 1019 | |
b039eaaf SL |
1020 | let vdata = if fields.is_empty() { |
1021 | ast::VariantData::Unit(ast::DUMMY_NODE_ID) | |
1022 | } else { | |
1023 | ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID) | |
1024 | }; | |
1025 | ||
970d7e83 | 1026 | respan(span, |
1a4d82fc | 1027 | ast::Variant_ { |
970d7e83 | 1028 | name: name, |
1a4d82fc | 1029 | attrs: Vec::new(), |
b039eaaf | 1030 | data: vdata, |
970d7e83 | 1031 | disr_expr: None, |
970d7e83 LB |
1032 | }) |
1033 | } | |
1034 | ||
1a4d82fc JJ |
1035 | fn item_enum_poly(&self, span: Span, name: Ident, |
1036 | enum_definition: ast::EnumDef, | |
1037 | generics: Generics) -> P<ast::Item> { | |
7453a54e | 1038 | self.item(span, name, Vec::new(), ast::ItemKind::Enum(enum_definition, generics)) |
970d7e83 LB |
1039 | } |
1040 | ||
1a4d82fc JJ |
1041 | fn item_enum(&self, span: Span, name: Ident, |
1042 | enum_definition: ast::EnumDef) -> P<ast::Item> { | |
970d7e83 | 1043 | self.item_enum_poly(span, name, enum_definition, |
9cc50fc6 | 1044 | Generics::default()) |
970d7e83 LB |
1045 | } |
1046 | ||
1a4d82fc | 1047 | fn item_struct(&self, span: Span, name: Ident, |
b039eaaf | 1048 | struct_def: ast::VariantData) -> P<ast::Item> { |
970d7e83 LB |
1049 | self.item_struct_poly( |
1050 | span, | |
1051 | name, | |
1052 | struct_def, | |
9cc50fc6 | 1053 | Generics::default() |
970d7e83 | 1054 | ) |
223e47cc | 1055 | } |
970d7e83 | 1056 | |
1a4d82fc | 1057 | fn item_struct_poly(&self, span: Span, name: Ident, |
b039eaaf | 1058 | struct_def: ast::VariantData, generics: Generics) -> P<ast::Item> { |
7453a54e | 1059 | self.item(span, name, Vec::new(), ast::ItemKind::Struct(struct_def, generics)) |
223e47cc | 1060 | } |
970d7e83 | 1061 | |
1a4d82fc | 1062 | fn item_mod(&self, span: Span, inner_span: Span, name: Ident, |
85aaf69f SL |
1063 | attrs: Vec<ast::Attribute>, |
1064 | items: Vec<P<ast::Item>>) -> P<ast::Item> { | |
970d7e83 LB |
1065 | self.item( |
1066 | span, | |
1067 | name, | |
1068 | attrs, | |
7453a54e | 1069 | ast::ItemKind::Mod(ast::Mod { |
1a4d82fc | 1070 | inner: inner_span, |
970d7e83 LB |
1071 | items: items, |
1072 | }) | |
1073 | ) | |
1074 | } | |
1075 | ||
1a4d82fc JJ |
1076 | fn item_static(&self, |
1077 | span: Span, | |
1078 | name: Ident, | |
1079 | ty: P<ast::Ty>, | |
1080 | mutbl: ast::Mutability, | |
1081 | expr: P<ast::Expr>) | |
1082 | -> P<ast::Item> { | |
7453a54e | 1083 | self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, expr)) |
1a4d82fc JJ |
1084 | } |
1085 | ||
1086 | fn item_const(&self, | |
1087 | span: Span, | |
1088 | name: Ident, | |
1089 | ty: P<ast::Ty>, | |
1090 | expr: P<ast::Expr>) | |
1091 | -> P<ast::Item> { | |
7453a54e | 1092 | self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr)) |
1a4d82fc JJ |
1093 | } |
1094 | ||
1095 | fn item_ty_poly(&self, span: Span, name: Ident, ty: P<ast::Ty>, | |
1096 | generics: Generics) -> P<ast::Item> { | |
7453a54e | 1097 | self.item(span, name, Vec::new(), ast::ItemKind::Ty(ty, generics)) |
970d7e83 LB |
1098 | } |
1099 | ||
1a4d82fc | 1100 | fn item_ty(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> P<ast::Item> { |
9cc50fc6 | 1101 | self.item_ty_poly(span, name, ty, Generics::default()) |
970d7e83 LB |
1102 | } |
1103 | ||
1a4d82fc JJ |
1104 | fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute { |
1105 | respan(sp, ast::Attribute_ { | |
1106 | id: attr::mk_attr_id(), | |
b039eaaf | 1107 | style: ast::AttrStyle::Outer, |
1a4d82fc JJ |
1108 | value: mi, |
1109 | is_sugared_doc: false, | |
1110 | }) | |
970d7e83 LB |
1111 | } |
1112 | ||
1a4d82fc | 1113 | fn meta_word(&self, sp: Span, w: InternedString) -> P<ast::MetaItem> { |
7453a54e | 1114 | P(respan(sp, ast::MetaItemKind::Word(w))) |
970d7e83 | 1115 | } |
1a4d82fc JJ |
1116 | fn meta_list(&self, |
1117 | sp: Span, | |
1118 | name: InternedString, | |
1119 | mis: Vec<P<ast::MetaItem>> ) | |
1120 | -> P<ast::MetaItem> { | |
7453a54e | 1121 | P(respan(sp, ast::MetaItemKind::List(name, mis))) |
970d7e83 | 1122 | } |
1a4d82fc JJ |
1123 | fn meta_name_value(&self, |
1124 | sp: Span, | |
1125 | name: InternedString, | |
7453a54e | 1126 | value: ast::LitKind) |
1a4d82fc | 1127 | -> P<ast::MetaItem> { |
7453a54e | 1128 | P(respan(sp, ast::MetaItemKind::NameValue(name, respan(sp, value)))) |
970d7e83 LB |
1129 | } |
1130 | ||
85aaf69f SL |
1131 | fn item_use(&self, sp: Span, |
1132 | vis: ast::Visibility, vp: P<ast::ViewPath>) -> P<ast::Item> { | |
1133 | P(ast::Item { | |
1134 | id: ast::DUMMY_NODE_ID, | |
1135 | ident: special_idents::invalid, | |
1136 | attrs: vec![], | |
7453a54e | 1137 | node: ast::ItemKind::Use(vp), |
970d7e83 LB |
1138 | vis: vis, |
1139 | span: sp | |
85aaf69f | 1140 | }) |
970d7e83 LB |
1141 | } |
1142 | ||
85aaf69f | 1143 | fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> { |
1a4d82fc | 1144 | let last = path.segments.last().unwrap().identifier; |
85aaf69f | 1145 | self.item_use_simple_(sp, vis, last, path) |
970d7e83 LB |
1146 | } |
1147 | ||
85aaf69f SL |
1148 | fn item_use_simple_(&self, sp: Span, vis: ast::Visibility, |
1149 | ident: ast::Ident, path: ast::Path) -> P<ast::Item> { | |
1150 | self.item_use(sp, vis, | |
1a4d82fc JJ |
1151 | P(respan(sp, |
1152 | ast::ViewPathSimple(ident, | |
85aaf69f | 1153 | path)))) |
223e47cc | 1154 | } |
970d7e83 | 1155 | |
85aaf69f SL |
1156 | fn item_use_list(&self, sp: Span, vis: ast::Visibility, |
1157 | path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item> { | |
1a4d82fc | 1158 | let imports = imports.iter().map(|id| { |
7453a54e SL |
1159 | let item = ast::PathListItemKind::Ident { |
1160 | name: *id, | |
1161 | rename: None, | |
1162 | id: ast::DUMMY_NODE_ID, | |
1163 | }; | |
1164 | respan(sp, item) | |
1a4d82fc | 1165 | }).collect(); |
970d7e83 | 1166 | |
85aaf69f | 1167 | self.item_use(sp, vis, |
1a4d82fc JJ |
1168 | P(respan(sp, |
1169 | ast::ViewPathList(self.path(sp, path), | |
85aaf69f | 1170 | imports)))) |
1a4d82fc | 1171 | } |
223e47cc | 1172 | |
85aaf69f SL |
1173 | fn item_use_glob(&self, sp: Span, |
1174 | vis: ast::Visibility, path: Vec<ast::Ident>) -> P<ast::Item> { | |
1175 | self.item_use(sp, vis, | |
1a4d82fc | 1176 | P(respan(sp, |
85aaf69f | 1177 | ast::ViewPathGlob(self.path(sp, path))))) |
970d7e83 LB |
1178 | } |
1179 | } |