diff options
author | Manish Goregaokar <manishsmail@gmail.com> | 2014-09-24 01:15:12 +0530 |
---|---|---|
committer | Manish Goregaokar <manishsmail@gmail.com> | 2014-09-24 01:15:22 +0530 |
commit | 3b7e07699e060887c1254228a7d8307da0ae0e14 (patch) | |
tree | 5a1f4efb4b0f247d0d06b7043e3af22ffb4cf471 /components/plugins/jstraceable.rs | |
parent | 27f3bcd7183d836bd454e687706b4e76d6d3b312 (diff) | |
download | servo-3b7e07699e060887c1254228a7d8307da0ae0e14.tar.gz servo-3b7e07699e060887c1254228a7d8307da0ae0e14.zip |
Add #[jstraceable] syntax extension
Diffstat (limited to 'components/plugins/jstraceable.rs')
-rw-r--r-- | components/plugins/jstraceable.rs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/components/plugins/jstraceable.rs b/components/plugins/jstraceable.rs new file mode 100644 index 00000000000..5a113ab1691 --- /dev/null +++ b/components/plugins/jstraceable.rs @@ -0,0 +1,76 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use syntax::ext::base::ExtCtxt; +use syntax::codemap::Span; +use syntax::ptr::P; +use syntax::ast::{Item, MetaItem, Expr}; +use syntax::ast; +use syntax::ext::build::AstBuilder; +use syntax::ext::deriving::generic::{combine_substructure, EnumMatching, FieldInfo, MethodDef, Struct, Substructure, TraitDef, ty}; + + pub fn expand_jstraceable(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, item: &Item, push: |P<Item>|) { + let trait_def = TraitDef { + span: span, + attributes: Vec::new(), + path: ty::Path::new(vec!("dom","bindings","trace","JSTraceable")), + additional_bounds: Vec::new(), + generics: ty::LifetimeBounds::empty(), + methods: vec!( + MethodDef { + name: "trace", + generics: ty::LifetimeBounds::empty(), + explicit_self: ty::borrowed_explicit_self(), + args: vec!(ty::Ptr(box ty::Literal(ty::Path::new(vec!("js","jsapi","JSTracer"))), ty::Raw(ast::MutMutable))), + ret_ty: ty::nil_ty(), + attributes: vec!(), + combine_substructure: combine_substructure(|a, b, c| { + jstraceable_substructure(a, b, c) + }) + } + ) + }; + trait_def.expand(cx, mitem, item, push) +} + +// Mostly copied from syntax::ext::deriving::hash +fn jstraceable_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> { + let state_expr = match substr.nonself_args { + [ref state_expr] => state_expr, + _ => cx.span_bug(trait_span, "incorrect number of arguments in `jstraceable`") + }; + let hash_ident = substr.method_ident; + let call_hash = |span, thing_expr| { + let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr.clone())); + cx.stmt_expr(expr) + }; + let mut stmts = Vec::new(); + + let fields = match *substr.fields { + Struct(ref fs) => fs, + EnumMatching(index, variant, ref fs) => { + // Determine the discriminant. We will feed this value to the byte + // iteration function. + let discriminant = match variant.node.disr_expr { + Some(ref d) => d.clone(), + None => cx.expr_uint(trait_span, index) + }; + + stmts.push(call_hash(trait_span, discriminant)); + + fs + } + _ => cx.span_bug(trait_span, "impossible substructure in `jstraceable`") + }; + + for &FieldInfo { ref self_, span, .. } in fields.iter() { + stmts.push(call_hash(span, self_.clone())); + } + + if stmts.len() == 0 { + cx.span_bug(trait_span, "#[jstraceable] needs at least one field"); + } + + cx.expr_block(cx.block(trait_span, stmts, None)) +} |