fold.rs 11.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11

12
use doc;
13 14
#[cfg(test)] use extract;
#[cfg(test)] use parse;
15

16 17 18 19 20 21 22 23
pub struct Fold<T> {
    ctxt: T,
    fold_doc: FoldDoc<T>,
    fold_crate: FoldCrate<T>,
    fold_item: FoldItem<T>,
    fold_mod: FoldMod<T>,
    fold_nmod: FoldNmod<T>,
    fold_fn: FoldFn<T>,
S
Sangeun Kim 已提交
24
    fold_static: FoldStatic<T>,
25 26 27 28 29 30
    fold_enum: FoldEnum<T>,
    fold_trait: FoldTrait<T>,
    fold_impl: FoldImpl<T>,
    fold_type: FoldType<T>,
    fold_struct: FoldStruct<T>
}
B
Brian Anderson 已提交
31

32
impl<T:Clone> Clone for Fold<T> {
33
    fn clone(&self) -> Fold<T> {
34
        Fold {
35
            ctxt: self.ctxt.clone(),
36 37 38 39 40 41
            fold_doc: self.fold_doc,
            fold_crate: self.fold_crate,
            fold_item: self.fold_item,
            fold_mod: self.fold_mod,
            fold_nmod: self.fold_nmod,
            fold_fn: self.fold_fn,
S
Sangeun Kim 已提交
42
            fold_static: self.fold_static,
43 44 45 46 47
            fold_enum: self.fold_enum,
            fold_trait: self.fold_trait,
            fold_impl: self.fold_impl,
            fold_type: self.fold_type,
            fold_struct: self.fold_struct
48
        }
49 50 51
    }
}

52 53 54 55 56 57
type FoldDoc<T> = @fn(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc;
type FoldCrate<T> = @fn(fold: &Fold<T>, doc: doc::CrateDoc) -> doc::CrateDoc;
type FoldItem<T> = @fn(fold: &Fold<T>, doc: doc::ItemDoc) -> doc::ItemDoc;
type FoldMod<T> = @fn(fold: &Fold<T>, doc: doc::ModDoc) -> doc::ModDoc;
type FoldNmod<T> = @fn(fold: &Fold<T>, doc: doc::NmodDoc) -> doc::NmodDoc;
type FoldFn<T> = @fn(fold: &Fold<T>, doc: doc::FnDoc) -> doc::FnDoc;
S
Sangeun Kim 已提交
58
type FoldStatic<T> = @fn(fold: &Fold<T>, doc: doc::StaticDoc) -> doc::StaticDoc;
59 60 61 62 63
type FoldEnum<T> = @fn(fold: &Fold<T>, doc: doc::EnumDoc) -> doc::EnumDoc;
type FoldTrait<T> = @fn(fold: &Fold<T>, doc: doc::TraitDoc) -> doc::TraitDoc;
type FoldImpl<T> = @fn(fold: &Fold<T>, doc: doc::ImplDoc) -> doc::ImplDoc;
type FoldType<T> = @fn(fold: &Fold<T>, doc: doc::TyDoc) -> doc::TyDoc;
type FoldStruct<T> = @fn(fold: &Fold<T>,
B
Brian Anderson 已提交
64
                         doc: doc::StructDoc) -> doc::StructDoc;
B
Brian Anderson 已提交
65 66 67

// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
68
fn mk_fold<T>(
B
Brian Anderson 已提交
69 70 71 72 73 74 75
    ctxt: T,
    fold_doc: FoldDoc<T>,
    fold_crate: FoldCrate<T>,
    fold_item: FoldItem<T>,
    fold_mod: FoldMod<T>,
    fold_nmod: FoldNmod<T>,
    fold_fn: FoldFn<T>,
S
Sangeun Kim 已提交
76
    fold_static: FoldStatic<T>,
B
Brian Anderson 已提交
77 78 79 80 81
    fold_enum: FoldEnum<T>,
    fold_trait: FoldTrait<T>,
    fold_impl: FoldImpl<T>,
    fold_type: FoldType<T>,
    fold_struct: FoldStruct<T>
B
Brian Anderson 已提交
82
) -> Fold<T> {
83
    Fold {
L
Luqman Aden 已提交
84 85 86 87 88 89 90
        ctxt: ctxt,
        fold_doc: fold_doc,
        fold_crate: fold_crate,
        fold_item: fold_item,
        fold_mod: fold_mod,
        fold_nmod: fold_nmod,
        fold_fn: fold_fn,
S
Sangeun Kim 已提交
91
        fold_static: fold_static,
L
Luqman Aden 已提交
92 93 94 95 96
        fold_enum: fold_enum,
        fold_trait: fold_trait,
        fold_impl: fold_impl,
        fold_type: fold_type,
        fold_struct: fold_struct
97
    }
B
Brian Anderson 已提交
98 99
}

100
pub fn default_any_fold<T:Clone>(ctxt: T) -> Fold<T> {
101
    mk_fold(
L
Luqman Aden 已提交
102
        ctxt,
B
Brian Anderson 已提交
103 104 105 106 107 108
        |f, d| default_seq_fold_doc(f, d),
        |f, d| default_seq_fold_crate(f, d),
        |f, d| default_seq_fold_item(f, d),
        |f, d| default_any_fold_mod(f, d),
        |f, d| default_any_fold_nmod(f, d),
        |f, d| default_seq_fold_fn(f, d),
S
Sangeun Kim 已提交
109
        |f, d| default_seq_fold_static(f, d),
B
Brian Anderson 已提交
110
        |f, d| default_seq_fold_enum(f, d),
111
        |f, d| default_seq_fold_trait(f, d),
B
Brian Anderson 已提交
112
        |f, d| default_seq_fold_impl(f, d),
113 114
        |f, d| default_seq_fold_type(f, d),
        |f, d| default_seq_fold_struct(f, d)
115 116 117
    )
}

118
pub fn default_seq_fold<T:Clone>(ctxt: T) -> Fold<T> {
B
Brian Anderson 已提交
119
    mk_fold(
L
Luqman Aden 已提交
120
        ctxt,
B
Brian Anderson 已提交
121 122 123 124 125 126
        |f, d| default_seq_fold_doc(f, d),
        |f, d| default_seq_fold_crate(f, d),
        |f, d| default_seq_fold_item(f, d),
        |f, d| default_seq_fold_mod(f, d),
        |f, d| default_seq_fold_nmod(f, d),
        |f, d| default_seq_fold_fn(f, d),
S
Sangeun Kim 已提交
127
        |f, d| default_seq_fold_static(f, d),
B
Brian Anderson 已提交
128
        |f, d| default_seq_fold_enum(f, d),
129
        |f, d| default_seq_fold_trait(f, d),
B
Brian Anderson 已提交
130
        |f, d| default_seq_fold_impl(f, d),
131 132
        |f, d| default_seq_fold_type(f, d),
        |f, d| default_seq_fold_struct(f, d)
B
Brian Anderson 已提交
133 134 135
    )
}

136
pub fn default_par_fold<T:Clone>(ctxt: T) -> Fold<T> {
137
    mk_fold(
L
Luqman Aden 已提交
138
        ctxt,
B
Brian Anderson 已提交
139 140 141 142 143 144
        |f, d| default_seq_fold_doc(f, d),
        |f, d| default_seq_fold_crate(f, d),
        |f, d| default_seq_fold_item(f, d),
        |f, d| default_par_fold_mod(f, d),
        |f, d| default_par_fold_nmod(f, d),
        |f, d| default_seq_fold_fn(f, d),
S
Sangeun Kim 已提交
145
        |f, d| default_seq_fold_static(f, d),
B
Brian Anderson 已提交
146
        |f, d| default_seq_fold_enum(f, d),
147
        |f, d| default_seq_fold_trait(f, d),
B
Brian Anderson 已提交
148
        |f, d| default_seq_fold_impl(f, d),
149 150
        |f, d| default_seq_fold_type(f, d),
        |f, d| default_seq_fold_struct(f, d)
151 152 153
    )
}

B
Brian Anderson 已提交
154
pub fn default_seq_fold_doc<T>(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc {
155
    doc::Doc {
156
        pages: do doc.pages.iter().map |page| {
157
            match (*page).clone() {
B
Brian Anderson 已提交
158
              doc::CratePage(doc) => {
159
                doc::CratePage((fold.fold_crate)(fold, doc))
160
              }
B
Brian Anderson 已提交
161 162
              doc::ItemPage(doc) => {
                doc::ItemPage(fold_ItemTag(fold, doc))
163 164
              }
            }
165
        }.collect(),
166 167
        .. doc
    }
168 169
}

B
Brian Anderson 已提交
170
pub fn default_seq_fold_crate<T>(
171
    fold: &Fold<T>,
B
Brian Anderson 已提交
172
    doc: doc::CrateDoc
B
Brian Anderson 已提交
173
) -> doc::CrateDoc {
174
    doc::CrateDoc {
175
        topmod: (fold.fold_mod)(fold, doc.topmod.clone())
B
Brian Anderson 已提交
176 177 178
    }
}

B
Brian Anderson 已提交
179
pub fn default_seq_fold_item<T>(
180
    _fold: &Fold<T>,
B
Brian Anderson 已提交
181
    doc: doc::ItemDoc
B
Brian Anderson 已提交
182
) -> doc::ItemDoc {
B
Brian Anderson 已提交
183 184 185
    doc
}

186
pub fn default_any_fold_mod<T:Clone>(
187
    fold: &Fold<T>,
B
Brian Anderson 已提交
188
    doc: doc::ModDoc
B
Brian Anderson 已提交
189
) -> doc::ModDoc {
190
    doc::ModDoc {
191
        item: (fold.fold_item)(fold, doc.item.clone()),
192
        items: doc.items.iter().map(|ItemTag| {
193
            fold_ItemTag(fold, (*ItemTag).clone())
194
        }).collect(),
195 196
        .. doc
    }
197 198
}

B
Brian Anderson 已提交
199
pub fn default_seq_fold_mod<T>(
200
    fold: &Fold<T>,
B
Brian Anderson 已提交
201
    doc: doc::ModDoc
B
Brian Anderson 已提交
202
) -> doc::ModDoc {
203
    doc::ModDoc {
204
        item: (fold.fold_item)(fold, doc.item.clone()),
205
        items: doc.items.iter().map(|ItemTag| {
206
            fold_ItemTag(fold, (*ItemTag).clone())
207
        }).collect(),
208 209
        .. doc
    }
210 211
}

212
pub fn default_par_fold_mod<T:Clone>(
213
    fold: &Fold<T>,
B
Brian Anderson 已提交
214
    doc: doc::ModDoc
B
Brian Anderson 已提交
215
) -> doc::ModDoc {
216
    doc::ModDoc {
217
        item: (fold.fold_item)(fold, doc.item.clone()),
218
        items: doc.items.iter().map(|ItemTag| {
219
            fold_ItemTag(fold, (*ItemTag).clone())
220
        }).collect(),
221 222
        .. doc
    }
B
Brian Anderson 已提交
223 224
}

225
pub fn default_any_fold_nmod<T:Clone>(
226
    fold: &Fold<T>,
B
Brian Anderson 已提交
227
    doc: doc::NmodDoc
B
Brian Anderson 已提交
228
) -> doc::NmodDoc {
229
    doc::NmodDoc {
230
        item: (fold.fold_item)(fold, doc.item.clone()),
231
        fns: doc.fns.iter().map(|FnDoc| {
232
            (fold.fold_fn)(fold, (*FnDoc).clone())
233
        }).collect(),
B
Brian Anderson 已提交
234
        .. doc
235 236 237
    }
}

B
Brian Anderson 已提交
238
pub fn default_seq_fold_nmod<T>(
239
    fold: &Fold<T>,
B
Brian Anderson 已提交
240
    doc: doc::NmodDoc
B
Brian Anderson 已提交
241
) -> doc::NmodDoc {
242
    doc::NmodDoc {
243
        item: (fold.fold_item)(fold, doc.item.clone()),
244
        fns: doc.fns.iter().map(|FnDoc| {
245
            (fold.fold_fn)(fold, (*FnDoc).clone())
246
        }).collect(),
B
Brian Anderson 已提交
247
        .. doc
248 249 250
    }
}

251
pub fn default_par_fold_nmod<T:Clone>(
252
    fold: &Fold<T>,
B
Brian Anderson 已提交
253
    doc: doc::NmodDoc
B
Brian Anderson 已提交
254
) -> doc::NmodDoc {
255
    doc::NmodDoc {
256
        item: (fold.fold_item)(fold, doc.item.clone()),
257
        fns: doc.fns.iter().map(|FnDoc| {
258
            (fold.fold_fn)(fold, (*FnDoc).clone())
259
        }).collect(),
B
Brian Anderson 已提交
260
        .. doc
261
    }
262 263
}

B
Brian Anderson 已提交
264
pub fn fold_ItemTag<T>(fold: &Fold<T>, doc: doc::ItemTag) -> doc::ItemTag {
265
    match doc {
B
Brian Anderson 已提交
266
      doc::ModTag(ModDoc) => {
267
        doc::ModTag((fold.fold_mod)(fold, ModDoc))
268
      }
B
Brian Anderson 已提交
269
      doc::NmodTag(nModDoc) => {
270
        doc::NmodTag((fold.fold_nmod)(fold, nModDoc))
271
      }
B
Brian Anderson 已提交
272
      doc::FnTag(FnDoc) => {
273
        doc::FnTag((fold.fold_fn)(fold, FnDoc))
274
      }
S
Sangeun Kim 已提交
275 276
      doc::StaticTag(StaticDoc) => {
        doc::StaticTag((fold.fold_static)(fold, StaticDoc))
277
      }
B
Brian Anderson 已提交
278
      doc::EnumTag(EnumDoc) => {
279
        doc::EnumTag((fold.fold_enum)(fold, EnumDoc))
280
      }
B
Brian Anderson 已提交
281
      doc::TraitTag(TraitDoc) => {
282
        doc::TraitTag((fold.fold_trait)(fold, TraitDoc))
283
      }
B
Brian Anderson 已提交
284
      doc::ImplTag(ImplDoc) => {
285
        doc::ImplTag((fold.fold_impl)(fold, ImplDoc))
286
      }
B
Brian Anderson 已提交
287
      doc::TyTag(TyDoc) => {
288
        doc::TyTag((fold.fold_type)(fold, TyDoc))
289
      }
290
      doc::StructTag(StructDoc) => {
291
        doc::StructTag((fold.fold_struct)(fold, StructDoc))
292
      }
293 294 295
    }
}

B
Brian Anderson 已提交
296
pub fn default_seq_fold_fn<T>(
297
    fold: &Fold<T>,
B
Brian Anderson 已提交
298
    doc: doc::FnDoc
B
Brian Anderson 已提交
299
) -> doc::FnDoc {
300
    doc::SimpleItemDoc {
301
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
302
        .. doc
B
Brian Anderson 已提交
303
    }
B
Brian Anderson 已提交
304 305
}

S
Sangeun Kim 已提交
306
pub fn default_seq_fold_static<T>(
307
    fold: &Fold<T>,
S
Sangeun Kim 已提交
308 309
    doc: doc::StaticDoc
) -> doc::StaticDoc {
310
    doc::SimpleItemDoc {
311
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
312
        .. doc
B
Brian Anderson 已提交
313
    }
314 315
}

B
Brian Anderson 已提交
316
pub fn default_seq_fold_enum<T>(
317
    fold: &Fold<T>,
B
Brian Anderson 已提交
318
    doc: doc::EnumDoc
B
Brian Anderson 已提交
319
) -> doc::EnumDoc {
320
    doc::EnumDoc {
321
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
322
        .. doc
B
Brian Anderson 已提交
323
    }
B
Brian Anderson 已提交
324 325
}

B
Brian Anderson 已提交
326
pub fn default_seq_fold_trait<T>(
327
    fold: &Fold<T>,
B
Brian Anderson 已提交
328
    doc: doc::TraitDoc
B
Brian Anderson 已提交
329
) -> doc::TraitDoc {
330
    doc::TraitDoc {
331
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
332
        .. doc
B
Brian Anderson 已提交
333
    }
334 335
}

B
Brian Anderson 已提交
336
pub fn default_seq_fold_impl<T>(
337
    fold: &Fold<T>,
B
Brian Anderson 已提交
338
    doc: doc::ImplDoc
B
Brian Anderson 已提交
339
) -> doc::ImplDoc {
340
    doc::ImplDoc {
341
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
342
        .. doc
B
Brian Anderson 已提交
343
    }
B
Brian Anderson 已提交
344 345
}

B
Brian Anderson 已提交
346
pub fn default_seq_fold_type<T>(
347
    fold: &Fold<T>,
B
Brian Anderson 已提交
348
    doc: doc::TyDoc
B
Brian Anderson 已提交
349
) -> doc::TyDoc {
350
    doc::SimpleItemDoc {
351
        item: (fold.fold_item)(fold, doc.item.clone()),
B
Brian Anderson 已提交
352
        .. doc
B
Brian Anderson 已提交
353
    }
354 355
}

B
Brian Anderson 已提交
356
pub fn default_seq_fold_struct<T>(
357
    fold: &Fold<T>,
B
Brian Anderson 已提交
358
    doc: doc::StructDoc
359
) -> doc::StructDoc {
360
    doc::StructDoc {
361
        item: (fold.fold_item)(fold, doc.item.clone()),
362 363 364 365
        .. doc
    }
}

366 367
#[test]
fn default_fold_should_produce_same_doc() {
368
    let source = @"mod a { fn b() { } mod c { fn d() { } } }";
369
    let ast = parse::from_str(source);
370
    let doc = extract::extract(ast, ~"");
371
    let fld = default_seq_fold(());
372
    let folded = (fld.fold_doc)(&fld, doc.clone());
373
    assert_eq!(doc, folded);
374 375 376
}

#[test]
S
Sangeun Kim 已提交
377
fn default_fold_should_produce_same_statics() {
378
    let source = @"static a: int = 0;";
379
    let ast = parse::from_str(source);
380
    let doc = extract::extract(ast, ~"");
381
    let fld = default_seq_fold(());
382
    let folded = (fld.fold_doc)(&fld, doc.clone());
383
    assert_eq!(doc, folded);
B
Brian Anderson 已提交
384 385 386 387
}

#[test]
fn default_fold_should_produce_same_enums() {
388
    let source = @"enum a { b }";
389
    let ast = parse::from_str(source);
390
    let doc = extract::extract(ast, ~"");
B
Brian Anderson 已提交
391
    let fld = default_seq_fold(());
392
    let folded = (fld.fold_doc)(&fld, doc.clone());
393
    assert_eq!(doc, folded);
394 395 396 397
}

#[test]
fn default_parallel_fold_should_produce_same_doc() {
398
    let source = @"mod a { fn b() { } mod c { fn d() { } } }";
399
    let ast = parse::from_str(source);
400
    let doc = extract::extract(ast, ~"");
401
    let fld = default_par_fold(());
402
    let folded = (fld.fold_doc)(&fld, doc.clone());
403
    assert_eq!(doc, folded);
404
}