Skip to content

Commit

Permalink
Merge branch 'master' into div-as-binop
Browse files Browse the repository at this point in the history
  • Loading branch information
kaj committed May 2, 2018
2 parents 9ed5d68 + dd3052e commit aa178f9
Show file tree
Hide file tree
Showing 28 changed files with 763 additions and 364 deletions.
99 changes: 20 additions & 79 deletions src/css/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use num_rational::Rational;
use num_traits::{One, Signed, Zero};
use ordermap::OrderMap;
use std::fmt::{self, Write};
use value::{rgb_to_name, ListSeparator, Operator, Quotes, Unit};
use value::{rgb_to_name, ListSeparator, Number, Operator, Quotes, Unit};

/// A sass value.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Value {
/// A special kind of escape. Only really used for !important.
Bang(String),
/// An function call that was not evaluated.
Call(String, CallArgs),
/// A (callable?) function.
Expand All @@ -20,11 +22,9 @@ pub enum Value {
/// A Numeric value is a rational value with a Unit (which may be
/// Unit::None) and flags.
///
/// The first flag is true for values with an explicit + sign.
///
/// The second flag is true for calculated values and false for
/// The boolean flag is true for calculated values and false for
/// literal values.
Numeric(Rational, Unit, bool, bool),
Numeric(Number, Unit, bool),
Color(
Rational,
Rational,
Expand All @@ -40,16 +40,14 @@ pub enum Value {
BinOp(Box<Value>, bool, Operator, bool, Box<Value>),
UnaryOp(Operator, Box<Value>),
Map(OrderMap<Value, Value>),
/// A unicode range for font selections. U+NN, U+N?, U+NN-MM.
/// The string is the entire value, including the "U+" tag.
UnicodeRange(String),
}

impl Value {
pub fn scalar(v: isize) -> Self {
Value::Numeric(
Rational::from_integer(v),
Unit::None,
false,
false,
)
Value::Numeric(Number::from_integer(v), Unit::None, false)
}
pub fn bool(v: bool) -> Self {
if v {
Expand Down Expand Up @@ -98,17 +96,15 @@ impl Value {

pub fn is_calculated(&self) -> bool {
match *self {
Value::Numeric(_, _, _, calculated) => calculated,
Value::Numeric(.., calculated) => calculated,
Value::Color(_, _, _, _, None) => true,
_ => false,
}
}

pub fn into_calculated(self) -> Self {
match self {
Value::Numeric(v, unit, with_sign, _) => {
Value::Numeric(v, unit, with_sign, true)
}
Value::Numeric(num, unit, _) => Value::Numeric(num, unit, true),
Value::List(v, sep, bracketed) => Value::List(
v.into_iter()
.map(|i| i.into_calculated())
Expand Down Expand Up @@ -252,6 +248,7 @@ impl Value {
impl fmt::Display for Value {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
match *self {
Value::Bang(ref s) => write!(out, "!{}", s),
Value::Literal(ref s, ref q) => match *q {
Quotes::Double => write!(
out,
Expand Down Expand Up @@ -284,14 +281,9 @@ impl fmt::Display for Value {
.collect::<String>();
write!(out, "get-function(\"{}\")", name)
}
Value::Numeric(ref v, ref u, ref with_sign, _) => {
let skipzero = out.alternate();
write!(
out,
"{}{}",
Decimals::new(v, *with_sign, skipzero),
u
)
Value::Numeric(ref num, ref unit, _) => {
num.fmt(out)?;
unit.fmt(out)
}
Value::Color(ref r, ref g, ref b, ref a, ref name) => {
if let Some(ref name) = *name {
Expand Down Expand Up @@ -326,13 +318,13 @@ impl fmt::Display for Value {
} else if out.alternate() {
write!(
out,
// I think the last {} should be {:#} here,
// but the test suite says otherwise.
"rgba({},{},{},{})",
r.round().to_integer() as u8,
g.round().to_integer() as u8,
b.round().to_integer() as u8,
// I think skip_zero should be true here,
// but the test suite says otherwise.
Decimals::new(a, false, false),
Number::new(a.clone()),
)
} else {
write!(
Expand All @@ -341,7 +333,7 @@ impl fmt::Display for Value {
r.round().to_integer() as u8,
g.round().to_integer() as u8,
b.round().to_integer() as u8,
Decimals::new(a, false, false),
Number::new(a.clone()),
)
}
}
Expand Down Expand Up @@ -420,58 +412,7 @@ impl fmt::Display for Value {
.collect::<Vec<_>>()
.join(", ")
),
Value::UnicodeRange(ref s) => write!(out, "{}", s),
}
}
}

struct Decimals<'a> {
r: &'a Rational,
with_sign: bool,
skip_zero: bool,
}

impl<'a> Decimals<'a> {
fn new(r: &'a Rational, with_sign: bool, skip_zero: bool) -> Self {
Decimals {
r,
with_sign,
skip_zero,
}
}
}

impl<'a> fmt::Display for Decimals<'a> {
fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
let t = self.r.to_integer();
if t == 0 {
if self.r.is_negative() {
out.write_str("-0")?;
} else if self.with_sign {
out.write_str("+0")?;
} else if self.r.is_zero() || !self.skip_zero {
out.write_char('0')?;
}
} else {
if self.with_sign && !t.is_negative() {
out.write_char('+')?;
}
write!(out, "{}", t)?;
}
let mut f = self.r.fract().abs();
if !f.is_zero() {
out.write_char('.')?;
for _ in 0..4 {
f *= 10;
write!(out, "{}", f.to_integer())?;
f = f.fract();
if f.is_zero() {
break;
}
}
if !f.is_zero() {
write!(out, "{}", (f * 10).round().to_integer())?;
}
}
Ok(())
}
}
1 change: 1 addition & 0 deletions src/file_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ impl FileContext {
name,
&format!("{}.scss", name),
&format!("_{}.scss", name),
&format!("{}/index.scss", name),
] {
let full = parent
.map(|p| p.join(name))
Expand Down
14 changes: 8 additions & 6 deletions src/functions/colors_hsl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use css::Value;
use num_rational::Rational;
use num_traits::{One, Signed, Zero};
use std::collections::BTreeMap;
use value::Unit;
use value::{Number, Unit};
use variablescope::Scope;

pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
Expand Down Expand Up @@ -131,7 +131,7 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
|args: &Scope| match &args.get("color") {
&Value::Color(ref red, ref green, ref blue, ref _alpha, _) => {
let (h, _s, _l) = rgb_to_hsl(red, green, blue);
Ok(Value::Numeric(h, Unit::Deg, false, true))
Ok(Value::Numeric(Number::new(h), Unit::Deg, true))
}
v => Err(Error::badarg("color", v)),
}
Expand Down Expand Up @@ -198,9 +198,8 @@ pub fn hsla_to_rgba(

fn percentage(v: Rational) -> Value {
Value::Numeric(
v * Rational::from_integer(100),
Number::new(v * Rational::from_integer(100)),
Unit::Percent,
false,
true,
)
}
Expand Down Expand Up @@ -308,7 +307,7 @@ fn cap_u8(n: Rational) -> Rational {

fn to_rational(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, ..) => Ok(v),
Value::Numeric(v, ..) => Ok(v.value),
v => Err(Error::badarg("number", &v)),
}
}
Expand All @@ -317,8 +316,11 @@ fn to_rational(v: Value) -> Result<Rational, Error> {
/// If v is not a percentage, keep it as it is.
fn to_rational_percent(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, Unit::Percent, ..) => Ok(v * Rational::new(1, 100)),
Value::Numeric(v, Unit::Percent, _) => {
Ok(v.value * Rational::new(1, 100))
}
Value::Numeric(v, ..) => {
let v = v.value;
if v <= Rational::new(1, 1) {
Ok(v)
} else {
Expand Down
12 changes: 7 additions & 5 deletions src/functions/colors_other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use css::Value;
use num_rational::Rational;
use num_traits::{One, Signed, Zero};
use std::collections::BTreeMap;
use value::{Quotes, Unit};
use value::{Number, Quotes, Unit};
use variablescope::Scope;

pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
Expand Down Expand Up @@ -74,7 +74,7 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
fn opacity(color: Value) -> Result<Value, Error> {
match color {
Value::Color(_r, _g, _b, a, _) => {
Ok(Value::Numeric(a, Unit::None, false, true))
Ok(Value::Numeric(Number::new(a), Unit::None, true))
}
v => Err(Error::badarg("color", &v)),
}
Expand Down Expand Up @@ -227,7 +227,7 @@ fn cap_u8(n: Rational) -> Rational {

fn to_rational(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, ..) => Ok(v),
Value::Numeric(v, ..) => Ok(v.value),
v => Err(Error::badarg("number", &v)),
}
}
Expand All @@ -236,8 +236,10 @@ fn to_rational(v: Value) -> Result<Rational, Error> {
/// If v is not a percentage, keep it as it is.
fn to_rational_percent(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, Unit::Percent, ..) => Ok(v * Rational::new(1, 100)),
Value::Numeric(v, ..) => Ok(v),
Value::Numeric(v, Unit::Percent, _) => {
Ok(v.value * Rational::new(1, 100))
}
Value::Numeric(v, ..) => Ok(v.value),
v => Err(Error::badarg("number", &v)),
}
}
Expand Down
42 changes: 30 additions & 12 deletions src/functions/colors_rgb.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use super::{Error, SassFunction};
use css::Value;
use css::{CallArgs, Value};
use num_rational::Rational;
use num_traits::One;
use std::collections::BTreeMap;
use value::Unit;
use value::{ListSeparator, Number, Unit};

pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
def!(f, rgb(red, green, blue), |s| Ok(Value::rgba(
Expand All @@ -26,7 +26,17 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
} else {
a
};
Ok(Value::rgba(r, g, b, to_rational(a)?))
match a {
Value::Numeric(a, ..) => Ok(Value::rgba(r, g, b, a.value)),
_ => Ok(Value::Call(
"rgba".into(),
CallArgs::from_value(Value::List(
vec![int_value(r), int_value(g), int_value(b), a],
ListSeparator::Space,
false,
)),
)),
}
} else {
Ok(Value::rgba(
to_int(red)?,
Expand All @@ -37,7 +47,11 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
}
});
fn num(v: &Rational) -> Result<Value, Error> {
Ok(Value::Numeric(*v, Unit::None, false, true))
Ok(Value::Numeric(
Number::new(*v),
Unit::None,
true,
))
}
def!(f, red(color), |s| match &s.get("color") {
&Value::Color(ref red, _, _, _, _) => num(red),
Expand All @@ -62,9 +76,9 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
) = (&color1, &color2, &weight)
{
let w = if wu == &Unit::Percent {
w / Rational::from_integer(100)
w.value / Rational::from_integer(100)
} else {
*w
w.value
};
let one = Rational::one();
let w2 = one - (one - w * a1) * a2;
Expand Down Expand Up @@ -92,9 +106,9 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
) => {
let ff = Rational::new(255, 1);
let w = if wu == &Unit::Percent {
w / Rational::from_integer(100)
w.value / Rational::from_integer(100)
} else {
*w
w.value
};
fn m(v1: &Rational, v2: &Rational, w: Rational) -> Rational {
*v1 * w + *v2 * (Rational::one() - w)
Expand All @@ -115,19 +129,23 @@ pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
});
}

fn int_value(v: Rational) -> Value {
Value::scalar(v.to_integer())
}

fn to_int(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, Unit::Percent, ..) => {
Ok(Rational::new(255, 100) * v)
Value::Numeric(v, Unit::Percent, _) => {
Ok(Rational::new(255, 100) * v.value)
}
Value::Numeric(v, ..) => Ok(v),
Value::Numeric(v, ..) => Ok(v.value),
v => Err(Error::badarg("number", &v)),
}
}

fn to_rational(v: Value) -> Result<Rational, Error> {
match v {
Value::Numeric(v, ..) => Ok(v),
Value::Numeric(num, ..) => Ok(num.value),
v => Err(Error::badarg("number", &v)),
}
}
Expand Down
Loading

0 comments on commit aa178f9

Please sign in to comment.