106 lines
2.4 KiB
Rust
106 lines
2.4 KiB
Rust
|
|
export fold;
|
||
|
|
export fold_crate, fold_mod, fold_fn, fold_modlist, fold_fnlist;
|
||
|
|
export default_seq_fold;
|
||
|
|
|
||
|
|
tag fold = t;
|
||
|
|
|
||
|
|
type fold_crate = fn~(fold: fold, doc: doc::cratedoc) -> doc::cratedoc;
|
||
|
|
type fold_mod = fn~(fold: fold, doc: doc::moddoc) -> doc::moddoc;
|
||
|
|
type fold_fn = fn~(fold: fold, doc: doc::fndoc) -> doc::fndoc;
|
||
|
|
type fold_modlist = fn~(fold: fold, list: doc::modlist) -> doc::modlist;
|
||
|
|
type fold_fnlist = fn~(fold: fold, list: doc::fnlist) -> doc::fnlist;
|
||
|
|
|
||
|
|
type t = {
|
||
|
|
fold_crate: fold_crate,
|
||
|
|
fold_mod: fold_mod,
|
||
|
|
fold_fn: fold_fn,
|
||
|
|
fold_modlist: fold_modlist,
|
||
|
|
fold_fnlist: fold_fnlist
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
// This exists because fn types don't infer correctly as record
|
||
|
|
// initializers, but they do as function arguments
|
||
|
|
fn mk_fold(
|
||
|
|
fold_crate: fold_crate,
|
||
|
|
fold_mod: fold_mod,
|
||
|
|
fold_fn: fold_fn,
|
||
|
|
fold_modlist: fold_modlist,
|
||
|
|
fold_fnlist: fold_fnlist
|
||
|
|
) -> fold {
|
||
|
|
fold({
|
||
|
|
fold_crate: fold_crate,
|
||
|
|
fold_mod: fold_mod,
|
||
|
|
fold_fn: fold_fn,
|
||
|
|
fold_modlist: fold_modlist,
|
||
|
|
fold_fnlist: fold_fnlist
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold() -> fold {
|
||
|
|
mk_fold(
|
||
|
|
default_seq_fold_crate,
|
||
|
|
default_seq_fold_mod,
|
||
|
|
default_seq_fold_fn,
|
||
|
|
default_seq_fold_modlist,
|
||
|
|
default_seq_fold_fnlist
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold_crate(
|
||
|
|
fold: fold,
|
||
|
|
doc: doc::cratedoc
|
||
|
|
) -> doc::cratedoc {
|
||
|
|
~{
|
||
|
|
topmod: fold.fold_mod(fold, doc.topmod)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold_mod(
|
||
|
|
fold: fold,
|
||
|
|
doc: doc::moddoc
|
||
|
|
) -> doc::moddoc {
|
||
|
|
~{
|
||
|
|
name: doc.name,
|
||
|
|
mods: fold.fold_modlist(fold, doc.mods),
|
||
|
|
fns: fold.fold_fnlist(fold, doc.fns)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold_fn(
|
||
|
|
_fold: fold,
|
||
|
|
doc: doc::fndoc
|
||
|
|
) -> doc::fndoc {
|
||
|
|
doc
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold_modlist(
|
||
|
|
fold: fold,
|
||
|
|
list: doc::modlist
|
||
|
|
) -> doc::modlist {
|
||
|
|
doc::modlist(vec::map(*list) {|doc|
|
||
|
|
fold.fold_mod(fold, doc)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
fn default_seq_fold_fnlist(
|
||
|
|
fold: fold,
|
||
|
|
list: doc::fnlist
|
||
|
|
) -> doc::fnlist {
|
||
|
|
doc::fnlist(vec::map(*list) {|doc|
|
||
|
|
fold.fold_fn(fold, doc)
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
#[test]
|
||
|
|
fn default_fold_should_produce_same_doc() {
|
||
|
|
let source = "mod a { fn b() { } mod c { fn d() { } } }";
|
||
|
|
let ast = parse::from_str(source);
|
||
|
|
let doc = extract::extract(ast, "");
|
||
|
|
let fld = default_seq_fold();
|
||
|
|
let folded = fld.fold_crate(fld, doc);
|
||
|
|
assert doc == folded;
|
||
|
|
}
|
||
|
|
}
|