Skip to content

Commit a0e123e

Browse files
committed
syntax: add #[deriving(Default)] syntax extension
1 parent ca47eeb commit a0e123e

File tree

3 files changed

+123
-2
lines changed

3 files changed

+123
-2
lines changed

src/libextra/glob.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,17 @@ fn list_dir_sorted(path: &Path) -> ~[Path] {
137137
/**
138138
* A compiled Unix shell style pattern.
139139
*/
140-
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Zero)]
140+
#[cfg(stage0)]
141+
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)]
142+
pub struct Pattern {
143+
priv tokens: ~[PatternToken]
144+
}
145+
146+
/**
147+
* A compiled Unix shell style pattern.
148+
*/
149+
#[cfg(not(stage0))]
150+
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)]
141151
pub struct Pattern {
142152
priv tokens: ~[PatternToken]
143153
}
@@ -458,7 +468,37 @@ fn is_sep(c: char) -> bool {
458468
/**
459469
* Configuration options to modify the behaviour of `Pattern::matches_with(..)`
460470
*/
461-
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Zero)]
471+
#[cfg(stage0)]
472+
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes)]
473+
pub struct MatchOptions {
474+
475+
/**
476+
* Whether or not patterns should be matched in a case-sensitive manner. This
477+
* currently only considers upper/lower case relationships between ASCII characters,
478+
* but in future this might be extended to work with Unicode.
479+
*/
480+
case_sensitive: bool,
481+
482+
/**
483+
* If this is true then path-component separator characters (e.g. `/` on Posix)
484+
* must be matched by a literal `/`, rather than by `*` or `?` or `[...]`
485+
*/
486+
require_literal_separator: bool,
487+
488+
/**
489+
* If this is true then paths that contain components that start with a `.` will
490+
* not match unless the `.` appears literally in the pattern: `*`, `?` or `[...]`
491+
* will not match. This is useful because such files are conventionally considered
492+
* hidden on Unix systems and it might be desirable to skip them when listing files.
493+
*/
494+
require_literal_leading_dot: bool
495+
}
496+
497+
/**
498+
* Configuration options to modify the behaviour of `Pattern::matches_with(..)`
499+
*/
500+
#[cfg(not(stage0))]
501+
#[deriving(Clone, Eq, TotalEq, Ord, TotalOrd, IterBytes, Default)]
462502
pub struct MatchOptions {
463503
464504
/**

src/libsyntax/ext/deriving/default.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2012-2013 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 ast::{MetaItem, item, Expr};
12+
use codemap::Span;
13+
use ext::base::ExtCtxt;
14+
use ext::build::AstBuilder;
15+
use ext::deriving::generic::*;
16+
17+
use std::vec;
18+
19+
pub fn expand_deriving_default(cx: @ExtCtxt,
20+
span: Span,
21+
mitem: @MetaItem,
22+
in_items: ~[@item])
23+
-> ~[@item] {
24+
let trait_def = TraitDef {
25+
path: Path::new(~["std", "default", "Default"]),
26+
additional_bounds: ~[],
27+
generics: LifetimeBounds::empty(),
28+
methods: ~[
29+
MethodDef {
30+
name: "default",
31+
generics: LifetimeBounds::empty(),
32+
explicit_self: None,
33+
args: ~[],
34+
ret_ty: Self,
35+
const_nonmatching: false,
36+
combine_substructure: default_substructure
37+
},
38+
]
39+
};
40+
trait_def.expand(cx, span, mitem, in_items)
41+
}
42+
43+
fn default_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
44+
let default_ident = ~[
45+
cx.ident_of("std"),
46+
cx.ident_of("default"),
47+
cx.ident_of("Default"),
48+
cx.ident_of("default")
49+
];
50+
let default_call = || {
51+
cx.expr_call_global(span, default_ident.clone(), ~[])
52+
};
53+
54+
return match *substr.fields {
55+
StaticStruct(_, ref summary) => {
56+
match *summary {
57+
Left(count) => {
58+
if count == 0 {
59+
cx.expr_ident(span, substr.type_ident)
60+
} else {
61+
let exprs = vec::from_fn(count, |_| default_call());
62+
cx.expr_call_ident(span, substr.type_ident, exprs)
63+
}
64+
}
65+
Right(ref fields) => {
66+
let default_fields = do fields.map |ident| {
67+
cx.field_imm(span, *ident, default_call())
68+
};
69+
cx.expr_struct_ident(span, substr.type_ident, default_fields)
70+
}
71+
}
72+
}
73+
StaticEnum(*) => {
74+
cx.span_fatal(span, "`Default` cannot be derived for enums, \
75+
only structs")
76+
}
77+
_ => cx.bug("Non-static method in `deriving(Default)`")
78+
};
79+
}

src/libsyntax/ext/deriving/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub mod decodable;
3131
pub mod rand;
3232
pub mod to_str;
3333
pub mod zero;
34+
pub mod default;
3435

3536
#[path="cmp/eq.rs"]
3637
pub mod eq;
@@ -97,6 +98,7 @@ pub fn expand_meta_deriving(cx: @ExtCtxt,
9798

9899
"ToStr" => expand!(to_str::expand_deriving_to_str),
99100
"Zero" => expand!(zero::expand_deriving_zero),
101+
"Default" => expand!(default::expand_deriving_default),
100102

101103
ref tname => {
102104
cx.span_err(titem.span, fmt!("unknown \

0 commit comments

Comments
 (0)