Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proc macro for css #17

Merged
merged 41 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
89df0c4
first prototype for css macro
WorldSEnder Aug 11, 2021
b5a9aa3
pull apart parser and output, fixing test cases in the process
WorldSEnder Aug 23, 2021
2c3dff6
use style macro instead of css
WorldSEnder Aug 23, 2021
c46c122
simplify code fold_normalized_scope_hierarchy
WorldSEnder Aug 23, 2021
8fa3ea8
fix errors
WorldSEnder Aug 23, 2021
5415061
be much more lenient in css component values
WorldSEnder Aug 24, 2021
8d9360b
be more strict in selectors
WorldSEnder Aug 24, 2021
0c93be6
pull some reify from parsed->output
WorldSEnder Aug 25, 2021
435a3f9
get rid of regex in dev-deps
WorldSEnder Aug 25, 2021
fea0385
lessons from integration into material_yewi
WorldSEnder Aug 25, 2021
2017ea9
helpful error message for mistaken blocks
WorldSEnder Aug 25, 2021
25d57ae
improve proc_macro validation
WorldSEnder Aug 26, 2021
3733db1
fix SheetRef->Sheet
WorldSEnder Aug 26, 2021
db6f92b
simplify scope folding logic
WorldSEnder Aug 26, 2021
c818fa5
expect to parse, don't propagate error
WorldSEnder Aug 26, 2021
ecef205
add macro benchmarks
WorldSEnder Aug 26, 2021
649dc08
validate @-rule names
WorldSEnder Aug 26, 2021
cccad18
move tests into stylist
WorldSEnder Aug 26, 2021
ae77b47
organize imports
WorldSEnder Aug 26, 2021
5b05e44
spacing of emitted component values
WorldSEnder Aug 28, 2021
af29169
pull apart output module for readability
WorldSEnder Aug 28, 2021
e620ea0
satisfy clippy
WorldSEnder Aug 28, 2021
08a29f7
pull out spacing iterator for testing
WorldSEnder Aug 28, 2021
b336bc1
combine successive string literals in output
WorldSEnder Aug 28, 2021
60e51da
add documentation to macros
WorldSEnder Aug 28, 2021
3e255f5
address comments
WorldSEnder Aug 29, 2021
974064e
complex benchmarks are dynamic now
WorldSEnder Aug 29, 2021
d7490e8
split parse into submodules
WorldSEnder Aug 29, 2021
6a3ec58
rewrite scope folding
WorldSEnder Aug 29, 2021
a8afe13
implement lazy optimization for inline sheets
WorldSEnder Aug 29, 2021
064e325
add peephole optimization for string literals
WorldSEnder Aug 29, 2021
a3bd39b
fixup
WorldSEnder Aug 29, 2021
978124d
more readable component value implementation
WorldSEnder Aug 29, 2021
256b154
self review, update comments
WorldSEnder Aug 29, 2021
5557cea
doc of inline::output module, fix clippy
WorldSEnder Aug 29, 2021
4d6dfc4
add inline macro to benchmark
WorldSEnder Aug 29, 2021
8291401
address review comments
WorldSEnder Aug 30, 2021
dc6d390
Reify should be more easy to use now
WorldSEnder Aug 30, 2021
0791614
Merge remote-tracking branch 'upstream/master' into stylist
WorldSEnder Aug 30, 2021
d9e1b0e
align to_string implementation in literal
WorldSEnder Aug 30, 2021
8cc98d4
fix clippy
WorldSEnder Aug 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 91 additions & 9 deletions examples/benchmarks/src/benchmarks.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
use stylist::ast::Sheet;
use stylist::Style;
use stylist::{
ast::{sheet, Sheet},
Style,
};

use crate::utils::now;

pub fn bench_parse_simple() -> f64 {
let start_time = now();
for _ in 0..1_000_000 {
for _ in 0..10_000_000 {
let _sheet: Sheet = "color:red;".parse().expect("Failed to parse stylesheet.");
}

now() - start_time
}

pub fn bench_macro_simple() -> f64 {
let start_time = now();
for _ in 0..10_000_000 {
let _sheet: Sheet = sheet!("color:red;");
}

now() - start_time
}

pub fn bench_macro_inline_simple() -> f64 {
let start_time = now();
for _ in 0..10_000_000 {
let _sheet: Sheet = sheet!(color:red;);
}

now() - start_time
}

pub fn bench_parse_simple_no_cache() -> f64 {
let start_time = now();
for i in 0..100_000 {
Expand All @@ -25,8 +45,42 @@ pub fn bench_parse_simple_no_cache() -> f64 {

pub fn bench_parse_complex() -> f64 {
let start_time = now();
for _ in 0..100_000 {
let _sheet: Sheet = r#"
for i in 0..1_000_000 {
let _sheet: Sheet = format!(
r#"
color:red;

.class-name-a {{
background: red;

display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}}

@media screen and (max-width: {i}px;) {{
font-size: 0.9rem;

.class-name-b {{
flex-direction: row;
}}
}}
"#,
i = i / 1000
)
.parse()
.expect("Failed to parse stylesheet.");
}

now() - start_time
}

pub fn bench_macro_complex() -> f64 {
let start_time = now();
for i in 0..1_000_000 {
let _sheet: Sheet = sheet!(
r#"
color:red;

.class-name-a {
Expand All @@ -38,16 +92,44 @@ pub fn bench_parse_complex() -> f64 {
align-items: center;
}

@media screen and (max-width: 500px;) {
@media screen and (max-width: ${i}px;) {
font-size: 0.9rem;

.class-name-b {
flex-direction: row;
}
}
"#
.parse()
.expect("Failed to parse stylesheet.");
"#,
i = (i / 1000).to_string()
);
}

now() - start_time
}

pub fn bench_macro_inline_complex() -> f64 {
let start_time = now();
for i in 0..1_000_000 {
let _sheet: Sheet = sheet!(
color: red;

.class-name-a {
background: red;

display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

@media screen and (max-width: ${i / 1000}px;) {
font-size: 0.9rem;

.class-name-b {
flex-direction: row;
}
}
);
}

now() - start_time
Expand Down
69 changes: 65 additions & 4 deletions examples/benchmarks/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use gloo::timers::callback::Timeout;
use stylist::yew::Global;
use stylist::{StyleSource, YieldStyle};
use stylist::{yew::Global, StyleSource, YieldStyle};
use yew::prelude::*;

use log::Level;
Expand All @@ -22,8 +21,12 @@ static GLOBAL_STYLE: &str = r#"

pub enum BenchMsg {
ParseSimpleFinish(f64),
MacroSimpleFinish(f64),
MacroInlineSimpleFinish(f64),
ParseSimpleNoCacheFinish(f64),
ParseComplexFinish(f64),
MacroComplexFinish(f64),
MacroInlineComplexFinish(f64),
ParseComplexNoCacheFinish(f64),
CachedLookupFinish(f64),
CachedLookupBigSheetFinish(f64),
Expand All @@ -35,8 +38,12 @@ pub struct Benchmarks {
finished: bool,

parse_simple: Option<f64>,
macro_simple: Option<f64>,
macro_inline_simple: Option<f64>,
parse_simple_no_cache: Option<f64>,
parse_complex: Option<f64>,
macro_complex: Option<f64>,
macro_inline_complex: Option<f64>,
parse_complex_no_cache: Option<f64>,

cached_lookup: Option<f64>,
Expand All @@ -54,8 +61,12 @@ impl Component for Benchmarks {
link,
finished: false,
parse_simple: None,
macro_simple: None,
macro_inline_simple: None,
parse_simple_no_cache: None,
parse_complex: None,
macro_complex: None,
macro_inline_complex: None,
parse_complex_no_cache: None,
cached_lookup: None,
cached_lookup_big_sheet: None,
Expand All @@ -76,6 +87,22 @@ impl Component for Benchmarks {
match msg {
BenchMsg::ParseSimpleFinish(m) => {
self.parse_simple = Some(m);
let cb = self
.link
.callback(|_| BenchMsg::MacroSimpleFinish(benchmarks::bench_macro_simple()));

Timeout::new(100, move || cb.emit(())).forget();
}
BenchMsg::MacroSimpleFinish(m) => {
self.macro_simple = Some(m);
let cb = self.link.callback(|_| {
BenchMsg::MacroInlineSimpleFinish(benchmarks::bench_macro_inline_simple())
});

Timeout::new(100, move || cb.emit(())).forget();
}
BenchMsg::MacroInlineSimpleFinish(m) => {
self.macro_inline_simple = Some(m);
let cb = self.link.callback(|_| {
BenchMsg::ParseSimpleNoCacheFinish(benchmarks::bench_parse_simple_no_cache())
});
Expand All @@ -94,6 +121,24 @@ impl Component for Benchmarks {
BenchMsg::ParseComplexFinish(m) => {
self.parse_complex = Some(m);

let cb = self
.link
.callback(|_| BenchMsg::MacroComplexFinish(benchmarks::bench_macro_complex()));

Timeout::new(100, move || cb.emit(())).forget();
}
BenchMsg::MacroComplexFinish(m) => {
self.macro_complex = Some(m);

let cb = self.link.callback(|_| {
BenchMsg::MacroInlineComplexFinish(benchmarks::bench_macro_inline_complex())
});

Timeout::new(100, move || cb.emit(())).forget();
}
BenchMsg::MacroInlineComplexFinish(m) => {
self.macro_inline_complex = Some(m);

let cb = self.link.callback(|_| {
BenchMsg::ParseComplexNoCacheFinish(benchmarks::bench_parse_complex_no_cache())
});
Expand Down Expand Up @@ -165,17 +210,33 @@ impl Component for Benchmarks {
</thead>
<tbody>
<tr>
<th>{"Parse Simple (1,000,000 iterations): "}</th>
<th>{"Parse Simple (10,000,000 iterations): "}</th>
<th>{self.parse_simple.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Macro Simple (10,000,000 iterations): "}</th>
<th>{self.macro_simple.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Macro Inline Simple (10,000,000 iterations): "}</th>
<th>{self.macro_inline_simple.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Parse Simple, No Cache (100,000 iterations): "}</th>
<th>{self.parse_simple_no_cache.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Parse Complex (100,000 iterations): "}</th>
<th>{"Parse Complex (1,000,000 iterations): "}</th>
<th>{self.parse_complex.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Macro Complex (1,000,000 iterations): "}</th>
<th>{self.macro_complex.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Macro Inline Complex (1,000,000 iterations): "}</th>
<th>{self.macro_inline_complex.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
</tr>
<tr>
<th>{"Parse Complex, No Cache (100,000 iterations): "}</th>
<th>{self.parse_complex_no_cache.map(|m| {format!("{:.0}ms", m)}).unwrap_or_else(|| "".to_string())}</th>
Expand Down
4 changes: 2 additions & 2 deletions packages/stylist-core/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mod tests {
.into(),
}),
ScopeContent::Block(Block {
condition: vec![".inner".into()].into(),
condition: vec![vec![".inner".into()].into()].into(),
style_attributes: vec![StyleAttribute {
key: "background-color".into(),
value: vec!["red".into()].into(),
Expand Down Expand Up @@ -96,7 +96,7 @@ width: 200px;
.into(),
}),
RuleContent::Block(Block {
condition: vec![".inner".into()].into(),
condition: vec![vec![".inner".into()].into()].into(),
style_attributes: vec![StyleAttribute {
key: "background-color".into(),
value: vec!["red".into()].into(),
Expand Down
15 changes: 7 additions & 8 deletions packages/stylist-core/src/ast/selector.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::borrow::Cow;
use std::fmt;
use std::{borrow::Cow, fmt};

use super::{StringFragment, ToStyleStr};
use crate::Result;
Expand Down Expand Up @@ -57,10 +56,10 @@ impl ToStyleStr for Selector {
}
}

impl<T: Into<Cow<'static, str>>> From<T> for Selector {
impl<T: Into<Cow<'static, [StringFragment]>>> From<T> for Selector {
fn from(s: T) -> Self {
Self {
fragments: vec![s.into().into()].into(),
fragments: s.into(),
}
}
}
Expand All @@ -71,7 +70,7 @@ mod tests {

#[test]
fn test_selector_gen_simple() -> Result<()> {
let s: Selector = ".abc".into();
let s: Selector = vec![".abc".into()].into();

assert_eq!(
s.to_style_str(Some("stylist-abcdefgh"))?,
Expand All @@ -83,7 +82,7 @@ mod tests {

#[test]
fn test_selector_pseduo() -> Result<()> {
let s: Selector = ":hover".into();
let s: Selector = vec![":hover".into()].into();

assert_eq!(
s.to_style_str(Some("stylist-abcdefgh"))?,
Expand All @@ -95,7 +94,7 @@ mod tests {

#[test]
fn test_selector_root_pseduo() -> Result<()> {
let s: Selector = ":root.big".into();
let s: Selector = vec![":root.big".into()].into();

assert_eq!(
s.to_style_str(Some("stylist-abcdefgh"))?,
Expand All @@ -107,7 +106,7 @@ mod tests {

#[test]
fn test_selector_gen_current() -> Result<()> {
let s: Selector = "&.big".into();
let s: Selector = vec!["&.big".into()].into();

assert_eq!(
s.to_style_str(Some("stylist-abcdefgh"))?,
Expand Down
Loading