summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/context.rs10
-rw-r--r--src/eval/state.rs36
-rw-r--r--src/eval/value.rs130
3 files changed, 91 insertions, 85 deletions
diff --git a/src/eval/context.rs b/src/eval/context.rs
index ece33146..64a8fbbe 100644
--- a/src/eval/context.rs
+++ b/src/eval/context.rs
@@ -119,15 +119,17 @@ impl EvalContext {
if !children.is_empty() || keep_empty(group.softness) {
self.runs.push(NodePages {
size: group.size,
- child: Node::any(NodePad {
+ child: NodePad {
padding: group.padding,
- child: Node::any(NodeStack {
+ child: NodeStack {
dirs: group.dirs,
align: group.align,
expansion: Gen::uniform(Expansion::Fill),
children,
- }),
- }),
+ }
+ .into(),
+ }
+ .into(),
})
}
group.softness
diff --git a/src/eval/state.rs b/src/eval/state.rs
index 7860c004..2a8ee2f0 100644
--- a/src/eval/state.rs
+++ b/src/eval/state.rs
@@ -128,7 +128,22 @@ impl StateFont {
impl Default for StateFont {
fn default() -> Self {
Self {
- families: Rc::new(default_font_families()),
+ /// The default tree of font fallbacks.
+ families: Rc::new(fallback! {
+ list: ["sans-serif"],
+ classes: {
+ "serif" => ["source serif pro", "noto serif"],
+ "sans-serif" => ["source sans pro", "noto sans"],
+ "monospace" => ["source code pro", "noto sans mono"],
+ },
+ base: [
+ "source sans pro",
+ "noto sans",
+ "segoe ui emoji",
+ "noto emoji",
+ "latin modern math",
+ ],
+ }),
variant: FontVariant {
style: FontStyle::Normal,
weight: FontWeight::REGULAR,
@@ -141,22 +156,3 @@ impl Default for StateFont {
}
}
}
-
-/// The default tree of font fallbacks.
-fn default_font_families() -> FallbackTree {
- fallback! {
- list: ["sans-serif"],
- classes: {
- "serif" => ["source serif pro", "noto serif"],
- "sans-serif" => ["source sans pro", "noto sans"],
- "monospace" => ["source code pro", "noto sans mono"],
- },
- base: [
- "source sans pro",
- "noto sans",
- "segoe ui emoji",
- "noto emoji",
- "latin modern math",
- ],
- }
-}
diff --git a/src/eval/value.rs b/src/eval/value.rs
index a91ff137..80c6b820 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -1,6 +1,6 @@
use std::any::Any;
use std::collections::HashMap;
-use std::fmt::{self, Debug, Formatter};
+use std::fmt::{self, Debug, Display, Formatter};
use std::ops::Deref;
use std::rc::Rc;
@@ -45,14 +45,6 @@ pub enum Value {
}
impl Value {
- /// Create a new dynamic value.
- pub fn any<T>(any: T) -> Self
- where
- T: Type + Debug + Clone + PartialEq + 'static,
- {
- Self::Any(ValueAny::new(any))
- }
-
/// Try to cast the value into a specific type.
pub fn cast<T>(self) -> CastResult<T, Self>
where
@@ -68,8 +60,8 @@ impl Value {
Self::Bool(_) => bool::TYPE_NAME,
Self::Int(_) => i64::TYPE_NAME,
Self::Float(_) => f64::TYPE_NAME,
- Self::Relative(_) => Relative::TYPE_NAME,
Self::Length(_) => Length::TYPE_NAME,
+ Self::Relative(_) => Relative::TYPE_NAME,
Self::Linear(_) => Linear::TYPE_NAME,
Self::Color(_) => Color::TYPE_NAME,
Self::Str(_) => String::TYPE_NAME,
@@ -88,16 +80,24 @@ impl Eval for &Value {
/// Evaluate everything contained in this value.
fn eval(self, ctx: &mut EvalContext) -> Self::Output {
- match self {
- // Don't print out none values.
- Value::None => {}
-
- // Pass through.
- Value::Content(tree) => tree.eval(ctx),
-
- // Format with debug.
- val => ctx.push(ctx.make_text_node(format!("{:?}", val))),
- }
+ ctx.push(ctx.make_text_node(match self {
+ Value::None => return,
+ Value::Bool(v) => v.to_string(),
+ Value::Int(v) => v.to_string(),
+ Value::Float(v) => v.to_string(),
+ Value::Length(v) => v.to_string(),
+ Value::Relative(v) => v.to_string(),
+ Value::Linear(v) => v.to_string(),
+ Value::Color(v) => v.to_string(),
+ Value::Str(v) => v.clone(),
+ // TODO: Find good representation for composite types.
+ Value::Array(_v) => "(array)".into(),
+ Value::Dict(_v) => "(dictionary)".into(),
+ Value::Content(tree) => return tree.eval(ctx),
+ Value::Func(v) => v.to_string(),
+ Value::Any(v) => v.to_string(),
+ Value::Error => "(error)".into(),
+ }));
}
}
@@ -110,21 +110,21 @@ impl Default for Value {
impl Debug for Value {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
- Self::None => f.pad("none"),
- Self::Bool(v) => v.fmt(f),
- Self::Int(v) => v.fmt(f),
- Self::Float(v) => v.fmt(f),
- Self::Length(v) => v.fmt(f),
- Self::Relative(v) => v.fmt(f),
- Self::Linear(v) => v.fmt(f),
- Self::Color(v) => v.fmt(f),
- Self::Str(v) => v.fmt(f),
- Self::Array(v) => v.fmt(f),
- Self::Dict(v) => v.fmt(f),
- Self::Content(v) => v.fmt(f),
- Self::Func(v) => v.fmt(f),
- Self::Any(v) => v.fmt(f),
- Self::Error => f.pad("<error>"),
+ Self::None => f.pad("None"),
+ Self::Bool(v) => Debug::fmt(v, f),
+ Self::Int(v) => Debug::fmt(v, f),
+ Self::Float(v) => Debug::fmt(v, f),
+ Self::Length(v) => Debug::fmt(v, f),
+ Self::Relative(v) => Debug::fmt(v, f),
+ Self::Linear(v) => Debug::fmt(v, f),
+ Self::Color(v) => Debug::fmt(v, f),
+ Self::Str(v) => Debug::fmt(v, f),
+ Self::Array(v) => Debug::fmt(v, f),
+ Self::Dict(v) => Debug::fmt(v, f),
+ Self::Content(v) => Debug::fmt(v, f),
+ Self::Func(v) => Debug::fmt(v, f),
+ Self::Any(v) => Debug::fmt(v, f),
+ Self::Error => f.pad("Error"),
}
}
}
@@ -140,15 +140,18 @@ pub type ValueContent = Tree;
/// A wrapper around a reference-counted executable function.
#[derive(Clone)]
-pub struct ValueFunc(Rc<dyn Fn(&mut EvalContext, &mut Args) -> Value>);
+pub struct ValueFunc {
+ name: String,
+ f: Rc<dyn Fn(&mut EvalContext, &mut Args) -> Value>,
+}
impl ValueFunc {
/// Create a new function value from a rust function or closure.
- pub fn new<F>(func: F) -> Self
+ pub fn new<F>(name: impl Into<String>, f: F) -> Self
where
F: Fn(&mut EvalContext, &mut Args) -> Value + 'static,
{
- Self(Rc::new(func))
+ Self { name: name.into(), f: Rc::new(f) }
}
}
@@ -162,13 +165,18 @@ impl Deref for ValueFunc {
type Target = dyn Fn(&mut EvalContext, &mut Args) -> Value;
fn deref(&self) -> &Self::Target {
- self.0.as_ref()
+ self.f.as_ref()
}
}
+impl Display for ValueFunc {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "<function {}>", self.name)
+ }
+}
impl Debug for ValueFunc {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.pad("<function>")
+ Display::fmt(self, f)
}
}
@@ -179,7 +187,7 @@ impl ValueAny {
/// Create a new instance from any value that satisifies the required bounds.
pub fn new<T>(any: T) -> Self
where
- T: Type + Debug + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + Clone + PartialEq + 'static,
{
Self(Box::new(any))
}
@@ -221,13 +229,19 @@ impl PartialEq for ValueAny {
}
}
+impl Display for ValueAny {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Display::fmt(&self.0, f)
+ }
+}
+
impl Debug for ValueAny {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.0.fmt(f)
+ Debug::fmt(&self.0, f)
}
}
-trait Bounds: Debug + 'static {
+trait Bounds: Debug + Display + 'static {
fn as_any(&self) -> &dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
fn dyn_eq(&self, other: &ValueAny) -> bool;
@@ -237,7 +251,7 @@ trait Bounds: Debug + 'static {
impl<T> Bounds for T
where
- T: Type + Debug + Clone + PartialEq + 'static,
+ T: Type + Debug + Display + Clone + PartialEq + 'static,
{
fn as_any(&self) -> &dyn Any {
self
@@ -304,6 +318,16 @@ impl<T, V> CastResult<T, V> {
}
}
+impl Type for Value {
+ const TYPE_NAME: &'static str = "value";
+}
+
+impl Cast<Value> for Value {
+ fn cast(value: Value) -> CastResult<Self, Value> {
+ CastResult::Ok(value)
+ }
+}
+
impl<T> Cast<Spanned<Value>> for T
where
T: Cast<Value>,
@@ -390,15 +414,6 @@ impl From<&str> for Value {
}
}
-impl<F> From<F> for Value
-where
- F: Fn(&mut EvalContext, &mut Args) -> Value + 'static,
-{
- fn from(func: F) -> Self {
- Self::Func(ValueFunc::new(func))
- }
-}
-
impl From<ValueAny> for Value {
fn from(v: ValueAny) -> Self {
Self::Any(v)
@@ -407,9 +422,8 @@ impl From<ValueAny> for Value {
/// Make a type usable as a [`Value`].
///
-/// Given a type `T`, this implements the following traits:
+/// Given a type `T`, this always implements the following traits:
/// - [`Type`] for `T`,
-/// - [`From<T>`](From) for [`Value`],
/// - [`Cast<Value>`](Cast) for `T`.
#[macro_export]
macro_rules! impl_type {
@@ -423,12 +437,6 @@ macro_rules! impl_type {
const TYPE_NAME: &'static str = $type_name;
}
- impl From<$type> for $crate::eval::Value {
- fn from(any: $type) -> Self {
- $crate::eval::Value::any(any)
- }
- }
-
impl $crate::eval::Cast<$crate::eval::Value> for $type {
fn cast(
value: $crate::eval::Value,