]>
git.proxmox.com Git - rustc.git/blob - src/libsyntax/ext/deriving/primitive.rs
4fe9aefa1a4dfe51a5080b51e47a7bb76a266379
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.
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.
11 use ast
::{MetaItem, Expr}
;
14 use ext
::base
::{ExtCtxt, Annotatable}
;
15 use ext
::build
::AstBuilder
;
16 use ext
::deriving
::generic
::*;
17 use ext
::deriving
::generic
::ty
::*;
18 use parse
::token
::InternedString
;
21 pub fn expand_deriving_from_primitive(cx
: &mut ExtCtxt
,
25 push
: &mut FnMut(Annotatable
))
27 let inline
= cx
.meta_word(span
, InternedString
::new("inline"));
28 let attrs
= vec
!(cx
.attribute(span
, inline
));
29 let trait_def
= TraitDef
{
31 attributes
: Vec
::new(),
32 path
: path_std
!(cx
, core
::num
::FromPrimitive
),
33 additional_bounds
: Vec
::new(),
34 generics
: LifetimeBounds
::empty(),
38 generics
: LifetimeBounds
::empty(),
40 args
: vec
!(Literal(path_local
!(i64))),
41 ret_ty
: Literal(Path
::new_(pathvec_std
!(cx
, core
::option
::Option
),
43 vec
!(Box
::new(Self_
)),
45 // #[inline] liable to cause code-bloat
46 attributes
: attrs
.clone(),
47 combine_substructure
: combine_substructure(Box
::new(|c
, s
, sub
| {
48 cs_from("i64", c
, s
, sub
)
53 generics
: LifetimeBounds
::empty(),
55 args
: vec
!(Literal(path_local
!(u64))),
56 ret_ty
: Literal(Path
::new_(pathvec_std
!(cx
, core
::option
::Option
),
58 vec
!(Box
::new(Self_
)),
60 // #[inline] liable to cause code-bloat
62 combine_substructure
: combine_substructure(Box
::new(|c
, s
, sub
| {
63 cs_from("u64", c
, s
, sub
)
67 associated_types
: Vec
::new(),
70 trait_def
.expand(cx
, mitem
, &item
, push
)
73 fn cs_from(name
: &str, cx
: &mut ExtCtxt
, trait_span
: Span
, substr
: &Substructure
) -> P
<Expr
> {
74 let n
= match (substr
.nonself_args
.len(), substr
.nonself_args
.get(0)) {
75 (1, Some(o_f
)) => o_f
,
76 _
=> cx
.span_bug(trait_span
, "incorrect number of arguments in `derive(FromPrimitive)`")
79 match *substr
.fields
{
81 cx
.span_err(trait_span
, "`FromPrimitive` cannot be derived for structs");
82 return cx
.expr_fail(trait_span
, InternedString
::new(""));
84 StaticEnum(enum_def
, _
) => {
85 if enum_def
.variants
.is_empty() {
86 cx
.span_err(trait_span
,
87 "`FromPrimitive` cannot be derived for enums with no variants");
88 return cx
.expr_fail(trait_span
, InternedString
::new(""));
91 let mut arms
= Vec
::new();
93 for variant
in &enum_def
.variants
{
94 match variant
.node
.kind
{
95 ast
::TupleVariantKind(ref args
) => {
97 cx
.span_err(trait_span
,
98 "`FromPrimitive` cannot be derived for \
99 enum variants with arguments");
100 return cx
.expr_fail(trait_span
,
101 InternedString
::new(""));
103 let span
= variant
.span
;
105 // expr for `$n == $variant as $name`
106 let path
= cx
.path(span
, vec
![substr
.type_ident
, variant
.node
.name
]);
107 let variant
= cx
.expr_path(path
);
108 let ty
= cx
.ty_ident(span
, cx
.ident_of(name
));
109 let cast
= cx
.expr_cast(span
, variant
.clone(), ty
);
110 let guard
= cx
.expr_binary(span
, ast
::BiEq
, n
.clone(), cast
);
112 // expr for `Some($variant)`
113 let body
= cx
.expr_some(span
, variant
);
115 // arm for `_ if $guard => $body`
118 pats
: vec
!(cx
.pat_wild(span
)),
125 ast
::StructVariantKind(_
) => {
126 cx
.span_err(trait_span
,
127 "`FromPrimitive` cannot be derived for enums \
128 with struct variants");
129 return cx
.expr_fail(trait_span
,
130 InternedString
::new(""));
135 // arm for `_ => None`
138 pats
: vec
!(cx
.pat_wild(trait_span
)),
140 body
: cx
.expr_none(trait_span
),
144 cx
.expr_match(trait_span
, n
.clone(), arms
)
146 _
=> cx
.span_bug(trait_span
, "expected StaticEnum in derive(FromPrimitive)")