Revert string interning

There existed issues related to multithreaded tests that are difficult
to resolve. In the future interning may be reimplemented but in a more
limited capacity.

The motivation behind interning *values* was that it appeared checking
for named colors was responsible for much of the time lost when parsing
unquoted strings. If interning were to be reimplemented, it may make
sense to limit it solely to identifiers and style properties.
This commit is contained in:
ConnorSkees 2020-05-22 14:20:31 -04:00
parent 3e5abf0587
commit 969726eb30
24 changed files with 431 additions and 1158 deletions

View File

@ -49,7 +49,6 @@ rand = { version = "0.7.3", optional = true }
codemap = "0.1.3"
peekmore = "0.4.0"
wasm-bindgen = { version = "0.2.60", optional = true }
lasso = "0.2.2"
[features]
default = ["commandline", "random"]

View File

@ -42,7 +42,7 @@ impl Each {
if self.vars.len() == 1 {
if this_iterator.len() == 1 {
scope.insert_var(
&self.vars[0].node,
&self.vars[0],
Spanned {
node: this_iterator[0].clone(),
span: self.vars[0].span,
@ -50,7 +50,7 @@ impl Each {
)?;
} else {
scope.insert_var(
&self.vars[0].node,
&self.vars[0],
Spanned {
node: Value::List(this_iterator, ListSeparator::Space, Brackets::None),
span: self.vars[0].span,

View File

@ -6,7 +6,6 @@ use crate::args::CallArgs;
use crate::color::Color;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -108,10 +107,7 @@ fn inner_hsl(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -140,10 +136,7 @@ fn inner_hsl(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -174,10 +167,7 @@ fn inner_hsl(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -211,14 +201,14 @@ fn inner_hsl(
}
v if v.is_special_function() => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}({}, {}, {}, {})",
name,
hue,
saturation,
lightness,
v.to_css_string(args.span())?
)),
),
QuoteKind::None,
));
}
@ -368,10 +358,10 @@ fn saturate(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
args.max_args(2)?;
if args.len() == 1 {
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"saturate({})",
arg!(args, scope, super_selector, 0, "amount").to_css_string(args.span())?
)),
),
QuoteKind::None,
));
}
@ -393,7 +383,7 @@ fn saturate(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
Value::Color(c) => c,
Value::Dimension(n, u) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("saturate({}{})", n, u)),
format!("saturate({}{})", n, u),
QuoteKind::None,
))
}
@ -442,7 +432,7 @@ fn grayscale(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
Value::Color(c) => c,
Value::Dimension(n, u) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("grayscale({}{})", n, u)),
format!("grayscale({}{})", n, u),
QuoteKind::None,
))
}
@ -495,10 +485,9 @@ fn invert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassR
};
match arg!(args, scope, super_selector, 0, "color") {
Value::Color(c) => Ok(Value::Color(Box::new(c.invert(weight)))),
Value::Dimension(n, Unit::Percent) => Ok(Value::Ident(
InternedString::get_or_intern(format!("invert({}%)", n)),
QuoteKind::None,
)),
Value::Dimension(n, Unit::Percent) => {
Ok(Value::Ident(format!("invert({}%)", n), QuoteKind::None))
}
Value::Dimension(..) => Err((
"Only one argument may be passed to the plain-CSS invert() function.",
args.span(),

View File

@ -3,7 +3,6 @@ use super::{Builtin, GlobalFunctionMap};
use crate::args::CallArgs;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -27,7 +26,7 @@ fn opacity(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sass
match arg!(args, scope, super_selector, 0, "color") {
Value::Color(c) => Ok(Value::Dimension(c.alpha(), Unit::None)),
Value::Dimension(num, unit) => Ok(Value::Ident(
InternedString::get_or_intern(format!("opacity({}{})", num, unit)),
format!("opacity({}{})", num, unit),
QuoteKind::None,
)),
v => Err((

View File

@ -6,7 +6,6 @@ use crate::args::CallArgs;
use crate::color::Color;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -47,13 +46,13 @@ fn inner_rgb(
let green = channels.pop().unwrap();
let red = channels.pop().unwrap();
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}({}, {}, {})",
name,
red.to_css_string(args.span())?,
green.to_css_string(args.span())?,
v.to_css_string(args.span())?
)),
),
QuoteKind::None,
));
}
@ -81,10 +80,7 @@ fn inner_rgb(
),
None => format!("{}({} {})", name, v.to_css_string(args.span())?, blue),
};
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
Some(v) => {
return Err((
@ -101,13 +97,13 @@ fn inner_rgb(
Some(Value::Dimension(n, Unit::Percent)) => (n / Number::from(100)) * Number::from(255),
Some(v) if v.is_special_function() => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}({}, {}, {})",
name,
v.to_css_string(args.span())?,
green,
blue
)),
),
QuoteKind::None,
));
}
@ -130,12 +126,12 @@ fn inner_rgb(
v if v.is_special_function() => {
let alpha = arg!(args, scope, super_selector, 1, "alpha");
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}({}, {})",
name,
v.to_css_string(args.span())?,
alpha.to_css_string(args.span())?
)),
),
QuoteKind::None,
));
}
@ -162,14 +158,14 @@ fn inner_rgb(
}
v if v.is_special_function() => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}({}, {}, {}, {})",
name,
color.red(),
color.green(),
color.blue(),
v.to_css_string(args.span())?
)),
),
QuoteKind::None,
));
}
@ -214,10 +210,7 @@ fn inner_rgb(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -257,10 +250,7 @@ fn inner_rgb(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -299,10 +289,7 @@ fn inner_rgb(
);
}
string.push(')');
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((
@ -340,10 +327,7 @@ fn inner_rgb(
blue,
v.to_css_string(args.span())?
);
return Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
));
return Ok(Value::Ident(string, QuoteKind::None));
}
v => {
return Err((

View File

@ -5,7 +5,6 @@ use num_traits::{One, Signed, ToPrimitive, Zero};
use crate::args::CallArgs;
use crate::common::{Brackets, ListSeparator, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -73,10 +72,11 @@ fn list_separator(
) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::Ident(
InternedString::get_or_intern(match arg!(args, scope, super_selector, 0, "list") {
match arg!(args, scope, super_selector, 0, "list") {
Value::List(_, sep, ..) => sep.name(),
_ => ListSeparator::Space.name(),
}),
}
.to_owned(),
QuoteKind::None,
))
}
@ -140,9 +140,9 @@ fn append(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassR
scope,
super_selector,
2,
"separator" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
"separator" = Value::Ident("auto".to_owned(), QuoteKind::None)
) {
Value::Ident(s, ..) => match s.resolve_ref() {
Value::Ident(s, ..) => match s.as_str() {
"auto" => sep,
"comma" => ListSeparator::Comma,
"space" => ListSeparator::Space,
@ -188,9 +188,9 @@ fn join(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
scope,
super_selector,
2,
"separator" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
"separator" = Value::Ident("auto".to_owned(), QuoteKind::None)
) {
Value::Ident(s, ..) => match s.resolve_ref() {
Value::Ident(s, ..) => match s.as_str() {
"auto" => {
if list1.is_empty() || (list1.len() == 1 && sep1 == ListSeparator::Space) {
sep2
@ -225,9 +225,9 @@ fn join(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
scope,
super_selector,
3,
"bracketed" = Value::Ident(InternedString::get_or_intern("auto"), QuoteKind::None)
"bracketed" = Value::Ident("auto".to_owned(), QuoteKind::None)
) {
Value::Ident(s, ..) => match s.resolve_ref() {
Value::Ident(s, ..) => match s.as_str() {
"auto" => brackets,
_ => Brackets::Bracketed,
},

View File

@ -5,7 +5,6 @@ use codemap::Spanned;
use crate::args::CallArgs;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::global_var_exists;
use crate::scope::Scope;
use crate::selector::Selector;
@ -28,7 +27,7 @@ fn feature_exists(
) -> SassResult<Value> {
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "feature") {
Value::Ident(s, _) => Ok(match s.resolve_ref() {
Value::Ident(s, _) => Ok(match s.as_str() {
// A local variable will shadow a global variable unless
// `!global` is used.
"global-variable-shadowing" => Value::True,
@ -72,17 +71,14 @@ fn unit(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassRes
.into())
}
};
Ok(Value::Ident(
InternedString::get_or_intern(unit),
QuoteKind::Quoted,
))
Ok(Value::Ident(unit, QuoteKind::Quoted))
}
fn type_of(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
args.max_args(1)?;
let value = arg!(args, scope, super_selector, 0, "value");
Ok(Value::Ident(
InternedString::get_or_intern(value.kind(args.span())?),
value.kind(args.span())?.to_owned(),
QuoteKind::None,
))
}
@ -99,9 +95,9 @@ fn unitless(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sas
fn inspect(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
args.max_args(1)?;
Ok(Value::Ident(
InternedString::get_or_intern(
arg!(args, scope, super_selector, 0, "value").inspect(args.span())?,
),
arg!(args, scope, super_selector, 0, "value")
.inspect(args.span())?
.into(),
QuoteKind::None,
))
}
@ -113,7 +109,7 @@ fn variable_exists(
) -> SassResult<Value> {
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "name") {
Value::Ident(s, _) => Ok(Value::bool(scope.var_exists(s))),
Value::Ident(s, _) => Ok(Value::bool(scope.var_exists(&s))),
v => Err((
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
args.span(),
@ -129,7 +125,7 @@ fn global_variable_exists(
) -> SassResult<Value> {
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "name") {
Value::Ident(s, _) => Ok(Value::bool(global_var_exists(s))),
Value::Ident(s, _) => Ok(Value::bool(global_var_exists(&s))),
v => Err((
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
args.span(),
@ -141,7 +137,7 @@ fn global_variable_exists(
fn mixin_exists(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
args.max_args(2)?;
match arg!(args, scope, super_selector, 0, "name") {
Value::Ident(s, _) => Ok(Value::bool(scope.mixin_exists(s))),
Value::Ident(s, _) => Ok(Value::bool(scope.mixin_exists(&s))),
v => Err((
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
args.span(),
@ -157,7 +153,9 @@ fn function_exists(
) -> SassResult<Value> {
args.max_args(2)?;
match arg!(args, scope, super_selector, 0, "name") {
Value::Ident(s, _) => Ok(Value::bool(scope.fn_exists(s))),
Value::Ident(s, _) => Ok(Value::bool(
scope.fn_exists(&s) || GLOBAL_FUNCTIONS.contains_key(s.as_str()),
)),
v => Err((
format!("$name: {} is not a string.", v.to_css_string(args.span())?),
args.span(),
@ -203,12 +201,12 @@ fn get_function(mut args: CallArgs, scope: &Scope, super_selector: &Selector) ->
}
let func = match scope.get_fn(Spanned {
node: name,
node: name.clone(),
span: args.span(),
}) {
Ok(f) => SassFunction::UserDefined(Box::new(f), name.into()),
Err(..) => match GLOBAL_FUNCTIONS.get(&name.resolve_ref()) {
Some(f) => SassFunction::Builtin(f.clone(), name.into()),
Ok(f) => SassFunction::UserDefined(Box::new(f), name),
Err(..) => match GLOBAL_FUNCTIONS.get(name.as_str()) {
Some(f) => SassFunction::Builtin(f.clone(), name),
None => return Err((format!("Function not found: {}", name), args.span()).into()),
},
};

View File

@ -9,7 +9,6 @@ use rand::{distributions::Alphanumeric, thread_rng, Rng};
use crate::args::CallArgs;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -22,10 +21,9 @@ fn to_upper_case(
) -> SassResult<Value> {
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "string") {
Value::Ident(i, q) => {
let mut i = i.resolve();
Value::Ident(mut i, q) => {
i.make_ascii_uppercase();
Ok(Value::Ident(InternedString::get_or_intern(i), q))
Ok(Value::Ident(i, q))
}
v => Err((
format!(
@ -45,10 +43,9 @@ fn to_lower_case(
) -> SassResult<Value> {
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "string") {
Value::Ident(i, q) => {
let mut i = i.resolve();
Value::Ident(mut i, q) => {
i.make_ascii_lowercase();
Ok(Value::Ident(InternedString::get_or_intern(i), q))
Ok(Value::Ident(i, q))
}
v => Err((
format!(
@ -65,7 +62,7 @@ fn str_length(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
args.max_args(1)?;
match arg!(args, scope, super_selector, 0, "string") {
Value::Ident(i, _) => Ok(Value::Dimension(
Number::from(i.resolve().chars().count()),
Number::from(i.chars().count()),
Unit::None,
)),
v => Err((
@ -124,7 +121,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
.into())
}
};
let str_len = string.resolve().chars().count();
let str_len = string.chars().count();
let start = match arg!(args, scope, super_selector, 1, "start-at") {
Value::Dimension(n, Unit::None) if n.is_decimal() => {
return Err((format!("{} is not an int.", n), args.span()).into())
@ -198,17 +195,14 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
}
if start > end || start > str_len {
Ok(Value::Ident(InternedString::get_or_intern(""), quotes))
Ok(Value::Ident(String::new(), quotes))
} else {
Ok(Value::Ident(
InternedString::get_or_intern(
string
.resolve()
.chars()
.skip(start - 1)
.take(end - start + 1)
.collect::<String>(),
),
.collect(),
quotes,
))
}
@ -217,7 +211,7 @@ fn str_slice(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
args.max_args(2)?;
let s1 = match arg!(args, scope, super_selector, 0, "string") {
Value::Ident(i, _) => i.resolve(),
Value::Ident(i, _) => i,
v => {
return Err((
format!(
@ -231,7 +225,7 @@ fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
};
let substr = match arg!(args, scope, super_selector, 1, "substring") {
Value::Ident(i, _) => i.resolve(),
Value::Ident(i, _) => i,
v => {
return Err((
format!(
@ -253,7 +247,7 @@ fn str_index(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> Sa
fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> SassResult<Value> {
args.max_args(3)?;
let (s1, quotes) = match arg!(args, scope, super_selector, 0, "string") {
Value::Ident(i, q) => (i.resolve().to_string(), q),
Value::Ident(i, q) => (i, q),
v => {
return Err((
format!(
@ -267,7 +261,7 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
};
let substr = match arg!(args, scope, super_selector, 1, "insert") {
Value::Ident(i, _) => i.resolve().to_string(),
Value::Ident(i, _) => i,
v => {
return Err((
format!(
@ -305,7 +299,7 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
};
if s1.is_empty() {
return Ok(Value::Ident(InternedString::get_or_intern(substr), quotes));
return Ok(Value::Ident(substr, quotes));
}
let len = s1.chars().count();
@ -348,21 +342,18 @@ fn str_insert(mut args: CallArgs, scope: &Scope, super_selector: &Selector) -> S
}
};
Ok(Value::Ident(InternedString::get_or_intern(string), quotes))
Ok(Value::Ident(string, quotes))
}
#[cfg(feature = "random")]
fn unique_id(args: CallArgs, _: &Scope, _: &Selector) -> SassResult<Value> {
args.max_args(0)?;
let mut rng = thread_rng();
let string: String = std::iter::repeat(())
let string = std::iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.take(7)
.collect();
Ok(Value::Ident(
InternedString::get_or_intern(string),
QuoteKind::None,
))
Ok(Value::Ident(string, QuoteKind::None))
}
pub(crate) fn declare(f: &mut GlobalFunctionMap) {

View File

@ -17,7 +17,6 @@
use std::fmt::{self, Display};
use crate::interner::InternedString;
use crate::value::Number;
pub(crate) use name::NAMED_COLORS;
@ -469,14 +468,14 @@ impl Color {
/// Other color functions
impl Color {
pub fn to_ie_hex_str(&self) -> InternedString {
InternedString::get_or_intern(format!(
pub fn to_ie_hex_str(&self) -> String {
format!(
"#{:X}{:X}{:X}{:X}",
(self.alpha() * Number::from(255)).round().to_integer(),
self.red().to_integer(),
self.green().to_integer(),
self.blue().to_integer()
))
)
}
}

View File

@ -4,11 +4,9 @@
use once_cell::sync::Lazy;
use std::collections::HashMap;
use crate::interner::InternedString;
pub(crate) struct NamedColorMap {
name_to_rgba: HashMap<InternedString, [u8; 4]>,
rgba_to_name: HashMap<[u8; 4], InternedString>,
name_to_rgba: HashMap<&'static str, [u8; 4]>,
rgba_to_name: HashMap<[u8; 4], &'static str>,
}
impl NamedColorMap {
@ -19,581 +17,161 @@ impl NamedColorMap {
}
}
fn insert(&mut self, name: InternedString, rgba: [u8; 4]) {
pub fn insert(&mut self, name: &'static str, rgba: [u8; 4]) {
self.name_to_rgba.insert(name, rgba);
self.rgba_to_name.insert(rgba, name);
}
pub fn get_by_name(&self, name: InternedString) -> Option<&[u8; 4]> {
self.name_to_rgba.get(&name)
pub fn get_by_name(&self, name: &str) -> Option<&[u8; 4]> {
self.name_to_rgba.get(name)
}
pub fn get_by_rgba(&self, rgba: [u8; 4]) -> Option<&InternedString> {
pub fn get_by_rgba(&self, rgba: [u8; 4]) -> Option<&&str> {
self.rgba_to_name.get(&rgba)
}
}
pub(crate) static NAMED_COLORS: Lazy<NamedColorMap> = Lazy::new(|| {
let mut m = NamedColorMap::with_capacity(150);
m.insert(
InternedString::get_or_intern("aliceblue"),
[0xF0, 0xF8, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("antiquewhite"),
[0xFA, 0xEB, 0xD7, 0xFF],
);
m.insert(
InternedString::get_or_intern("aqua"),
[0x00, 0xFF, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("aquamarine"),
[0x7F, 0xFF, 0xD4, 0xFF],
);
m.insert(
InternedString::get_or_intern("azure"),
[0xF0, 0xFF, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("beige"),
[0xF5, 0xF5, 0xDC, 0xFF],
);
m.insert(
InternedString::get_or_intern("bisque"),
[0xFF, 0xE4, 0xC4, 0xFF],
);
m.insert(
InternedString::get_or_intern("black"),
[0x00, 0x00, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("blanchedalmond"),
[0xFF, 0xEB, 0xCD, 0xFF],
);
m.insert(
InternedString::get_or_intern("blue"),
[0x00, 0x00, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("blueviolet"),
[0x8A, 0x2B, 0xE2, 0xFF],
);
m.insert(
InternedString::get_or_intern("brown"),
[0xA5, 0x2A, 0x2A, 0xFF],
);
m.insert(
InternedString::get_or_intern("burlywood"),
[0xDE, 0xB8, 0x87, 0xFF],
);
m.insert(
InternedString::get_or_intern("cadetblue"),
[0x5F, 0x9E, 0xA0, 0xFF],
);
m.insert(
InternedString::get_or_intern("chartreuse"),
[0x7F, 0xFF, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("chocolate"),
[0xD2, 0x69, 0x1E, 0xFF],
);
m.insert(
InternedString::get_or_intern("coral"),
[0xFF, 0x7F, 0x50, 0xFF],
);
m.insert(
InternedString::get_or_intern("cornflowerblue"),
[0x64, 0x95, 0xED, 0xFF],
);
m.insert(
InternedString::get_or_intern("cornsilk"),
[0xFF, 0xF8, 0xDC, 0xFF],
);
m.insert(
InternedString::get_or_intern("crimson"),
[0xDC, 0x14, 0x3C, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkblue"),
[0x00, 0x00, 0x8B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkcyan"),
[0x00, 0x8B, 0x8B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkgoldenrod"),
[0xB8, 0x86, 0x0B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkgray"),
[0xA9, 0xA9, 0xA9, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkgreen"),
[0x00, 0x64, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkkhaki"),
[0xBD, 0xB7, 0x6B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkmagenta"),
[0x8B, 0x00, 0x8B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkolivegreen"),
[0x55, 0x6B, 0x2F, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkorange"),
[0xFF, 0x8C, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkorchid"),
[0x99, 0x32, 0xCC, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkred"),
[0x8B, 0x00, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("darksalmon"),
[0xE9, 0x96, 0x7A, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkseagreen"),
[0x8F, 0xBC, 0x8F, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkslateblue"),
[0x48, 0x3D, 0x8B, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkslategray"),
[0x2F, 0x4F, 0x4F, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkturquoise"),
[0x00, 0xCE, 0xD1, 0xFF],
);
m.insert(
InternedString::get_or_intern("darkviolet"),
[0x94, 0x00, 0xD3, 0xFF],
);
m.insert(
InternedString::get_or_intern("deeppink"),
[0xFF, 0x14, 0x93, 0xFF],
);
m.insert(
InternedString::get_or_intern("deepskyblue"),
[0x00, 0xBF, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("dimgray"),
[0x69, 0x69, 0x69, 0xFF],
);
m.insert(
InternedString::get_or_intern("dodgerblue"),
[0x1E, 0x90, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("firebrick"),
[0xB2, 0x22, 0x22, 0xFF],
);
m.insert(
InternedString::get_or_intern("floralwhite"),
[0xFF, 0xFA, 0xF0, 0xFF],
);
m.insert(
InternedString::get_or_intern("forestgreen"),
[0x22, 0x8B, 0x22, 0xFF],
);
m.insert(
InternedString::get_or_intern("fuchsia"),
[0xFF, 0x00, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("gainsboro"),
[0xDC, 0xDC, 0xDC, 0xFF],
);
m.insert(
InternedString::get_or_intern("ghostwhite"),
[0xF8, 0xF8, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("gold"),
[0xFF, 0xD7, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("goldenrod"),
[0xDA, 0xA5, 0x20, 0xFF],
);
m.insert(
InternedString::get_or_intern("gray"),
[0x80, 0x80, 0x80, 0xFF],
);
m.insert(
InternedString::get_or_intern("green"),
[0x00, 0x80, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("greenyellow"),
[0xAD, 0xFF, 0x2F, 0xFF],
);
m.insert(
InternedString::get_or_intern("honeydew"),
[0xF0, 0xFF, 0xF0, 0xFF],
);
m.insert(
InternedString::get_or_intern("hotpink"),
[0xFF, 0x69, 0xB4, 0xFF],
);
m.insert(
InternedString::get_or_intern("indianred"),
[0xCD, 0x5C, 0x5C, 0xFF],
);
m.insert(
InternedString::get_or_intern("indigo"),
[0x4B, 0x00, 0x82, 0xFF],
);
m.insert(
InternedString::get_or_intern("ivory"),
[0xFF, 0xFF, 0xF0, 0xFF],
);
m.insert(
InternedString::get_or_intern("khaki"),
[0xF0, 0xE6, 0x8C, 0xFF],
);
m.insert(
InternedString::get_or_intern("lavender"),
[0xE6, 0xE6, 0xFA, 0xFF],
);
m.insert(
InternedString::get_or_intern("lavenderblush"),
[0xFF, 0xF0, 0xF5, 0xFF],
);
m.insert(
InternedString::get_or_intern("lawngreen"),
[0x7C, 0xFC, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("lemonchiffon"),
[0xFF, 0xFA, 0xCD, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightblue"),
[0xAD, 0xD8, 0xE6, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightcoral"),
[0xF0, 0x80, 0x80, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightcyan"),
[0xE0, 0xFF, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightgoldenrodyellow"),
[0xFA, 0xFA, 0xD2, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightgray"),
[0xD3, 0xD3, 0xD3, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightgreen"),
[0x90, 0xEE, 0x90, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightpink"),
[0xFF, 0xB6, 0xC1, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightsalmon"),
[0xFF, 0xA0, 0x7A, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightseagreen"),
[0x20, 0xB2, 0xAA, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightskyblue"),
[0x87, 0xCE, 0xFA, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightslategray"),
[0x77, 0x88, 0x99, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightsteelblue"),
[0xB0, 0xC4, 0xDE, 0xFF],
);
m.insert(
InternedString::get_or_intern("lightyellow"),
[0xFF, 0xFF, 0xE0, 0xFF],
);
m.insert(
InternedString::get_or_intern("lime"),
[0x00, 0xFF, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("limegreen"),
[0x32, 0xCD, 0x32, 0xFF],
);
m.insert(
InternedString::get_or_intern("linen"),
[0xFA, 0xF0, 0xE6, 0xFF],
);
m.insert(
InternedString::get_or_intern("maroon"),
[0x80, 0x00, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumaquamarine"),
[0x66, 0xCD, 0xAA, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumblue"),
[0x00, 0x00, 0xCD, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumorchid"),
[0xBA, 0x55, 0xD3, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumpurple"),
[0x93, 0x70, 0xDB, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumseagreen"),
[0x3C, 0xB3, 0x71, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumslateblue"),
[0x7B, 0x68, 0xEE, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumspringgreen"),
[0x00, 0xFA, 0x9A, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumturquoise"),
[0x48, 0xD1, 0xCC, 0xFF],
);
m.insert(
InternedString::get_or_intern("mediumvioletred"),
[0xC7, 0x15, 0x85, 0xFF],
);
m.insert(
InternedString::get_or_intern("midnightblue"),
[0x19, 0x19, 0x70, 0xFF],
);
m.insert(
InternedString::get_or_intern("mintcream"),
[0xF5, 0xFF, 0xFA, 0xFF],
);
m.insert(
InternedString::get_or_intern("mistyrose"),
[0xFF, 0xE4, 0xE1, 0xFF],
);
m.insert(
InternedString::get_or_intern("moccasin"),
[0xFF, 0xE4, 0xB5, 0xFF],
);
m.insert(
InternedString::get_or_intern("navajowhite"),
[0xFF, 0xDE, 0xAD, 0xFF],
);
m.insert(
InternedString::get_or_intern("navy"),
[0x00, 0x00, 0x80, 0xFF],
);
m.insert(
InternedString::get_or_intern("oldlace"),
[0xFD, 0xF5, 0xE6, 0xFF],
);
m.insert(
InternedString::get_or_intern("olive"),
[0x80, 0x80, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("olivedrab"),
[0x6B, 0x8E, 0x23, 0xFF],
);
m.insert(
InternedString::get_or_intern("orange"),
[0xFF, 0xA5, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("orangered"),
[0xFF, 0x45, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("orchid"),
[0xDA, 0x70, 0xD6, 0xFF],
);
m.insert(
InternedString::get_or_intern("palegoldenrod"),
[0xEE, 0xE8, 0xAA, 0xFF],
);
m.insert(
InternedString::get_or_intern("palegreen"),
[0x98, 0xFB, 0x98, 0xFF],
);
m.insert(
InternedString::get_or_intern("paleturquoise"),
[0xAF, 0xEE, 0xEE, 0xFF],
);
m.insert(
InternedString::get_or_intern("palevioletred"),
[0xDB, 0x70, 0x93, 0xFF],
);
m.insert(
InternedString::get_or_intern("papayawhip"),
[0xFF, 0xEF, 0xD5, 0xFF],
);
m.insert(
InternedString::get_or_intern("peachpuff"),
[0xFF, 0xDA, 0xB9, 0xFF],
);
m.insert(
InternedString::get_or_intern("peru"),
[0xCD, 0x85, 0x3F, 0xFF],
);
m.insert(
InternedString::get_or_intern("pink"),
[0xFF, 0xC0, 0xCB, 0xFF],
);
m.insert(
InternedString::get_or_intern("plum"),
[0xDD, 0xA0, 0xDD, 0xFF],
);
m.insert(
InternedString::get_or_intern("powderblue"),
[0xB0, 0xE0, 0xE6, 0xFF],
);
m.insert(
InternedString::get_or_intern("purple"),
[0x80, 0x00, 0x80, 0xFF],
);
m.insert(
InternedString::get_or_intern("rebeccapurple"),
[0x66, 0x33, 0x99, 0xFF],
);
m.insert(
InternedString::get_or_intern("red"),
[0xFF, 0x00, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("rosybrown"),
[0xBC, 0x8F, 0x8F, 0xFF],
);
m.insert(
InternedString::get_or_intern("royalblue"),
[0x41, 0x69, 0xE1, 0xFF],
);
m.insert(
InternedString::get_or_intern("saddlebrown"),
[0x8B, 0x45, 0x13, 0xFF],
);
m.insert(
InternedString::get_or_intern("salmon"),
[0xFA, 0x80, 0x72, 0xFF],
);
m.insert(
InternedString::get_or_intern("sandybrown"),
[0xF4, 0xA4, 0x60, 0xFF],
);
m.insert(
InternedString::get_or_intern("seagreen"),
[0x2E, 0x8B, 0x57, 0xFF],
);
m.insert(
InternedString::get_or_intern("seashell"),
[0xFF, 0xF5, 0xEE, 0xFF],
);
m.insert(
InternedString::get_or_intern("sienna"),
[0xA0, 0x52, 0x2D, 0xFF],
);
m.insert(
InternedString::get_or_intern("silver"),
[0xC0, 0xC0, 0xC0, 0xFF],
);
m.insert(
InternedString::get_or_intern("skyblue"),
[0x87, 0xCE, 0xEB, 0xFF],
);
m.insert(
InternedString::get_or_intern("slateblue"),
[0x6A, 0x5A, 0xCD, 0xFF],
);
m.insert(
InternedString::get_or_intern("slategray"),
[0x70, 0x80, 0x90, 0xFF],
);
m.insert(
InternedString::get_or_intern("snow"),
[0xFF, 0xFA, 0xFA, 0xFF],
);
m.insert(
InternedString::get_or_intern("springgreen"),
[0x00, 0xFF, 0x7F, 0xFF],
);
m.insert(
InternedString::get_or_intern("steelblue"),
[0x46, 0x82, 0xB4, 0xFF],
);
m.insert(
InternedString::get_or_intern("tan"),
[0xD2, 0xB4, 0x8C, 0xFF],
);
m.insert(
InternedString::get_or_intern("teal"),
[0x00, 0x80, 0x80, 0xFF],
);
m.insert(
InternedString::get_or_intern("thistle"),
[0xD8, 0xBF, 0xD8, 0xFF],
);
m.insert(
InternedString::get_or_intern("tomato"),
[0xFF, 0x63, 0x47, 0xFF],
);
m.insert(
InternedString::get_or_intern("turquoise"),
[0x40, 0xE0, 0xD0, 0xFF],
);
m.insert(
InternedString::get_or_intern("violet"),
[0xEE, 0x82, 0xEE, 0xFF],
);
m.insert(
InternedString::get_or_intern("wheat"),
[0xF5, 0xDE, 0xB3, 0xFF],
);
m.insert(
InternedString::get_or_intern("white"),
[0xFF, 0xFF, 0xFF, 0xFF],
);
m.insert(
InternedString::get_or_intern("whitesmoke"),
[0xF5, 0xF5, 0xF5, 0xFF],
);
m.insert(
InternedString::get_or_intern("yellow"),
[0xFF, 0xFF, 0x00, 0xFF],
);
m.insert(
InternedString::get_or_intern("yellowgreen"),
[0x9A, 0xCD, 0x32, 0xFF],
);
m.insert(
InternedString::get_or_intern("transparent"),
[0x00, 0x00, 0x00, 0x00],
);
m.insert("aliceblue", [0xF0, 0xF8, 0xFF, 0xFF]);
m.insert("antiquewhite", [0xFA, 0xEB, 0xD7, 0xFF]);
m.insert("aqua", [0x00, 0xFF, 0xFF, 0xFF]);
m.insert("aquamarine", [0x7F, 0xFF, 0xD4, 0xFF]);
m.insert("azure", [0xF0, 0xFF, 0xFF, 0xFF]);
m.insert("beige", [0xF5, 0xF5, 0xDC, 0xFF]);
m.insert("bisque", [0xFF, 0xE4, 0xC4, 0xFF]);
m.insert("black", [0x00, 0x00, 0x00, 0xFF]);
m.insert("blanchedalmond", [0xFF, 0xEB, 0xCD, 0xFF]);
m.insert("blue", [0x00, 0x00, 0xFF, 0xFF]);
m.insert("blueviolet", [0x8A, 0x2B, 0xE2, 0xFF]);
m.insert("brown", [0xA5, 0x2A, 0x2A, 0xFF]);
m.insert("burlywood", [0xDE, 0xB8, 0x87, 0xFF]);
m.insert("cadetblue", [0x5F, 0x9E, 0xA0, 0xFF]);
m.insert("chartreuse", [0x7F, 0xFF, 0x00, 0xFF]);
m.insert("chocolate", [0xD2, 0x69, 0x1E, 0xFF]);
m.insert("coral", [0xFF, 0x7F, 0x50, 0xFF]);
m.insert("cornflowerblue", [0x64, 0x95, 0xED, 0xFF]);
m.insert("cornsilk", [0xFF, 0xF8, 0xDC, 0xFF]);
m.insert("crimson", [0xDC, 0x14, 0x3C, 0xFF]);
m.insert("darkblue", [0x00, 0x00, 0x8B, 0xFF]);
m.insert("darkcyan", [0x00, 0x8B, 0x8B, 0xFF]);
m.insert("darkgoldenrod", [0xB8, 0x86, 0x0B, 0xFF]);
m.insert("darkgray", [0xA9, 0xA9, 0xA9, 0xFF]);
m.insert("darkgreen", [0x00, 0x64, 0x00, 0xFF]);
m.insert("darkkhaki", [0xBD, 0xB7, 0x6B, 0xFF]);
m.insert("darkmagenta", [0x8B, 0x00, 0x8B, 0xFF]);
m.insert("darkolivegreen", [0x55, 0x6B, 0x2F, 0xFF]);
m.insert("darkorange", [0xFF, 0x8C, 0x00, 0xFF]);
m.insert("darkorchid", [0x99, 0x32, 0xCC, 0xFF]);
m.insert("darkred", [0x8B, 0x00, 0x00, 0xFF]);
m.insert("darksalmon", [0xE9, 0x96, 0x7A, 0xFF]);
m.insert("darkseagreen", [0x8F, 0xBC, 0x8F, 0xFF]);
m.insert("darkslateblue", [0x48, 0x3D, 0x8B, 0xFF]);
m.insert("darkslategray", [0x2F, 0x4F, 0x4F, 0xFF]);
m.insert("darkturquoise", [0x00, 0xCE, 0xD1, 0xFF]);
m.insert("darkviolet", [0x94, 0x00, 0xD3, 0xFF]);
m.insert("deeppink", [0xFF, 0x14, 0x93, 0xFF]);
m.insert("deepskyblue", [0x00, 0xBF, 0xFF, 0xFF]);
m.insert("dimgray", [0x69, 0x69, 0x69, 0xFF]);
m.insert("dodgerblue", [0x1E, 0x90, 0xFF, 0xFF]);
m.insert("firebrick", [0xB2, 0x22, 0x22, 0xFF]);
m.insert("floralwhite", [0xFF, 0xFA, 0xF0, 0xFF]);
m.insert("forestgreen", [0x22, 0x8B, 0x22, 0xFF]);
m.insert("fuchsia", [0xFF, 0x00, 0xFF, 0xFF]);
m.insert("gainsboro", [0xDC, 0xDC, 0xDC, 0xFF]);
m.insert("ghostwhite", [0xF8, 0xF8, 0xFF, 0xFF]);
m.insert("gold", [0xFF, 0xD7, 0x00, 0xFF]);
m.insert("goldenrod", [0xDA, 0xA5, 0x20, 0xFF]);
m.insert("gray", [0x80, 0x80, 0x80, 0xFF]);
m.insert("green", [0x00, 0x80, 0x00, 0xFF]);
m.insert("greenyellow", [0xAD, 0xFF, 0x2F, 0xFF]);
m.insert("honeydew", [0xF0, 0xFF, 0xF0, 0xFF]);
m.insert("hotpink", [0xFF, 0x69, 0xB4, 0xFF]);
m.insert("indianred", [0xCD, 0x5C, 0x5C, 0xFF]);
m.insert("indigo", [0x4B, 0x00, 0x82, 0xFF]);
m.insert("ivory", [0xFF, 0xFF, 0xF0, 0xFF]);
m.insert("khaki", [0xF0, 0xE6, 0x8C, 0xFF]);
m.insert("lavender", [0xE6, 0xE6, 0xFA, 0xFF]);
m.insert("lavenderblush", [0xFF, 0xF0, 0xF5, 0xFF]);
m.insert("lawngreen", [0x7C, 0xFC, 0x00, 0xFF]);
m.insert("lemonchiffon", [0xFF, 0xFA, 0xCD, 0xFF]);
m.insert("lightblue", [0xAD, 0xD8, 0xE6, 0xFF]);
m.insert("lightcoral", [0xF0, 0x80, 0x80, 0xFF]);
m.insert("lightcyan", [0xE0, 0xFF, 0xFF, 0xFF]);
m.insert("lightgoldenrodyellow", [0xFA, 0xFA, 0xD2, 0xFF]);
m.insert("lightgray", [0xD3, 0xD3, 0xD3, 0xFF]);
m.insert("lightgreen", [0x90, 0xEE, 0x90, 0xFF]);
m.insert("lightpink", [0xFF, 0xB6, 0xC1, 0xFF]);
m.insert("lightsalmon", [0xFF, 0xA0, 0x7A, 0xFF]);
m.insert("lightseagreen", [0x20, 0xB2, 0xAA, 0xFF]);
m.insert("lightskyblue", [0x87, 0xCE, 0xFA, 0xFF]);
m.insert("lightslategray", [0x77, 0x88, 0x99, 0xFF]);
m.insert("lightsteelblue", [0xB0, 0xC4, 0xDE, 0xFF]);
m.insert("lightyellow", [0xFF, 0xFF, 0xE0, 0xFF]);
m.insert("lime", [0x00, 0xFF, 0x00, 0xFF]);
m.insert("limegreen", [0x32, 0xCD, 0x32, 0xFF]);
m.insert("linen", [0xFA, 0xF0, 0xE6, 0xFF]);
m.insert("maroon", [0x80, 0x00, 0x00, 0xFF]);
m.insert("mediumaquamarine", [0x66, 0xCD, 0xAA, 0xFF]);
m.insert("mediumblue", [0x00, 0x00, 0xCD, 0xFF]);
m.insert("mediumorchid", [0xBA, 0x55, 0xD3, 0xFF]);
m.insert("mediumpurple", [0x93, 0x70, 0xDB, 0xFF]);
m.insert("mediumseagreen", [0x3C, 0xB3, 0x71, 0xFF]);
m.insert("mediumslateblue", [0x7B, 0x68, 0xEE, 0xFF]);
m.insert("mediumspringgreen", [0x00, 0xFA, 0x9A, 0xFF]);
m.insert("mediumturquoise", [0x48, 0xD1, 0xCC, 0xFF]);
m.insert("mediumvioletred", [0xC7, 0x15, 0x85, 0xFF]);
m.insert("midnightblue", [0x19, 0x19, 0x70, 0xFF]);
m.insert("mintcream", [0xF5, 0xFF, 0xFA, 0xFF]);
m.insert("mistyrose", [0xFF, 0xE4, 0xE1, 0xFF]);
m.insert("moccasin", [0xFF, 0xE4, 0xB5, 0xFF]);
m.insert("navajowhite", [0xFF, 0xDE, 0xAD, 0xFF]);
m.insert("navy", [0x00, 0x00, 0x80, 0xFF]);
m.insert("oldlace", [0xFD, 0xF5, 0xE6, 0xFF]);
m.insert("olive", [0x80, 0x80, 0x00, 0xFF]);
m.insert("olivedrab", [0x6B, 0x8E, 0x23, 0xFF]);
m.insert("orange", [0xFF, 0xA5, 0x00, 0xFF]);
m.insert("orangered", [0xFF, 0x45, 0x00, 0xFF]);
m.insert("orchid", [0xDA, 0x70, 0xD6, 0xFF]);
m.insert("palegoldenrod", [0xEE, 0xE8, 0xAA, 0xFF]);
m.insert("palegreen", [0x98, 0xFB, 0x98, 0xFF]);
m.insert("paleturquoise", [0xAF, 0xEE, 0xEE, 0xFF]);
m.insert("palevioletred", [0xDB, 0x70, 0x93, 0xFF]);
m.insert("papayawhip", [0xFF, 0xEF, 0xD5, 0xFF]);
m.insert("peachpuff", [0xFF, 0xDA, 0xB9, 0xFF]);
m.insert("peru", [0xCD, 0x85, 0x3F, 0xFF]);
m.insert("pink", [0xFF, 0xC0, 0xCB, 0xFF]);
m.insert("plum", [0xDD, 0xA0, 0xDD, 0xFF]);
m.insert("powderblue", [0xB0, 0xE0, 0xE6, 0xFF]);
m.insert("purple", [0x80, 0x00, 0x80, 0xFF]);
m.insert("rebeccapurple", [0x66, 0x33, 0x99, 0xFF]);
m.insert("red", [0xFF, 0x00, 0x00, 0xFF]);
m.insert("rosybrown", [0xBC, 0x8F, 0x8F, 0xFF]);
m.insert("royalblue", [0x41, 0x69, 0xE1, 0xFF]);
m.insert("saddlebrown", [0x8B, 0x45, 0x13, 0xFF]);
m.insert("salmon", [0xFA, 0x80, 0x72, 0xFF]);
m.insert("sandybrown", [0xF4, 0xA4, 0x60, 0xFF]);
m.insert("seagreen", [0x2E, 0x8B, 0x57, 0xFF]);
m.insert("seashell", [0xFF, 0xF5, 0xEE, 0xFF]);
m.insert("sienna", [0xA0, 0x52, 0x2D, 0xFF]);
m.insert("silver", [0xC0, 0xC0, 0xC0, 0xFF]);
m.insert("skyblue", [0x87, 0xCE, 0xEB, 0xFF]);
m.insert("slateblue", [0x6A, 0x5A, 0xCD, 0xFF]);
m.insert("slategray", [0x70, 0x80, 0x90, 0xFF]);
m.insert("snow", [0xFF, 0xFA, 0xFA, 0xFF]);
m.insert("springgreen", [0x00, 0xFF, 0x7F, 0xFF]);
m.insert("steelblue", [0x46, 0x82, 0xB4, 0xFF]);
m.insert("tan", [0xD2, 0xB4, 0x8C, 0xFF]);
m.insert("teal", [0x00, 0x80, 0x80, 0xFF]);
m.insert("thistle", [0xD8, 0xBF, 0xD8, 0xFF]);
m.insert("tomato", [0xFF, 0x63, 0x47, 0xFF]);
m.insert("turquoise", [0x40, 0xE0, 0xD0, 0xFF]);
m.insert("violet", [0xEE, 0x82, 0xEE, 0xFF]);
m.insert("wheat", [0xF5, 0xDE, 0xB3, 0xFF]);
m.insert("white", [0xFF, 0xFF, 0xFF, 0xFF]);
m.insert("whitesmoke", [0xF5, 0xF5, 0xF5, 0xFF]);
m.insert("yellow", [0xFF, 0xFF, 0x00, 0xFF]);
m.insert("yellowgreen", [0x9A, 0xCD, 0x32, 0xFF]);
m.insert("transparent", [0x00, 0x00, 0x00, 0x00]);
m
});

View File

@ -1,4 +1,3 @@
use crate::interner::InternedString;
use std::fmt::{self, Display, Write};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -120,38 +119,3 @@ impl Display for QualifiedName {
f.write_str(&self.ident)
}
}
#[derive(Debug, Clone, Hash, Eq, PartialEq, Copy)]
pub(crate) struct Identifier(InternedString);
impl Into<Identifier> for InternedString {
fn into(self) -> Identifier {
Identifier(InternedString::get_or_intern(
self.resolve_ref().replace('_', "-"),
))
}
}
impl From<String> for Identifier {
fn from(s: String) -> Identifier {
Identifier(InternedString::get_or_intern(s.replace('_', "-")))
}
}
impl Into<Identifier> for &String {
fn into(self) -> Identifier {
Identifier(InternedString::get_or_intern(self.replace('_', "-")))
}
}
impl Into<Identifier> for &str {
fn into(self) -> Identifier {
Identifier(InternedString::get_or_intern(self.replace('_', "-")))
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

View File

@ -1,35 +0,0 @@
use lasso::{Rodeo, Spur};
use std::cell::RefCell;
use std::fmt::{self, Display};
thread_local!(static STRINGS: RefCell<Rodeo<Spur>> = RefCell::new(Rodeo::default()));
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct InternedString(Spur);
impl InternedString {
pub fn get_or_intern<T: AsRef<str>>(s: T) -> Self {
Self(STRINGS.with(|interner| interner.borrow_mut().get_or_intern(s)))
}
pub fn resolve(self) -> String {
STRINGS.with(|interner| interner.borrow().resolve(&self.0).to_string())
}
pub fn is_empty(self) -> bool {
self.resolve_ref() == ""
}
pub fn resolve_ref<'a>(self) -> &'a str {
unsafe {
STRINGS.with(|interner| &(*(interner.as_ptr()).as_ref().unwrap().resolve(&self.0)))
}
}
}
impl Display for InternedString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
STRINGS.with(|interner| write!(f, "{}", interner.borrow().resolve(&self.0)))
}
}

View File

@ -90,7 +90,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
use crate::atrule::{AtRule, AtRuleKind, Function, Mixin};
pub use crate::error::{SassError, SassResult};
use crate::interner::InternedString;
use crate::scope::{insert_global_var, Scope};
use crate::selector::Selector;
use crate::style::Style;
@ -110,7 +109,6 @@ mod color;
mod common;
mod error;
mod imports;
mod interner;
mod lexer;
mod output;
mod scope;
@ -200,7 +198,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
&mut values.into_iter().peekmore(),
scope,
super_selector,
InternedString::get_or_intern(""),
String::new(),
tok.pos,
)?;
return Ok(Some(Spanned {
@ -220,7 +218,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
devour_whitespace(toks);
return Ok(Some(Spanned {
node: Expr::Style(Box::new(Style {
property: InternedString::get_or_intern(""),
property: String::new(),
value: Value::Null.span(span),
})),
span,
@ -230,7 +228,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
&mut v,
scope,
super_selector,
InternedString::get_or_intern(""),
String::new(),
span_before,
)?;
let value = Style::parse_value(&mut v, scope, super_selector)?;
@ -257,7 +255,7 @@ pub(crate) fn eat_expr<I: Iterator<Item = Token>>(
&mut v,
scope,
super_selector,
InternedString::get_or_intern(""),
String::new(),
tok.pos,
)?;
let value = Style::parse_value(&mut v, scope, super_selector)?;

View File

@ -4,70 +4,66 @@ use std::collections::HashMap;
use codemap::Spanned;
use crate::atrule::{Function, Mixin};
use crate::common::Identifier;
use crate::error::SassResult;
use crate::value::Value;
thread_local!(pub(crate) static GLOBAL_SCOPE: RefCell<Scope> = RefCell::new(Scope::new()));
pub(crate) fn get_global_var<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Spanned<Value>> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().vars().get(&s.node.into()) {
pub(crate) fn get_global_var(s: Spanned<String>) -> SassResult<Spanned<Value>> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().vars().get(&s.node) {
Some(v) => Ok(v.clone()),
None => Err(("Undefined variable.", s.span).into()),
})
}
/// Returns true if a variable exists in the *global* scope
pub(crate) fn global_var_exists<T: Into<Identifier>>(v: T) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().vars().contains_key(&v.into()))
pub(crate) fn global_var_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().vars().contains_key(&v.replace('_', "-")))
}
pub(crate) fn insert_global_var<T: Into<Identifier>>(
s: T,
v: Spanned<Value>,
) -> SassResult<Option<Spanned<Value>>> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s.into(), v))
pub(crate) fn insert_global_var(s: &str, v: Spanned<Value>) -> SassResult<Option<Spanned<Value>>> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_var(s, v))
}
pub(crate) fn get_global_fn<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Function> {
GLOBAL_SCOPE.with(
|scope| match scope.borrow().functions().get(&s.node.into()) {
pub(crate) fn get_global_fn(s: Spanned<String>) -> SassResult<Function> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().functions().get(&s.node) {
Some(v) => Ok(v.clone()),
None => Err(("Undefined function.", s.span).into()),
},
)
})
}
/// Returns true if a function exists in the *global* scope
pub(crate) fn global_fn_exists<T: Into<Identifier>>(v: T) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().functions().contains_key(&v.into()))
pub(crate) fn global_fn_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| {
scope
.borrow()
.functions()
.contains_key(&v.replace('_', "-"))
})
}
pub(crate) fn insert_global_fn<T: Into<Identifier>>(s: T, v: Function) -> Option<Function> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_fn(s.into(), v))
pub(crate) fn insert_global_fn(s: &str, v: Function) -> Option<Function> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_fn(s, v))
}
pub(crate) fn get_global_mixin<T: Into<Identifier>>(s: Spanned<T>) -> SassResult<Mixin> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().mixins().get(&s.node.into()) {
pub(crate) fn get_global_mixin(s: Spanned<String>) -> SassResult<Mixin> {
GLOBAL_SCOPE.with(|scope| match scope.borrow().mixins().get(&s.node) {
Some(v) => Ok(v.clone()),
None => Err(("Undefined mixin.", s.span).into()),
})
}
/// Returns true if a mixin exists in the *global* scope
pub(crate) fn global_mixin_exists<T: Into<Identifier>>(v: T) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().mixins().contains_key(&v.into()))
pub(crate) fn global_mixin_exists(v: &str) -> bool {
GLOBAL_SCOPE.with(|scope| scope.borrow().mixins().contains_key(&v.replace('_', "-")))
}
pub(crate) fn insert_global_mixin<T: Into<Identifier>>(s: T, v: Mixin) -> Option<Mixin> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_mixin(s.into(), v))
pub(crate) fn insert_global_mixin(s: &str, v: Mixin) -> Option<Mixin> {
GLOBAL_SCOPE.with(|scope| scope.borrow_mut().insert_mixin(s, v))
}
#[derive(Debug, Clone)]
pub(crate) struct Scope {
vars: HashMap<Identifier, Spanned<Value>>,
mixins: HashMap<Identifier, Mixin>,
functions: HashMap<Identifier, Function>,
vars: HashMap<String, Spanned<Value>>,
mixins: HashMap<String, Mixin>,
functions: HashMap<String, Function>,
}
impl Scope {
@ -80,72 +76,68 @@ impl Scope {
}
}
pub const fn vars(&self) -> &HashMap<Identifier, Spanned<Value>> {
pub const fn vars(&self) -> &HashMap<String, Spanned<Value>> {
&self.vars
}
pub const fn functions(&self) -> &HashMap<Identifier, Function> {
pub const fn functions(&self) -> &HashMap<String, Function> {
&self.functions
}
pub const fn mixins(&self) -> &HashMap<Identifier, Mixin> {
pub const fn mixins(&self) -> &HashMap<String, Mixin> {
&self.mixins
}
pub fn get_var<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Spanned<Value>> {
let name = name.map_node(|n| n.into());
pub fn get_var(&self, mut name: Spanned<String>) -> SassResult<Spanned<Value>> {
name.node = name.node.replace('_', "-");
match self.vars.get(&name.node) {
Some(v) => Ok(v.clone()),
None => get_global_var(name),
}
}
pub fn insert_var<T: Into<Identifier>>(
&mut self,
s: T,
v: Spanned<Value>,
) -> SassResult<Option<Spanned<Value>>> {
pub fn insert_var(&mut self, s: &str, v: Spanned<Value>) -> SassResult<Option<Spanned<Value>>> {
let Spanned { node, span } = v;
Ok(self.vars.insert(s.into(), node.eval(span)?))
Ok(self.vars.insert(s.replace('_', "-"), node.eval(span)?))
}
pub fn var_exists<T: Into<Identifier>>(&self, v: T) -> bool {
let name = v.into();
self.vars.contains_key(&name) || global_var_exists(name)
pub fn var_exists(&self, v: &str) -> bool {
let name = &v.replace('_', "-");
self.vars.contains_key(name) || global_var_exists(name)
}
pub fn get_mixin<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Mixin> {
let name = name.map_node(|n| n.into());
pub fn get_mixin(&self, mut name: Spanned<String>) -> SassResult<Mixin> {
name.node = name.node.replace('_', "-");
match self.mixins.get(&name.node) {
Some(v) => Ok(v.clone()),
None => get_global_mixin(name),
}
}
pub fn insert_mixin<T: Into<Identifier>>(&mut self, s: T, v: Mixin) -> Option<Mixin> {
self.mixins.insert(s.into(), v)
pub fn insert_mixin(&mut self, s: &str, v: Mixin) -> Option<Mixin> {
self.mixins.insert(s.replace('_', "-"), v)
}
pub fn mixin_exists<T: Into<Identifier>>(&self, v: T) -> bool {
let name = v.into();
self.mixins.contains_key(&name) || global_mixin_exists(name)
pub fn mixin_exists(&self, v: &str) -> bool {
let name = &v.replace('_', "-");
self.mixins.contains_key(name) || global_mixin_exists(name)
}
pub fn get_fn<T: Into<Identifier>>(&self, name: Spanned<T>) -> SassResult<Function> {
let name = name.map_node(|n| n.into());
pub fn get_fn(&self, mut name: Spanned<String>) -> SassResult<Function> {
name.node = name.node.replace('_', "-");
match self.functions.get(&name.node) {
Some(v) => Ok(v.clone()),
None => get_global_fn(name),
}
}
pub fn insert_fn<T: Into<Identifier>>(&mut self, s: T, v: Function) -> Option<Function> {
self.functions.insert(s.into(), v)
pub fn insert_fn(&mut self, s: &str, v: Function) -> Option<Function> {
self.functions.insert(s.replace('_', "-"), v)
}
pub fn fn_exists<T: Into<Identifier>>(&self, v: T) -> bool {
let name = v.into();
self.functions.contains_key(&name) || global_fn_exists(name)
pub fn fn_exists(&self, v: &str) -> bool {
let name = &v.replace('_', "-");
self.functions.contains_key(name) || global_fn_exists(name)
}
pub fn extend(&mut self, other: Scope) {

View File

@ -7,7 +7,6 @@ use codemap::Span;
use super::{Selector, SelectorKind};
use crate::common::{QualifiedName, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::utils::{devour_whitespace, eat_ident, is_ident, parse_quoted_string};
use crate::value::Value;
@ -125,7 +124,7 @@ impl Attribute {
q @ '\'' | q @ '"' => {
toks.next();
match parse_quoted_string(toks, scope, q, super_selector)?.node {
Value::Ident(s, ..) => s.resolve().to_string(),
Value::Ident(s, ..) => s,
_ => unreachable!(),
}
}
@ -181,10 +180,7 @@ impl Display for Attribute {
// or having special emitter for quoted strings?
// (also avoids the clone because we can consume/modify self)
f.write_str(
&Value::Ident(
InternedString::get_or_intern(self.value.clone()),
QuoteKind::Quoted,
)
&Value::Ident(self.value.clone(), QuoteKind::Quoted)
.to_css_string(self.span)
.unwrap(),
)?;

View File

@ -4,7 +4,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
use crate::common::{Brackets, ListSeparator, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::utils::{
devour_whitespace, eat_comment, eat_ident_no_interpolation, parse_interpolation,
@ -58,12 +57,7 @@ impl SelectorPart {
Value::List(
kinds
.iter()
.map(|s| {
Value::Ident(
InternedString::get_or_intern(s.to_string()),
QuoteKind::None,
)
})
.map(|s| Value::Ident(s.to_string(), QuoteKind::None))
.collect(),
ListSeparator::Space,
Brackets::None,

View File

@ -3,7 +3,6 @@ use peekmore::PeekMoreIterator;
use codemap::{Span, Spanned};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::utils::{devour_whitespace, devour_whitespace_or_comment, eat_ident};
@ -13,7 +12,7 @@ use crate::{Expr, Token};
/// A style: `color: red`
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) struct Style {
pub property: InternedString,
pub property: String,
pub value: Spanned<Value>,
}
@ -22,9 +21,9 @@ impl Style {
toks: &mut PeekMoreIterator<I>,
scope: &Scope,
super_selector: &Selector,
super_property: InternedString,
super_property: String,
span_before: Span,
) -> SassResult<InternedString> {
) -> SassResult<String> {
StyleParser::new(scope, super_selector).parse_property(toks, super_property, span_before)
}
@ -58,7 +57,7 @@ impl Style {
toks: &mut PeekMoreIterator<I>,
scope: &Scope,
super_selector: &Selector,
super_property: InternedString,
super_property: String,
) -> SassResult<Expr> {
StyleParser::new(scope, super_selector).eat_style_group(toks, super_property, scope)
}
@ -89,7 +88,7 @@ impl<'a> StyleParser<'a> {
pub(crate) fn eat_style_group<I: Iterator<Item = Token>>(
&self,
toks: &mut PeekMoreIterator<I>,
super_property: InternedString,
super_property: String,
scope: &Scope,
) -> SassResult<Expr> {
let mut styles = Vec::new();
@ -100,7 +99,8 @@ impl<'a> StyleParser<'a> {
let span_before = toks.next().unwrap().pos;
devour_whitespace(toks);
loop {
let property = self.parse_property(toks, super_property, span_before)?;
let property =
self.parse_property(toks, super_property.clone(), span_before)?;
if let Some(tok) = toks.peek() {
if tok.kind == '{' {
match self.eat_style_group(toks, property, scope)? {
@ -133,7 +133,7 @@ impl<'a> StyleParser<'a> {
}
'{' => {
styles.push(Style {
property: property,
property: property.clone(),
value,
});
match self.eat_style_group(toks, property, scope)? {
@ -170,7 +170,7 @@ impl<'a> StyleParser<'a> {
}
'{' => {
let mut v = vec![Style {
property: super_property,
property: super_property.clone(),
value,
}];
match self.eat_style_group(toks, super_property, scope)? {
@ -195,9 +195,9 @@ impl<'a> StyleParser<'a> {
pub(crate) fn parse_property<I: Iterator<Item = Token>>(
&self,
toks: &mut PeekMoreIterator<I>,
super_property: InternedString,
mut super_property: String,
span_before: Span,
) -> SassResult<InternedString> {
) -> SassResult<String> {
devour_whitespace(toks);
let property = eat_ident(toks, self.scope, self.super_selector, span_before)?;
devour_whitespace_or_comment(toks)?;
@ -209,13 +209,12 @@ impl<'a> StyleParser<'a> {
}
if super_property.is_empty() {
Ok(InternedString::get_or_intern(property.node))
Ok(property.node)
} else {
let mut super_property = super_property.resolve().to_string();
super_property.reserve(1 + property.node.len());
super_property.push('-');
super_property.push_str(&property.node);
Ok(InternedString::get_or_intern(super_property))
Ok(super_property)
}
}
}

View File

@ -10,7 +10,6 @@ use peekmore::{PeekMore, PeekMoreIterator};
use wasm_bindgen::prelude::*;
use crate::atrule::{eat_include, AtRule, AtRuleKind};
use crate::common::Identifier;
use crate::error::{SassError, SassResult};
use crate::imports::import;
use crate::lexer::Lexer;
@ -165,9 +164,8 @@ impl<'a> StyleSheetParser<'a> {
let mut rules: Vec<Spanned<Stmt>> = Vec::new();
while let Some(Token { kind, .. }) = self.lexer.peek() {
match kind {
_ if is_selector_char(*kind) => {
rules.extend(self.eat_rules(&Selector::new(), &mut Scope::new())?)
}
_ if is_selector_char(*kind) => rules
.extend(self.eat_rules(&Selector::new(), &mut Scope::new())?),
'\t' | '\n' | ' ' => {
self.lexer.next();
continue;
@ -179,18 +177,15 @@ impl<'a> StyleSheetParser<'a> {
match self.lexer.peek() {
Some(Token { kind: ':', .. }) => {
self.lexer
.take(name.node.chars().count() + whitespace + 1)
self.lexer.take(name.node.chars().count() + whitespace + 1)
.for_each(drop);
devour_whitespace(self.lexer);
let name = name.map_node(|n| Identifier::from(n));
let VariableDecl { val, default, .. } =
eat_variable_value(self.lexer, &Scope::new(), &Selector::new())?;
if !(default && global_var_exists(name.node)) {
insert_global_var(name.node, val)?;
if !(default && global_var_exists(&name)) {
insert_global_var(&name.node, val)?;
}
}
Some(..) | None => return Err(("expected \":\".", name.span).into()),
@ -207,15 +202,17 @@ impl<'a> StyleSheetParser<'a> {
let comment = eat_comment(self.lexer, &Scope::new(), &Selector::new())?;
rules.push(comment.map_node(Stmt::MultilineComment));
}
_ => return Err(("expected selector.", pos).into()),
_ => return Err(("expected selector.", pos).into())
}
}
'@' => {
let span_before = self.lexer.next().unwrap().pos();
let Spanned {
node: at_rule_kind,
span,
} = eat_ident(self.lexer, &Scope::new(), &Selector::new(), span_before)?;
let Spanned { node: at_rule_kind, span } = eat_ident(
self.lexer,
&Scope::new(),
&Selector::new(),
span_before
)?;
if at_rule_kind.is_empty() {
return Err(("Expected identifier.", span).into());
}
@ -225,14 +222,14 @@ impl<'a> StyleSheetParser<'a> {
&Scope::new(),
&Selector::new(),
None,
span,
span
)?),
AtRuleKind::Import => {
devour_whitespace(self.lexer);
let mut file_name = String::new();
let next = match self.lexer.next() {
Some(v) => v,
None => todo!("expected input after @import"),
None => todo!("expected input after @import")
};
match next.kind {
q @ '"' | q @ '\'' => {
@ -241,12 +238,8 @@ impl<'a> StyleSheetParser<'a> {
self.lexer,
&Scope::new(),
q,
&Selector::new(),
)?
.node
.unquote()
.to_css_string(span)?,
);
&Selector::new())?
.node.unquote().to_css_string(span)?);
}
_ => return Err(("Expected string.", next.pos()).into()),
}
@ -258,22 +251,14 @@ impl<'a> StyleSheetParser<'a> {
devour_whitespace(self.lexer);
let (new_rules, new_scope) =
import(self.path, file_name.as_ref(), &mut self.map)?;
let (new_rules, new_scope) = import(self.path, file_name.as_ref(), &mut self.map)?;
rules.extend(new_rules);
GLOBAL_SCOPE.with(|s| {
s.borrow_mut().extend(new_scope);
});
}
v => {
let rule = AtRule::from_tokens(
v,
span,
self.lexer,
&mut Scope::new(),
&Selector::new(),
None,
)?;
let rule = AtRule::from_tokens(v, span, self.lexer, &mut Scope::new(), &Selector::new(), None)?;
match rule.node {
AtRule::Mixin(name, mixin) => {
insert_global_mixin(&name, *mixin);
@ -289,36 +274,17 @@ impl<'a> StyleSheetParser<'a> {
("This at-rule is not allowed here.", rule.span).into()
)
}
AtRule::For(f) => rules.extend(f.ruleset_eval(
&mut Scope::new(),
&Selector::new(),
None,
)?),
AtRule::While(w) => rules.extend(w.ruleset_eval(
&mut Scope::new(),
&Selector::new(),
true,
None,
)?),
AtRule::Each(e) => rules.extend(e.ruleset_eval(
&mut Scope::new(),
&Selector::new(),
None,
)?),
AtRule::Include(s) => rules.extend(s),
AtRule::Content => {
return Err((
"@content is only allowed within mixin declarations.",
rule.span,
)
.into())
AtRule::For(f) => rules.extend(f.ruleset_eval(&mut Scope::new(), &Selector::new(), None)?),
AtRule::While(w) => rules.extend(w.ruleset_eval(&mut Scope::new(), &Selector::new(), true, None)?),
AtRule::Each(e) => {
rules.extend(e.ruleset_eval(&mut Scope::new(), &Selector::new(), None)?)
}
AtRule::Include(s) => rules.extend(s),
AtRule::Content => return Err(
("@content is only allowed within mixin declarations.", rule.span
).into()),
AtRule::If(i) => {
rules.extend(i.eval(
&mut Scope::new(),
&Selector::new(),
None,
)?);
rules.extend(i.eval(&mut Scope::new(), &Selector::new(), None)?);
}
AtRule::AtRoot(root_rules) => rules.extend(root_rules),
AtRule::Unknown(..) => rules.push(rule.map_node(Stmt::AtRule)),
@ -326,13 +292,11 @@ impl<'a> StyleSheetParser<'a> {
}
}
}
}
},
'&' => {
return Err((
"Top-level selectors may not contain the parent selector \"&\".",
self.lexer.next().unwrap().pos(),
return Err(
("Top-level selectors may not contain the parent selector \"&\".", self.lexer.next().unwrap().pos()).into(),
)
.into())
}
c if c.is_control() => {
return Err(("expected selector.", self.lexer.next().unwrap().pos()).into());

View File

@ -6,7 +6,6 @@ use peekmore::PeekMoreIterator;
use crate::common::QuoteKind;
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::selector::Selector;
use crate::value::Value;
use crate::{Scope, Token};
@ -214,7 +213,7 @@ pub(crate) fn eat_ident<I: Iterator<Item = Token>>(
toks.next();
text.push_str(
&match parse_interpolation(toks, scope, super_selector)?.node {
Value::Ident(s, ..) => s.resolve().to_string(),
Value::Ident(s, ..) => s,
v => v.to_css_string(span)?.into(),
},
);
@ -292,7 +291,7 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
toks.next();
let interpolation = parse_interpolation(toks, scope, super_selector)?;
s.push_str(&match interpolation.node {
Value::Ident(s, ..) => s.resolve().to_string(),
Value::Ident(s, ..) => s,
v => v.to_css_string(interpolation.span)?.into(),
});
continue;
@ -346,7 +345,7 @@ pub(crate) fn parse_quoted_string<I: Iterator<Item = Token>>(
}
}
Ok(Spanned {
node: Value::Ident(InternedString::get_or_intern(s), QuoteKind::Quoted),
node: Value::Ident(s, QuoteKind::Quoted),
span,
})
}

View File

@ -113,7 +113,7 @@ pub(crate) fn try_eat_url<I: Iterator<Item = Token>>(
let (interpolation, count) = peek_interpolation(toks, scope, super_selector)?;
peek_counter += count;
buf.push_str(&match interpolation.node {
Value::Ident(s, ..) => s.resolve().to_string(),
Value::Ident(s, ..) => s,
v => v.to_css_string(interpolation.span)?.into(),
});
} else {

View File

@ -6,7 +6,6 @@ use codemap::{Span, Spanned};
use crate::color::Color;
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::unit::Unit;
use crate::utils::hex_char_for;
@ -34,7 +33,7 @@ pub(crate) enum Value {
UnaryOp(Op, Box<Value>),
BinaryOp(Box<Value>, Op, Box<Value>),
Paren(Box<Value>),
Ident(InternedString, QuoteKind),
Ident(String, QuoteKind),
Map(SassMap),
ArgList(Vec<Spanned<Value>>),
/// Returned by `get-function()`
@ -168,7 +167,6 @@ impl Value {
}
Self::Paren(val) => val.to_css_string(span)?,
Self::Ident(string, QuoteKind::None) => {
let string = string.resolve();
let mut after_newline = false;
let mut buf = String::with_capacity(string.len());
for c in string.chars() {
@ -191,9 +189,8 @@ impl Value {
Cow::Owned(buf)
}
Self::Ident(string, QuoteKind::Quoted) => {
let string = string.resolve();
let mut buf = String::with_capacity(string.len());
visit_quoted_string(&mut buf, false, &string)?;
visit_quoted_string(&mut buf, false, string)?;
Cow::Owned(buf)
}
Self::True => Cow::Borrowed("true"),
@ -252,7 +249,7 @@ impl Value {
pub fn is_special_function(&self) -> bool {
match self {
Self::Ident(s, QuoteKind::None) => is_special_function(s.resolve_ref()),
Self::Ident(s, QuoteKind::None) => is_special_function(s),
_ => false,
}
}

View File

@ -4,7 +4,6 @@ use codemap::{Span, Spanned};
use crate::common::{Op, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::unit::{Unit, UNIT_CONVERSION_TABLE};
use crate::value::Value;
@ -112,10 +111,7 @@ impl Value {
pub fn unary_op_plus(self, span: Span) -> SassResult<Self> {
Ok(match self.eval(span)?.node {
v @ Value::Dimension(..) => v,
v => Value::Ident(
InternedString::get_or_intern(format!("+{}", v.to_css_string(span)?)),
QuoteKind::None,
),
v => Value::Ident(format!("+{}", v.to_css_string(span)?), QuoteKind::None),
})
}
@ -263,28 +259,22 @@ impl Value {
Self::Function(..) | Self::ArgList(..) | Self::Map(..) => todo!(),
Self::Important | Self::True | Self::False => match other {
Self::Ident(s, QuoteKind::Quoted) => Value::Ident(
InternedString::get_or_intern(format!("{}{}", self.to_css_string(span)?, s)),
format!("{}{}", self.to_css_string(span)?, s),
QuoteKind::Quoted,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(self.to_css_string(span)?.into_owned()),
QuoteKind::None,
),
Self::Null => Value::Ident(self.to_css_string(span)?.into(), QuoteKind::None),
_ => Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
},
Self::Null => match other {
Self::Null => Self::Null,
_ => Value::Ident(
InternedString::get_or_intern(dbg!(other.to_css_string(span)?).into_owned()),
QuoteKind::None,
),
_ => Value::Ident(other.to_css_string(span)?.into(), QuoteKind::None),
},
Self::Dimension(num, unit) => match other {
Self::Dimension(num2, unit2) => {
@ -309,30 +299,14 @@ impl Value {
)
}
}
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!("{}{}{}", num, unit, s)),
q,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}{}", num, unit)),
QuoteKind::None,
),
Self::Ident(s, q) => Value::Ident(format!("{}{}{}", num, unit, s), q),
Self::Null => Value::Ident(format!("{}{}", num, unit), QuoteKind::None),
Self::List(..) => Value::Ident(
InternedString::get_or_intern(format!(
"{}{}{}",
num,
unit,
other.to_css_string(span)?
)),
format!("{}{}{}", num, unit, other.to_css_string(span)?),
QuoteKind::None,
),
Self::True | Self::False => Self::Ident(
InternedString::get_or_intern(format!(
"{}{}{}",
num,
unit,
other.to_css_string(span)?
)),
format!("{}{}{}", num, unit, other.to_css_string(span)?),
QuoteKind::None,
),
_ => {
@ -349,15 +323,10 @@ impl Value {
}
},
Self::Color(c) => match other {
Self::Ident(s, q) => {
Value::Ident(InternedString::get_or_intern(format!("{}{}", c, s)), q)
}
Self::Null => Value::Ident(
InternedString::get_or_intern(c.to_string()),
QuoteKind::None,
),
Self::Ident(s, q) => Value::Ident(format!("{}{}", c, s), q),
Self::Null => Value::Ident(c.to_string(), QuoteKind::None),
Self::List(..) => Value::Ident(
InternedString::get_or_intern(format!("{}{}", c, other.to_css_string(span)?)),
format!("{}{}", c, other.to_css_string(span)?),
QuoteKind::None,
),
_ => {
@ -394,27 +363,18 @@ impl Value {
}
Self::UnaryOp(..) | Self::Paren(..) => self.eval(span)?.node.add(other, span)?,
Self::Ident(text, quotes) => match other {
Self::Ident(text2, ..) => Self::Ident(
InternedString::get_or_intern(text.resolve() + text2.resolve_ref()),
quotes,
),
_ => Value::Ident(
InternedString::get_or_intern(text.resolve() + &other.to_css_string(span)?),
quotes,
),
Self::Ident(text2, ..) => Self::Ident(text + &text2, quotes),
_ => Value::Ident(text + &other.to_css_string(span)?, quotes),
},
Self::List(..) => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!("{}{}", self.to_css_string(span)?, s)),
q,
),
Self::Ident(s, q) => Value::Ident(format!("{}{}", self.to_css_string(span)?, s), q),
Self::Paren(..) => (self.add(other.eval(span)?.node, span))?,
_ => Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
},
@ -452,34 +412,20 @@ impl Value {
}
}
Self::List(..) => Value::Ident(
InternedString::get_or_intern(format!(
"{}{}-{}",
num,
unit,
other.to_css_string(span)?
)),
format!("{}{}-{}", num, unit, other.to_css_string(span)?),
QuoteKind::None,
),
Self::Ident(..) => Value::Ident(
InternedString::get_or_intern(format!(
"{}{}-{}",
num,
unit,
other.to_css_string(span)?
)),
format!("{}{}-{}", num, unit, other.to_css_string(span)?),
QuoteKind::None,
),
_ => todo!(),
},
Self::Color(c) => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!("{}-{}{}{}", c, q, s, q)),
QuoteKind::None,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}-", c)),
QuoteKind::None,
),
Self::Ident(s, q) => {
Value::Ident(format!("{}-{}{}{}", c, q, s, q), QuoteKind::None)
}
Self::Null => Value::Ident(format!("{}-", c), QuoteKind::None),
Self::Dimension(..) | Self::Color(..) => {
return Err((
format!(
@ -492,7 +438,7 @@ impl Value {
.into())
}
_ => Value::Ident(
InternedString::get_or_intern(format!("{}-{}", c, other.to_css_string(span)?)),
format!("{}-{}", c, other.to_css_string(span)?),
QuoteKind::None,
),
},
@ -518,54 +464,41 @@ impl Value {
}
Self::Paren(..) => self.eval(span)?.node.sub(other, span)?,
Self::Ident(..) => Self::Ident(
InternedString::get_or_intern(format!(
format!(
"{}-{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
Self::List(..) => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!(
"{}-{}{}{}",
self.to_css_string(span)?,
q,
s,
q
)),
format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
QuoteKind::None,
),
_ => Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}-{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
},
_ => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!(
"{}-{}{}{}",
self.to_css_string(span)?,
q,
s,
q
)),
QuoteKind::None,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}-", self.to_css_string(span)?)),
format!("{}-{}{}{}", self.to_css_string(span)?, q, s, q),
QuoteKind::None,
),
Self::Null => {
Value::Ident(format!("{}-", self.to_css_string(span)?), QuoteKind::None)
}
_ => Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}-{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
},
@ -671,24 +604,19 @@ impl Value {
)
}
}
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!("{}{}/{}{}{}", num, unit, q, s, q)),
QuoteKind::None,
),
Self::Ident(s, q) => {
Value::Ident(format!("{}{}/{}{}{}", num, unit, q, s, q), QuoteKind::None)
}
Self::BinaryOp(..) | Self::Paren(..) => {
Self::Dimension(num, unit).div(other.eval(span)?.node, span)?
}
_ => todo!(),
},
Self::Color(c) => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!("{}/{}{}{}", c, q, s, q)),
QuoteKind::None,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}/", c)),
QuoteKind::None,
),
Self::Ident(s, q) => {
Value::Ident(format!("{}/{}{}{}", c, q, s, q), QuoteKind::None)
}
Self::Null => Value::Ident(format!("{}/", c), QuoteKind::None),
Self::Dimension(..) | Self::Color(..) => {
return Err((
format!(
@ -701,7 +629,7 @@ impl Value {
.into())
}
_ => Value::Ident(
InternedString::get_or_intern(format!("{}/{}", c, other.to_css_string(span)?)),
format!("{}/{}", c, other.to_css_string(span)?),
QuoteKind::None,
),
},
@ -728,7 +656,7 @@ impl Value {
Self::Paren(..) => self.eval(span)?.node.div(other, span)?,
Self::Ident(s1, q1) => match other {
Self::Ident(s2, q2) => Value::Ident(
InternedString::get_or_intern(format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2)),
format!("{}{}{}/{}{}{}", q1, s1, q1, q2, s2, q2),
QuoteKind::None,
),
Self::Important
@ -736,42 +664,26 @@ impl Value {
| Self::False
| Self::Dimension(..)
| Self::Color(..) => Value::Ident(
InternedString::get_or_intern(format!(
"{}{}{}/{}",
q1,
s1,
q1,
other.to_css_string(span)?
)),
QuoteKind::None,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}{}{}/", q1, s1, q1)),
format!("{}{}{}/{}", q1, s1, q1, other.to_css_string(span)?),
QuoteKind::None,
),
Self::Null => Value::Ident(format!("{}{}{}/", q1, s1, q1), QuoteKind::None),
_ => todo!(),
},
_ => match other {
Self::Ident(s, q) => Value::Ident(
InternedString::get_or_intern(format!(
"{}/{}{}{}",
self.to_css_string(span)?,
q,
s,
q
)),
QuoteKind::None,
),
Self::Null => Value::Ident(
InternedString::get_or_intern(format!("{}/", self.to_css_string(span)?)),
format!("{}/{}{}{}", self.to_css_string(span)?, q, s, q),
QuoteKind::None,
),
Self::Null => {
Value::Ident(format!("{}/", self.to_css_string(span)?), QuoteKind::None)
}
_ => Value::Ident(
InternedString::get_or_intern(format!(
format!(
"{}/{}",
self.to_css_string(span)?,
other.to_css_string(span)?
)),
),
QuoteKind::None,
),
},
@ -824,10 +736,7 @@ impl Value {
pub fn neg(self, span: Span) -> SassResult<Self> {
Ok(match self.eval(span)?.node {
Value::Dimension(n, u) => Value::Dimension(-n, u),
v => Value::Ident(
InternedString::get_or_intern(format!("-{}", v.to_css_string(span)?)),
QuoteKind::None,
),
v => Value::Ident(format!("-{}", v.to_css_string(span)?), QuoteKind::None),
})
}
}

View File

@ -16,7 +16,6 @@ use crate::builtin::GLOBAL_FUNCTIONS;
use crate::color::{Color, NAMED_COLORS};
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
use crate::error::SassResult;
use crate::interner::InternedString;
use crate::scope::Scope;
use crate::selector::Selector;
use crate::unit::Unit;
@ -59,10 +58,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
span = span.merge(i.span);
} else {
return Ok(Spanned {
node: Value::Ident(
InternedString::get_or_intern(format!("#{}", i.node)),
QuoteKind::None,
),
node: Value::Ident(format!("#{}", i.node), QuoteKind::None),
span: i.span,
});
}
@ -71,13 +67,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
3 => {
let v = match u16::from_str_radix(&s, 16) {
Ok(a) => a,
Err(_) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("#{}", s)),
QuoteKind::None,
)
.span(span))
}
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
};
let red = (((v & 0xf00) >> 8) * 0x11) as u8;
let green = (((v & 0x0f0) >> 4) * 0x11) as u8;
@ -90,13 +80,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
4 => {
let v = match u16::from_str_radix(&s, 16) {
Ok(a) => a,
Err(_) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("#{}", s)),
QuoteKind::None,
)
.span(span))
}
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
};
let red = (((v & 0xf000) >> 12) * 0x11) as u8;
let green = (((v & 0x0f00) >> 8) * 0x11) as u8;
@ -114,13 +98,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
6 => {
let v = match u32::from_str_radix(&s, 16) {
Ok(a) => a,
Err(_) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("#{}", s)),
QuoteKind::None,
)
.span(span))
}
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
};
let red = ((v & 0x00ff_0000) >> 16) as u8;
let green = ((v & 0x0000_ff00) >> 8) as u8;
@ -133,13 +111,7 @@ fn parse_hex<I: Iterator<Item = Token>>(
8 => {
let v = match u32::from_str_radix(&s, 16) {
Ok(a) => a,
Err(_) => {
return Ok(Value::Ident(
InternedString::get_or_intern(format!("#{}", s)),
QuoteKind::None,
)
.span(span))
}
Err(_) => return Ok(Value::Ident(format!("#{}", s), QuoteKind::None).span(span)),
};
let red = ((v & 0xff00_0000) >> 24) as u8;
let green = ((v & 0x00ff_0000) >> 16) as u8;
@ -293,10 +265,7 @@ fn eat_op<I: Iterator<Item = Token>>(
devour_whitespace(iter);
space_separated.push(Spanned {
node: Value::Ident(
InternedString::get_or_intern(format!(
"/{}",
right.node.to_css_string(right.span)?
)),
format!("/{}", right.node.to_css_string(right.span)?),
QuoteKind::None,
),
span: op.span.merge(right.span),
@ -340,13 +309,7 @@ fn eat_op<I: Iterator<Item = Token>>(
devour_whitespace(iter);
// special case when the value is literally "and" or "or"
if iter.peek().is_none() {
space_separated.push(
Value::Ident(
InternedString::get_or_intern(op.to_string()),
QuoteKind::None,
)
.span(op.span),
);
space_separated.push(Value::Ident(op.to_string(), QuoteKind::None).span(op.span));
} else if let Some(left) = space_separated.pop() {
devour_whitespace(iter);
let right = single_value(iter, scope, super_selector, left.span)?;
@ -409,23 +372,30 @@ fn single_value<I: Iterator<Item = Token>>(
let val = single_value(iter, scope, super_selector, span)?;
Spanned {
node: Value::Ident(
InternedString::get_or_intern(format!(
"/{}",
val.node.to_css_string(val.span)?
)),
format!("/{}", val.node.to_css_string(val.span)?),
QuoteKind::None,
),
span: next.span.merge(val.span),
}
}
Op::And => Spanned {
node: Value::Ident(InternedString::get_or_intern("and"), QuoteKind::None),
Op::And => {
Spanned {
node: Value::Ident(
"and".into(),
QuoteKind::None,
),
span: next.span,
},
Op::Or => Spanned {
node: Value::Ident(InternedString::get_or_intern("or"), QuoteKind::None),
}
}
Op::Or => {
Spanned {
node: Value::Ident(
"or".into(),
QuoteKind::None,
),
span: next.span,
},
}
}
_ => {
return Err(("Expected expression.", next.span).into());
}
@ -599,20 +569,15 @@ impl Value {
) -> SassResult<Spanned<IntermediateValue>> {
let Spanned { node: mut s, span } = eat_ident(toks, scope, super_selector, span_before)?;
let lower = dbg!(InternedString::get_or_intern(s.to_ascii_lowercase()));
let lower = s.to_ascii_lowercase();
if lower.resolve_ref() == "progid"
&& toks.peek().is_some()
&& toks.peek().unwrap().kind == ':'
{
s = "progid:".to_string();
if lower == "progid" && toks.peek().is_some() && toks.peek().unwrap().kind == ':' {
s = lower;
toks.next();
s.push(':');
s.push_str(&eat_progid(toks, scope, super_selector)?);
return Ok(Spanned {
node: IntermediateValue::Value(Value::Ident(
InternedString::get_or_intern(s),
QuoteKind::None,
)),
node: IntermediateValue::Value(Value::Ident(s, QuoteKind::None)),
span,
});
}
@ -634,9 +599,9 @@ impl Value {
.span(span))
}
None => {
match lower.resolve_ref() {
match lower.as_str() {
"calc" | "element" | "expression" => {
s = lower.resolve().to_string();
s = lower;
eat_calc_args(toks, scope, super_selector, &mut s)?;
}
// "min" => {}
@ -651,11 +616,9 @@ impl Value {
&eat_call_args(toks)?.to_css_string(scope, super_selector)?,
),
}
return Ok(IntermediateValue::Value(Value::Ident(
InternedString::get_or_intern(s),
QuoteKind::None,
))
.span(span));
return Ok(
IntermediateValue::Value(Value::Ident(s, QuoteKind::None)).span(span)
);
}
},
};
@ -667,24 +630,21 @@ impl Value {
.span(span));
}
if let Some(c) = NAMED_COLORS.get_by_name(lower) {
if let Some(c) = NAMED_COLORS.get_by_name(&lower.as_str()) {
return Ok(IntermediateValue::Value(Value::Color(Box::new(Color::new(
c[0], c[1], c[2], c[3], s,
))))
.span(span));
}
Ok(match dbg!(lower.resolve_ref()) {
Ok(match lower.as_str() {
"true" => IntermediateValue::Value(Value::True),
"false" => IntermediateValue::Value(Value::False),
"null" => IntermediateValue::Value(Value::Null),
"not" => IntermediateValue::Op(Op::Not),
"and" => IntermediateValue::Op(Op::And),
"or" => IntermediateValue::Op(Op::Or),
_ => IntermediateValue::Value(Value::Ident(
InternedString::get_or_intern(s),
QuoteKind::None,
)),
_ => IntermediateValue::Value(Value::Ident(s, QuoteKind::None)),
}
.span(span))
}

View File

@ -14,7 +14,6 @@ use std::fmt;
use crate::args::CallArgs;
use crate::atrule::Function;
use crate::builtin::Builtin;
use crate::common::Identifier;
use crate::error::SassResult;
use crate::scope::Scope;
use crate::selector::Selector;
@ -28,15 +27,15 @@ use crate::value::Value;
/// for use in the builtin function `inspect()`
#[derive(Clone)]
pub(crate) enum SassFunction {
Builtin(Builtin, Identifier),
UserDefined(Box<Function>, Identifier),
Builtin(Builtin, String),
UserDefined(Box<Function>, String),
}
impl SassFunction {
/// Get the name of the function referenced
///
/// Used mainly in debugging and `inspect()`
pub fn name(&self) -> &Identifier {
pub fn name(&self) -> &str {
match self {
Self::Builtin(_, name) => name,
Self::UserDefined(_, name) => name,