mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Revert "Move PropertyBitField to a syntax extension."
This reverts commit d6002a0a50
.
This commit is contained in:
parent
cc03e4f9e2
commit
c0d08a6c2e
2 changed files with 65 additions and 141 deletions
|
@ -4,133 +4,14 @@
|
||||||
|
|
||||||
#![crate_name = "macros"]
|
#![crate_name = "macros"]
|
||||||
#![crate_type = "rlib"]
|
#![crate_type = "rlib"]
|
||||||
#![crate_type = "dylib"]
|
|
||||||
|
|
||||||
#![feature(macro_rules, plugin_registrar, quote)]
|
#![feature(macro_rules)]
|
||||||
|
|
||||||
//! Exports macros for use in other Servo crates.
|
//! Exports macros for use in other Servo crates.
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate sync;
|
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<ast::TokenTree>)
|
|
||||||
-> Box<base::MacResult> {
|
|
||||||
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<T>, 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<Gc<ast::Item>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MacResult for MacItems {
|
|
||||||
fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
|
|
||||||
Some(SmallVector::many(self.items.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
box MacItems { items: vec![struct_def, impl_def] } as Box<MacResult>
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! bitfield(
|
macro_rules! bitfield(
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub use self::common_types::*;
|
||||||
use selector_matching::DeclarationBlock;
|
use selector_matching::DeclarationBlock;
|
||||||
|
|
||||||
|
|
||||||
|
pub use self::property_bit_field::PropertyBitField;
|
||||||
pub mod common_types;
|
pub mod common_types;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1338,11 +1339,53 @@ pub mod shorthands {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bit_struct! PropertyBitField [
|
// TODO(SimonSapin): Convert this to a syntax extension rather than a Mako template.
|
||||||
% for property in LONGHANDS:
|
// Maybe submit for inclusion in libstd?
|
||||||
${property.ident},
|
mod property_bit_field {
|
||||||
% endfor
|
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.
|
/// Declarations are stored in reverse order.
|
||||||
|
@ -1465,12 +1508,12 @@ impl PropertyDeclaration {
|
||||||
return ExperimentalProperty
|
return ExperimentalProperty
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
if seen.${property.ident}() {
|
if seen.get_${property.ident}() {
|
||||||
return ValidOrIgnoredDeclaration
|
return ValidOrIgnoredDeclaration
|
||||||
}
|
}
|
||||||
match longhands::${property.ident}::parse_declared(value, base_url) {
|
match longhands::${property.ident}::parse_declared(value, base_url) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
seen.set_${property.ident}(true);
|
seen.set_${property.ident}();
|
||||||
result_list.push(${property.camel_case}Declaration(value));
|
result_list.push(${property.camel_case}Declaration(value));
|
||||||
ValidOrIgnoredDeclaration
|
ValidOrIgnoredDeclaration
|
||||||
},
|
},
|
||||||
|
@ -1483,15 +1526,15 @@ impl PropertyDeclaration {
|
||||||
% endfor
|
% endfor
|
||||||
% for shorthand in SHORTHANDS:
|
% for shorthand in SHORTHANDS:
|
||||||
"${shorthand.name}" => {
|
"${shorthand.name}" => {
|
||||||
if ${" && ".join("seen.%s()" % sub_property.ident
|
if ${" && ".join("seen.get_%s()" % sub_property.ident
|
||||||
for sub_property in shorthand.sub_properties)} {
|
for sub_property in shorthand.sub_properties)} {
|
||||||
return ValidOrIgnoredDeclaration
|
return ValidOrIgnoredDeclaration
|
||||||
}
|
}
|
||||||
match CSSWideKeyword::parse(value) {
|
match CSSWideKeyword::parse(value) {
|
||||||
Ok(InheritKeyword) => {
|
Ok(InheritKeyword) => {
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
if !seen.${sub_property.ident}() {
|
if !seen.get_${sub_property.ident}() {
|
||||||
seen.set_${sub_property.ident}(true);
|
seen.set_${sub_property.ident}();
|
||||||
result_list.push(
|
result_list.push(
|
||||||
${sub_property.camel_case}Declaration(Inherit));
|
${sub_property.camel_case}Declaration(Inherit));
|
||||||
}
|
}
|
||||||
|
@ -1500,8 +1543,8 @@ impl PropertyDeclaration {
|
||||||
},
|
},
|
||||||
Ok(InitialKeyword) => {
|
Ok(InitialKeyword) => {
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
if !seen.${sub_property.ident}() {
|
if !seen.get_${sub_property.ident}() {
|
||||||
seen.set_${sub_property.ident}(true);
|
seen.set_${sub_property.ident}();
|
||||||
result_list.push(
|
result_list.push(
|
||||||
${sub_property.camel_case}Declaration(Initial));
|
${sub_property.camel_case}Declaration(Initial));
|
||||||
}
|
}
|
||||||
|
@ -1510,8 +1553,8 @@ impl PropertyDeclaration {
|
||||||
},
|
},
|
||||||
Ok(UnsetKeyword) => {
|
Ok(UnsetKeyword) => {
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
if !seen.${sub_property.ident}() {
|
if !seen.get_${sub_property.ident}() {
|
||||||
seen.set_${sub_property.ident}(true);
|
seen.set_${sub_property.ident}();
|
||||||
result_list.push(${sub_property.camel_case}Declaration(
|
result_list.push(${sub_property.camel_case}Declaration(
|
||||||
${"Inherit" if sub_property.style_struct.inherited else "Initial"}
|
${"Inherit" if sub_property.style_struct.inherited else "Initial"}
|
||||||
));
|
));
|
||||||
|
@ -1522,8 +1565,8 @@ impl PropertyDeclaration {
|
||||||
Err(()) => match shorthands::${shorthand.ident}::parse(value, base_url) {
|
Err(()) => match shorthands::${shorthand.ident}::parse(value, base_url) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
% for sub_property in shorthand.sub_properties:
|
% for sub_property in shorthand.sub_properties:
|
||||||
if !seen.${sub_property.ident}() {
|
if !seen.get_${sub_property.ident}() {
|
||||||
seen.set_${sub_property.ident}(true);
|
seen.set_${sub_property.ident}();
|
||||||
result_list.push(${sub_property.camel_case}Declaration(
|
result_list.push(${sub_property.camel_case}Declaration(
|
||||||
match result.${sub_property.ident} {
|
match result.${sub_property.ident} {
|
||||||
Some(value) => SpecifiedValue(value),
|
Some(value) => SpecifiedValue(value),
|
||||||
|
@ -1770,10 +1813,10 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock]
|
||||||
% if property.derived_from is None:
|
% if property.derived_from is None:
|
||||||
${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => {
|
${property.camel_case}Declaration(ref ${'_' if not style_struct.inherited else ''}declared_value) => {
|
||||||
% if style_struct.inherited:
|
% if style_struct.inherited:
|
||||||
if seen.${property.ident}() {
|
if seen.get_${property.ident}() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen.set_${property.ident}(true);
|
seen.set_${property.ident}();
|
||||||
let computed_value = match *declared_value {
|
let computed_value = match *declared_value {
|
||||||
SpecifiedValue(ref specified_value)
|
SpecifiedValue(ref specified_value)
|
||||||
=> longhands::${property.ident}::to_computed_value(
|
=> longhands::${property.ident}::to_computed_value(
|
||||||
|
@ -1977,10 +2020,10 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
|
||||||
% for property in style_struct.longhands:
|
% for property in style_struct.longhands:
|
||||||
% if property.derived_from is None:
|
% if property.derived_from is None:
|
||||||
${property.camel_case}Declaration(ref declared_value) => {
|
${property.camel_case}Declaration(ref declared_value) => {
|
||||||
if seen.${property.ident}() {
|
if seen.get_${property.ident}() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
seen.set_${property.ident}(true);
|
seen.set_${property.ident}();
|
||||||
let computed_value = match *declared_value {
|
let computed_value = match *declared_value {
|
||||||
SpecifiedValue(ref specified_value)
|
SpecifiedValue(ref specified_value)
|
||||||
=> longhands::${property.ident}::to_computed_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.
|
// 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();
|
let box_ = style_box_.make_unique_experimental();
|
||||||
box_.display = longhands::display::to_computed_value(box_.display, &context);
|
box_.display = longhands::display::to_computed_value(box_.display, &context);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue