diff options
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/convert.rs | 152 | ||||
| -rw-r--r-- | src/eval/mod.rs | 47 | ||||
| -rw-r--r-- | src/eval/state.rs | 40 | ||||
| -rw-r--r-- | src/eval/value.rs | 11 |
4 files changed, 110 insertions, 140 deletions
diff --git a/src/eval/convert.rs b/src/eval/convert.rs index 4c177c5b..69ef2506 100644 --- a/src/eval/convert.rs +++ b/src/eval/convert.rs @@ -6,8 +6,7 @@ use fontdock::{FontStretch, FontStyle, FontWeight}; use super::{Value, ValueDict, ValueFunc}; use crate::diag::Diag; -use crate::geom::Linear; -use crate::layout::{Dir, SpecAlign}; +use crate::geom::{Dir, Length, Linear, Relative}; use crate::paper::Paper; use crate::syntax::{Ident, SpanWith, Spanned, SynTree}; @@ -37,26 +36,53 @@ impl<T: Convert> Convert for Spanned<T> { } } -/// A value type that matches [length] values. -/// -/// [length]: enum.Value.html#variant.Length -pub struct Absolute(pub f64); - -impl From<Absolute> for f64 { - fn from(abs: Absolute) -> f64 { - abs.0 - } +macro_rules! convert_match { + ($type:ty, $name:expr, $($p:pat => $r:expr),* $(,)?) => { + impl $crate::eval::Convert for $type { + fn convert( + value: $crate::syntax::Spanned<$crate::eval::Value> + ) -> (Result<Self, $crate::eval::Value>, Option<$crate::diag::Diag>) { + #[allow(unreachable_patterns)] + match value.v { + $($p => (Ok($r), None)),*, + v => { + let err = $crate::error!("expected {}, found {}", $name, v.ty()); + (Err(v), Some(err)) + }, + } + } + } + }; } -/// A value type that matches [relative] values. -/// -/// [relative]: enum.Value.html#variant.Relative -pub struct Relative(pub f64); - -impl From<Relative> for f64 { - fn from(rel: Relative) -> f64 { - rel.0 - } +macro_rules! convert_ident { + ($type:ty, $name:expr, $parse:expr) => { + impl $crate::eval::Convert for $type { + fn convert( + value: $crate::syntax::Spanned<$crate::eval::Value>, + ) -> ( + Result<Self, $crate::eval::Value>, + Option<$crate::diag::Diag>, + ) { + match value.v { + Value::Ident(id) => { + if let Some(thing) = $parse(&id) { + (Ok(thing), None) + } else { + ( + Err($crate::eval::Value::Ident(id)), + Some($crate::error!("invalid {}", $name)), + ) + } + } + v => { + let err = $crate::error!("expected {}, found {}", $name, v.ty()); + (Err(v), Some(err)) + } + } + } + } + }; } /// A value type that matches [identifier] and [string] values. @@ -79,70 +105,31 @@ impl Deref for StringLike { } } -macro_rules! impl_match { - ($type:ty, $name:expr, $($p:pat => $r:expr),* $(,)?) => { - impl Convert for $type { - fn convert(value: Spanned<Value>) -> (Result<Self, Value>, Option<Diag>) { - #[allow(unreachable_patterns)] - match value.v { - $($p => (Ok($r), None)),*, - v => { - let err = error!("expected {}, found {}", $name, v.ty()); - (Err(v), Some(err)) - }, - } - } - } - }; -} - -impl_match!(Value, "value", v => v); -impl_match!(Ident, "identifier", Value::Ident(v) => v); -impl_match!(bool, "bool", Value::Bool(v) => v); -impl_match!(i64, "integer", Value::Int(v) => v); -impl_match!(f64, "float", +convert_match!(Value, "value", v => v); +convert_match!(Ident, "identifier", Value::Ident(v) => v); +convert_match!(bool, "bool", Value::Bool(v) => v); +convert_match!(i64, "integer", Value::Int(v) => v); +convert_match!(f64, "float", Value::Int(v) => v as f64, Value::Float(v) => v, ); -impl_match!(Absolute, "length", Value::Length(v) => Absolute(v)); -impl_match!(Relative, "relative", Value::Relative(v) => Relative(v)); -impl_match!(Linear, "linear", +convert_match!(Length, "length", Value::Length(v) => v); +convert_match!(Relative, "relative", Value::Relative(v) => v); +convert_match!(Linear, "linear", Value::Linear(v) => v, - Value::Length(v) => Linear::abs(v), - Value::Relative(v) => Linear::rel(v), + Value::Length(v) => v.into(), + Value::Relative(v) => v.into(), ); -impl_match!(String, "string", Value::Str(v) => v); -impl_match!(SynTree, "tree", Value::Content(v) => v); -impl_match!(ValueDict, "dictionary", Value::Dict(v) => v); -impl_match!(ValueFunc, "function", Value::Func(v) => v); -impl_match!(StringLike, "identifier or string", +convert_match!(String, "string", Value::Str(v) => v); +convert_match!(SynTree, "tree", Value::Content(v) => v); +convert_match!(ValueDict, "dictionary", Value::Dict(v) => v); +convert_match!(ValueFunc, "function", Value::Func(v) => v); +convert_match!(StringLike, "identifier or string", Value::Ident(Ident(v)) => StringLike(v), Value::Str(v) => StringLike(v), ); -macro_rules! impl_ident { - ($type:ty, $name:expr, $parse:expr) => { - impl Convert for $type { - fn convert(value: Spanned<Value>) -> (Result<Self, Value>, Option<Diag>) { - match value.v { - Value::Ident(id) => { - if let Some(thing) = $parse(&id) { - (Ok(thing), None) - } else { - (Err(Value::Ident(id)), Some(error!("invalid {}", $name))) - } - } - v => { - let err = error!("expected {}, found {}", $name, v.ty()); - (Err(v), Some(err)) - } - } - } - } - }; -} - -impl_ident!(Dir, "direction", |v| match v { +convert_ident!(Dir, "direction", |v| match v { "ltr" => Some(Self::LTR), "rtl" => Some(Self::RTL), "ttb" => Some(Self::TTB), @@ -150,18 +137,9 @@ impl_ident!(Dir, "direction", |v| match v { _ => None, }); -impl_ident!(SpecAlign, "alignment", |v| match v { - "left" => Some(Self::Left), - "right" => Some(Self::Right), - "top" => Some(Self::Top), - "bottom" => Some(Self::Bottom), - "center" => Some(Self::Center), - _ => None, -}); - -impl_ident!(FontStyle, "font style", Self::from_str); -impl_ident!(FontStretch, "font stretch", Self::from_str); -impl_ident!(Paper, "paper", Self::from_name); +convert_ident!(FontStyle, "font style", Self::from_str); +convert_ident!(FontStretch, "font stretch", Self::from_str); +convert_ident!(Paper, "paper", Self::from_name); impl Convert for FontWeight { fn convert(value: Spanned<Value>) -> (Result<Self, Value>, Option<Diag>) { diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 2c6f4d7c..fc8bbbd6 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -1,7 +1,8 @@ //! Evaluation of syntax trees. -mod args; +#[macro_use] mod convert; +mod args; mod dict; mod scope; mod state; @@ -22,10 +23,10 @@ use fontdock::FontStyle; use crate::diag::Diag; use crate::diag::{Deco, Feedback, Pass}; -use crate::layout::nodes::{ +use crate::geom::{Gen, Length, Relative, Spec, Switch}; +use crate::layout::{ Document, LayoutNode, Pad, Pages, Par, Softness, Spacing, Stack, Text, }; -use crate::layout::{Gen2, Spec2, Switch}; use crate::syntax::*; /// Evaluate a syntax tree into a document. @@ -168,7 +169,7 @@ impl EvalContext { dirs, children, aligns, - expand: Spec2::new(true, true), + expand: Spec::new(true, true), }), }), }) @@ -195,7 +196,7 @@ impl EvalContext { line_spacing, children, aligns, - expand: Gen2::new(false, expand_cross).switch(dirs), + expand: Gen::new(false, expand_cross).switch(dirs), }); } } @@ -337,7 +338,7 @@ impl Eval for NodeRaw { dirs: ctx.state.dirs, children, aligns: ctx.state.aligns, - expand: Spec2::new(false, false), + expand: Spec::new(false, false), }); ctx.state.text.fallback = prev; @@ -366,8 +367,8 @@ impl Eval for Lit { Lit::Bool(v) => Value::Bool(v), Lit::Int(v) => Value::Int(v), Lit::Float(v) => Value::Float(v), - Lit::Length(v) => Value::Length(v.as_raw()), - Lit::Percent(v) => Value::Relative(v / 100.0), + Lit::Length(v, unit) => Value::Length(Length::with_unit(v, unit)), + Lit::Percent(v) => Value::Relative(Relative::new(v / 100.0)), Lit::Color(v) => Value::Color(v), Lit::Str(ref v) => Value::Str(v.clone()), Lit::Dict(ref v) => Value::Dict(v.eval(ctx)), @@ -473,7 +474,6 @@ fn neg(ctx: &mut EvalContext, span: Span, value: Value) -> Value { /// Compute the sum of two values. fn add(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { - use crate::geom::Linear as Lin; use Value::*; match (lhs, rhs) { // Numbers to themselves. @@ -484,15 +484,15 @@ fn add(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { // Lengths, relatives and linears to themselves. (Length(a), Length(b)) => Length(a + b), - (Length(a), Relative(b)) => Linear(Lin::abs(a) + Lin::rel(b)), - (Length(a), Linear(b)) => Linear(Lin::abs(a) + b), + (Length(a), Relative(b)) => Linear(a + b), + (Length(a), Linear(b)) => Linear(a + b), - (Relative(a), Length(b)) => Linear(Lin::rel(a) + Lin::abs(b)), + (Relative(a), Length(b)) => Linear(a + b), (Relative(a), Relative(b)) => Relative(a + b), - (Relative(a), Linear(b)) => Linear(Lin::rel(a) + b), + (Relative(a), Linear(b)) => Linear(a + b), - (Linear(a), Length(b)) => Linear(a + Lin::abs(b)), - (Linear(a), Relative(b)) => Linear(a + Lin::rel(b)), + (Linear(a), Length(b)) => Linear(a + b), + (Linear(a), Relative(b)) => Linear(a + b), (Linear(a), Linear(b)) => Linear(a + b), // Complex data types to themselves. @@ -509,7 +509,6 @@ fn add(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { /// Compute the difference of two values. fn sub(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { - use crate::geom::Linear as Lin; use Value::*; match (lhs, rhs) { // Numbers from themselves. @@ -520,13 +519,13 @@ fn sub(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { // Lengths, relatives and linears from themselves. (Length(a), Length(b)) => Length(a - b), - (Length(a), Relative(b)) => Linear(Lin::abs(a) - Lin::rel(b)), - (Length(a), Linear(b)) => Linear(Lin::abs(a) - b), - (Relative(a), Length(b)) => Linear(Lin::rel(a) - Lin::abs(b)), + (Length(a), Relative(b)) => Linear(a - b), + (Length(a), Linear(b)) => Linear(a - b), + (Relative(a), Length(b)) => Linear(a - b), (Relative(a), Relative(b)) => Relative(a - b), - (Relative(a), Linear(b)) => Linear(Lin::rel(a) - b), - (Linear(a), Length(b)) => Linear(a - Lin::abs(b)), - (Linear(a), Relative(b)) => Linear(a - Lin::rel(b)), + (Relative(a), Linear(b)) => Linear(a - b), + (Linear(a), Length(b)) => Linear(a - b), + (Linear(a), Relative(b)) => Linear(a - b), (Linear(a), Linear(b)) => Linear(a - b), (a, b) => { @@ -561,8 +560,8 @@ fn mul(ctx: &mut EvalContext, span: Span, lhs: Value, rhs: Value) -> Value { (Float(a), Linear(b)) => Linear(a * b), // Integers with strings. - (Int(a), Str(b)) => Str(b.repeat(a.max(0) as usize)), - (Str(a), Int(b)) => Str(a.repeat(b.max(0) as usize)), + (Int(a), Str(b)) => Str(b.repeat(0.max(a) as usize)), + (Str(a), Int(b)) => Str(a.repeat(0.max(b) as usize)), (a, b) => { ctx.diag(error!(span, "cannot multiply {} with {}", a.ty(), b.ty())); diff --git a/src/eval/state.rs b/src/eval/state.rs index 7372b851..3ae6b414 100644 --- a/src/eval/state.rs +++ b/src/eval/state.rs @@ -5,9 +5,7 @@ use std::rc::Rc; use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight}; use super::Scope; -use crate::geom::{Linear, Size}; -use crate::layout::{Dir, Gen2, GenAlign, Sides}; -use crate::length::Length; +use crate::geom::{Align, Dir, Gen, Length, Linear, Relative, Sides, Size}; use crate::paper::{Paper, PaperClass, PAPER_A4}; /// The active evaluation state. @@ -20,9 +18,9 @@ pub struct State { /// The page state. pub page: PageState, /// The active layouting directions. - pub dirs: Gen2<Dir>, + pub dirs: Gen<Dir>, /// The active alignments. - pub aligns: Gen2<GenAlign>, + pub aligns: Gen<Align>, } impl Default for State { @@ -31,8 +29,8 @@ impl Default for State { scope: crate::library::_std(), text: TextState::default(), page: PageState::default(), - dirs: Gen2::new(Dir::TTB, Dir::LTR), - aligns: Gen2::new(GenAlign::Start, GenAlign::Start), + dirs: Gen::new(Dir::TTB, Dir::LTR), + aligns: Gen::new(Align::Start, Align::Start), } } } @@ -62,22 +60,22 @@ pub struct TextState { impl TextState { /// The absolute font size. - pub fn font_size(&self) -> f64 { + pub fn font_size(&self) -> Length { self.font_size.eval() } /// The absolute word spacing. - pub fn word_spacing(&self) -> f64 { + pub fn word_spacing(&self) -> Length { self.word_spacing.eval(self.font_size()) } /// The absolute line spacing. - pub fn line_spacing(&self) -> f64 { + pub fn line_spacing(&self) -> Length { self.line_spacing.eval(self.font_size()) } /// The absolute paragraph spacing. - pub fn par_spacing(&self) -> f64 { + pub fn par_spacing(&self) -> Length { self.par_spacing.eval(self.font_size()) } } @@ -105,10 +103,10 @@ impl Default for TextState { }, strong: false, emph: false, - font_size: FontSize::abs(Length::pt(11.0).as_raw()), - word_spacing: Linear::rel(0.25), - line_spacing: Linear::rel(0.2), - par_spacing: Linear::rel(0.5), + font_size: FontSize::abs(Length::pt(11.0)), + word_spacing: Relative::new(0.25).into(), + line_spacing: Relative::new(0.2).into(), + par_spacing: Relative::new(0.5).into(), } } } @@ -117,7 +115,7 @@ impl Default for TextState { #[derive(Debug, Clone, PartialEq)] pub struct FontSize { /// The base font size, updated whenever the font size is set absolutely. - pub base: f64, + pub base: Length, /// The scale to apply on the base font size, updated when the font size /// is set relatively. pub scale: Linear, @@ -125,17 +123,17 @@ pub struct FontSize { impl FontSize { /// Create a new font size. - pub fn new(base: f64, scale: Linear) -> Self { - Self { base, scale } + pub fn new(base: Length, scale: impl Into<Linear>) -> Self { + Self { base, scale: scale.into() } } /// Create a new font size with the given `base` and a scale of `1.0`. - pub fn abs(base: f64) -> Self { - Self::new(base, Linear::rel(1.0)) + pub fn abs(base: Length) -> Self { + Self::new(base, Relative::ONE) } /// Compute the absolute font size. - pub fn eval(&self) -> f64 { + pub fn eval(&self) -> Length { self.scale.eval(self.base) } } diff --git a/src/eval/value.rs b/src/eval/value.rs index c4b11ebe..56dadfc3 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use super::{Args, Dict, Eval, EvalContext, SpannedEntry}; use crate::color::RgbaColor; -use crate::geom::Linear; +use crate::geom::{Length, Linear, Relative}; use crate::syntax::{Ident, SynTree}; /// A computational value. @@ -23,14 +23,9 @@ pub enum Value { /// A floating-point number: `1.2, 200%`. Float(f64), /// A length: `2cm, 5.2in`. - Length(f64), + Length(Length), /// A relative value: `50%`. - /// - /// _Note_: `50%` is represented as `0.5` here, but as `50.0` in the - /// corresponding [literal]. - /// - /// [literal]: ../syntax/ast/enum.Lit.html#variant.Percent - Relative(f64), + Relative(Relative), /// A combination of an absolute length and a relative value: `20% + 5cm`. Linear(Linear), /// A color value with alpha channel: `#f79143ff`. |
