From c0d08a6c2e049b6b2daabe946fb3d3a33fbcc372 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Tue, 2 Sep 2014 07:58:17 +1000 Subject: [PATCH] Revert "Move PropertyBitField to a syntax extension." This reverts commit d6002a0a50f4c9fab7bcaf592b296123d33ac212. --- src/components/macros/macros.rs | 121 +------------------- src/components/style/properties/mod.rs.mako | 85 ++++++++++---- 2 files changed, 65 insertions(+), 141 deletions(-) diff --git a/src/components/macros/macros.rs b/src/components/macros/macros.rs index ecd8915dbc4..fabfc8bb7c0 100644 --- a/src/components/macros/macros.rs +++ b/src/components/macros/macros.rs @@ -4,133 +4,14 @@ #![crate_name = "macros"] #![crate_type = "rlib"] -#![crate_type = "dylib"] -#![feature(macro_rules, plugin_registrar, quote)] +#![feature(macro_rules)] //! Exports macros for use in other Servo crates. #[cfg(test)] extern crate sync; -extern crate rustc; -extern crate syntax; - -use syntax::ast; -use syntax::codemap::Span; -use syntax::ext::base; -use syntax::ext::base::{ExtCtxt, MacResult}; -use syntax::parse::token; -use syntax::util::small_vector::SmallVector; -use rustc::plugin::Registry; -use std::gc::{Gc, GC}; - - -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_syntax_extension( - token::intern("bit_struct"), - base::IdentTT(box base::BasicIdentMacroExpander { - expander: expand_bit_struct, - span: None, - }, None)); -} - -fn expand_bit_struct(cx: &mut ExtCtxt, sp: Span, name: ast::Ident, tts: Vec) - -> Box { - let mut fields = Vec::new(); - for (i, e) in tts.iter().enumerate() { - if i & 1 == 1 { - match *e { - ast::TTTok(_, token::COMMA) => (), - _ => { - cx.span_err(sp, "bit_struct! expecting comma."); - return base::DummyResult::any(sp); - } - } - } else { - match *e { - ast::TTTok(_, token::IDENT(ident, _)) => { - fields.push(ident) - } - _ => { - cx.span_err(sp, "bit_struct! requires ident args."); - return base::DummyResult::any(sp); - } - } - } - } - let bits_per_word = - if cfg!(target_word_size = "64") { 64 } - else if cfg!(target_word_size = "32") { 32 } - else { fail!("Unexpected target word size") }; - let nb_words = (fields.len() - 1 + bits_per_word) / bits_per_word; - - let struct_def = quote_item!(&*cx, - pub struct $name { - storage: [uint, ..$nb_words] - } - ).unwrap(); - let impl_def = quote_item!(&*cx, - impl $name { - #[inline] - pub fn new() -> $name { - $name { storage: [0, ..$nb_words] } - } - } - ).unwrap(); - - // Unwrap from Gc, which does not implement DerefMut - let mut impl_def = (*impl_def).clone(); - match impl_def.node { - ast::ItemImpl(_, _, _, ref mut methods) => { - for (i, field) in fields.iter().enumerate() { - let setter_name = "set_".to_string() + field.as_str(); - let setter = token::str_to_ident(setter_name.as_slice()); - let word = i / bits_per_word; - let bit = i % bits_per_word; - let additional_impl = quote_item!(&*cx, - impl $name { - #[allow(non_snake_case_functions)] - pub fn $field(&self) -> bool { - (self.storage[$word] & (1 << $bit)) != 0 - } - #[allow(non_snake_case_functions)] - pub fn $setter(&mut self, new_value: bool) { - if new_value { - self.storage[$word] |= 1 << $bit - } else { - self.storage[$word] &= !(1 << $bit) - } - } - } - ).unwrap(); - match additional_impl.node { - ast::ItemImpl(_, _, _, ref additional_methods) => { - methods.push_all(additional_methods.as_slice()); - } - _ => fail!() - } - } - } - _ => fail!() - } - // Re-wrap. - let impl_def = box(GC) impl_def; - - struct MacItems { - items: Vec> - } - - impl MacResult for MacItems { - fn make_items(&self) -> Option>> { - Some(SmallVector::many(self.items.clone())) - } - } - - box MacItems { items: vec![struct_def, impl_def] } as Box -} - #[macro_export] macro_rules! bitfield( diff --git a/src/components/style/properties/mod.rs.mako b/src/components/style/properties/mod.rs.mako index 975bdd3c9ce..e699c392a77 100644 --- a/src/components/style/properties/mod.rs.mako +++ b/src/components/style/properties/mod.rs.mako @@ -21,6 +21,7 @@ pub use self::common_types::*; use selector_matching::DeclarationBlock; +pub use self::property_bit_field::PropertyBitField; pub mod common_types; @@ -1338,11 +1339,53 @@ pub mod shorthands { } -bit_struct! PropertyBitField [ - % for property in LONGHANDS: - ${property.ident}, - % endfor -] +// TODO(SimonSapin): Convert this to a syntax extension rather than a Mako template. +// Maybe submit for inclusion in libstd? +mod property_bit_field { + use std::uint; + use std::mem; + + pub struct PropertyBitField { + storage: [uint, ..(${len(LONGHANDS)} - 1 + uint::BITS) / uint::BITS] + } + + impl PropertyBitField { + #[inline] + pub fn new() -> PropertyBitField { + PropertyBitField { storage: unsafe { mem::zeroed() } } + } + + #[inline] + fn get(&self, bit: uint) -> bool { + (self.storage[bit / uint::BITS] & (1 << (bit % uint::BITS))) != 0 + } + #[inline] + fn set(&mut self, bit: uint) { + self.storage[bit / uint::BITS] |= 1 << (bit % uint::BITS) + } + #[inline] + fn clear(&mut self, bit: uint) { + self.storage[bit / uint::BITS] &= !(1 << (bit % uint::BITS)) + } + % for i, property in enumerate(LONGHANDS): + #[allow(non_snake_case_functions)] + #[inline] + pub fn get_${property.ident}(&self) -> bool { + self.get(${i}) + } + #[allow(non_snake_case_functions)] + #[inline] + pub fn set_${property.ident}(&mut self) { + self.set(${i}) + } + #[allow(non_snake_case_functions)] + #[inline] + pub fn clear_${property.ident}(&mut self) { + self.clear(${i}) + } + % endfor + } +} /// Declarations are stored in reverse order. @@ -1465,12 +1508,12 @@ impl PropertyDeclaration { return ExperimentalProperty } % endif - if seen.${property.ident}() { + if seen.get_${property.ident}() { return ValidOrIgnoredDeclaration } match longhands::${property.ident}::parse_declared(value, base_url) { Ok(value) => { - seen.set_${property.ident}(true); + seen.set_${property.ident}(); result_list.push(${property.camel_case}Declaration(value)); ValidOrIgnoredDeclaration }, @@ -1483,15 +1526,15 @@ impl PropertyDeclaration { % endfor % for shorthand in SHORTHANDS: "${shorthand.name}" => { - if ${" && ".join("seen.%s()" % sub_property.ident + if ${" && ".join("seen.get_%s()" % sub_property.ident for sub_property in shorthand.sub_properties)} { return ValidOrIgnoredDeclaration } match CSSWideKeyword::parse(value) { Ok(InheritKeyword) => { % for sub_property in shorthand.sub_properties: - if !seen.${sub_property.ident}() { - seen.set_${sub_property.ident}(true); + if !seen.get_${sub_property.ident}() { + seen.set_${sub_property.ident}(); result_list.push( ${sub_property.camel_case}Declaration(Inherit)); } @@ -1500,8 +1543,8 @@ impl PropertyDeclaration { }, Ok(InitialKeyword) => { % for sub_property in shorthand.sub_properties: - if !seen.${sub_property.ident}() { - seen.set_${sub_property.ident}(true); + if !seen.get_${sub_property.ident}() { + seen.set_${sub_property.ident}(); result_list.push( ${sub_property.camel_case}Declaration(Initial)); } @@ -1510,8 +1553,8 @@ impl PropertyDeclaration { }, Ok(UnsetKeyword) => { % for sub_property in shorthand.sub_properties: - if !seen.${sub_property.ident}() { - seen.set_${sub_property.ident}(true); + if !seen.get_${sub_property.ident}() { + seen.set_${sub_property.ident}(); result_list.push(${sub_property.camel_case}Declaration( ${"Inherit" if sub_property.style_struct.inherited else "Initial"} )); @@ -1522,8 +1565,8 @@ impl PropertyDeclaration { Err(()) => match shorthands::${shorthand.ident}::parse(value, base_url) { Ok(result) => { % for sub_property in shorthand.sub_properties: - if !seen.${sub_property.ident}() { - seen.set_${sub_property.ident}(true); + if !seen.get_${sub_property.ident}() { + seen.set_${sub_property.ident}(); result_list.push(${sub_property.camel_case}Declaration( match result.${sub_property.ident} { Some(value) => SpecifiedValue(value), @@ -1770,10 +1813,10 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock] % if property.derived_from is None: ${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => { % if style_struct.inherited: - if seen.${property.ident}() { + if seen.get_${property.ident}() { continue } - seen.set_${property.ident}(true); + seen.set_${property.ident}(); let computed_value = match *declared_value { SpecifiedValue(ref specified_value) => longhands::${property.ident}::to_computed_value( @@ -1977,10 +2020,10 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], % for property in style_struct.longhands: % if property.derived_from is None: ${property.camel_case}Declaration(ref declared_value) => { - if seen.${property.ident}() { + if seen.get_${property.ident}() { continue } - seen.set_${property.ident}(true); + seen.set_${property.ident}(); let computed_value = match *declared_value { SpecifiedValue(ref specified_value) => longhands::${property.ident}::to_computed_value( @@ -2038,7 +2081,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock], } // The initial value of display may be changed at computed value time. - if !seen.display() { + if !seen.get_display() { let box_ = style_box_.make_unique_experimental(); box_.display = longhands::display::to_computed_value(box_.display, &context); }