summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/eval/function.rs29
-rw-r--r--src/eval/mod.rs29
-rw-r--r--src/eval/ops.rs2
-rw-r--r--src/eval/scope.rs12
-rw-r--r--src/eval/value.rs356
-rw-r--r--src/library/layout.rs2
-rw-r--r--src/library/mod.rs54
-rw-r--r--src/library/text.rs18
-rw-r--r--src/pretty.rs6
9 files changed, 227 insertions, 281 deletions
diff --git a/src/eval/function.rs b/src/eval/function.rs
index 28a62873..72722230 100644
--- a/src/eval/function.rs
+++ b/src/eval/function.rs
@@ -81,22 +81,14 @@ impl FuncArgs {
T: Cast<Spanned<Value>>,
{
(0 .. self.items.len()).find_map(|index| {
- let slot = &mut self.items[index];
- if slot.name.is_some() {
- return None;
- }
-
- let value = std::mem::replace(&mut slot.value, Spanned::zero(Value::None));
- match T::cast(value) {
- Ok(t) => {
- self.items.remove(index);
- Some(t)
- }
- Err(value) => {
- slot.value = value;
- None
+ let slot = self.items.get_mut(index)?;
+ if slot.name.is_none() {
+ if T::is(&slot.value) {
+ let value = self.items.remove(index).value;
+ return T::cast(value).ok();
}
}
+ None
})
}
@@ -137,13 +129,8 @@ impl FuncArgs {
match T::cast(value) {
Ok(t) => Some(t),
- Err(value) => {
- ctx.diag(error!(
- span,
- "expected {}, found {}",
- T::TYPE_NAME,
- value.v.type_name(),
- ));
+ Err(msg) => {
+ ctx.diag(error!(span, "{}", msg));
None
}
}
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index fd4417ec..ed8a81c8 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -195,18 +195,25 @@ impl<'a> EvalContext<'a> {
}
match T::cast(value) {
- Ok(t) => Some(t),
- Err(value) => {
- self.diag(error!(
- span,
- "expected {}, found {}",
- T::TYPE_NAME,
- value.type_name(),
- ));
+ Ok(value) => Some(value),
+ Err(msg) => {
+ self.diag(error!(span, "{}", msg));
None
}
}
}
+
+ /// Join with another value.
+ pub fn join(&mut self, lhs: Value, rhs: Value, span: Span) -> Value {
+ let (a, b) = (lhs.type_name(), rhs.type_name());
+ match ops::join(lhs, rhs) {
+ Ok(joined) => joined,
+ Err(prev) => {
+ self.diag(error!(span, "cannot join {} with {}", a, b));
+ prev
+ }
+ }
+ }
}
/// Evaluate an expression.
@@ -328,7 +335,7 @@ impl Eval for BlockExpr {
let mut output = Value::None;
for expr in &self.exprs {
let value = expr.eval(ctx);
- output = output.join(ctx, value, expr.span());
+ output = ctx.join(output, value, expr.span());
}
if self.scoping {
@@ -627,7 +634,7 @@ impl Eval for WhileExpr {
if let Some(condition) = ctx.cast(condition, self.condition.span()) {
if condition {
let value = self.body.eval(ctx);
- output = output.join(ctx, value, self.body.span());
+ output = ctx.join(output, value, self.body.span());
} else {
return output;
}
@@ -652,7 +659,7 @@ impl Eval for ForExpr {
$(ctx.scopes.def_mut($binding.as_str(), $value);)*
let value = self.body.eval(ctx);
- output = output.join(ctx, value, self.body.span());
+ output = ctx.join(output, value, self.body.span());
}
ctx.scopes.exit();
diff --git a/src/eval/ops.rs b/src/eval/ops.rs
index 53205ce8..6408c6c3 100644
--- a/src/eval/ops.rs
+++ b/src/eval/ops.rs
@@ -230,7 +230,7 @@ pub fn equal(lhs: &Value, rhs: &Value) -> bool {
(Dict(a), Dict(b)) => a == b,
(Template(a), Template(b)) => a == b,
(Func(a), Func(b)) => a == b,
- (Any(a), Any(b)) => a == b,
+ (Dyn(a), Dyn(b)) => a == b,
(Error, Error) => true,
// Some technically different things should compare equal.
diff --git a/src/eval/scope.rs b/src/eval/scope.rs
index 4a9d5970..9945104a 100644
--- a/src/eval/scope.rs
+++ b/src/eval/scope.rs
@@ -1,10 +1,10 @@
use std::cell::RefCell;
use std::collections::HashMap;
-use std::fmt::{self, Debug, Display, Formatter};
+use std::fmt::{self, Debug, Formatter};
use std::iter;
use std::rc::Rc;
-use super::{AnyValue, EcoString, EvalContext, FuncArgs, Function, Type, Value};
+use super::{EcoString, EvalContext, FuncArgs, Function, Value};
/// A slot where a variable is stored.
pub type Slot = Rc<RefCell<Value>>;
@@ -95,14 +95,6 @@ impl Scope {
self.def_const(name.clone(), Function::new(Some(name), f));
}
- /// Define a constant variable with a value of variant `Value::Any`.
- pub fn def_any<T>(&mut self, var: impl Into<EcoString>, any: T)
- where
- T: Type + Debug + Display + Clone + PartialEq + 'static,
- {
- self.def_const(var, AnyValue::new(any))
- }
-
/// Define a mutable variable with a value.
pub fn def_mut(&mut self, var: impl Into<EcoString>, value: impl Into<Value>) {
self.values.insert(var.into(), Rc::new(RefCell::new(value.into())));
diff --git a/src/eval/value.rs b/src/eval/value.rs
index 8e3a1c61..4b3cd807 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -1,13 +1,14 @@
use std::any::Any;
use std::cmp::Ordering;
use std::fmt::{self, Debug, Display, Formatter};
+use std::rc::Rc;
-use super::{ops, Array, Dict, EvalContext, Function, Template, TemplateFunc};
+use super::{ops, Array, Dict, Function, Template, TemplateFunc};
use crate::color::{Color, RgbaColor};
use crate::eco::EcoString;
use crate::exec::ExecContext;
use crate::geom::{Angle, Fractional, Length, Linear, Relative};
-use crate::syntax::{Span, Spanned};
+use crate::syntax::Spanned;
/// A computational value.
#[derive(Debug, Clone)]
@@ -44,8 +45,8 @@ pub enum Value {
Template(Template),
/// An executable function.
Func(Function),
- /// Any object.
- Any(AnyValue),
+ /// A dynamic value.
+ Dyn(Dynamic),
/// The result of invalid operations.
Error,
}
@@ -78,29 +79,61 @@ impl Value {
Self::Dict(_) => Dict::TYPE_NAME,
Self::Template(_) => Template::TYPE_NAME,
Self::Func(_) => Function::TYPE_NAME,
- Self::Any(v) => v.type_name(),
+ Self::Dyn(v) => v.type_name(),
Self::Error => "error",
}
}
+ /// Check whether the value is castable into a specific type.
+ pub fn is<T>(&self) -> bool
+ where
+ T: Cast<Value>,
+ {
+ T::is(self)
+ }
+
/// Try to cast the value into a specific type.
- pub fn cast<T>(self) -> Result<T, Self>
+ pub fn cast<T>(self) -> Result<T, String>
where
T: Cast<Value>,
{
T::cast(self)
}
+}
- /// Join with another value.
- pub fn join(self, ctx: &mut EvalContext, other: Self, span: Span) -> Self {
- let (lhs, rhs) = (self.type_name(), other.type_name());
- match ops::join(self, other) {
- Ok(joined) => joined,
- Err(prev) => {
- ctx.diag(error!(span, "cannot join {} with {}", lhs, rhs));
- prev
- }
- }
+impl From<i32> for Value {
+ fn from(v: i32) -> Self {
+ Self::Int(v as i64)
+ }
+}
+
+impl From<usize> for Value {
+ fn from(v: usize) -> Self {
+ Self::Int(v as i64)
+ }
+}
+
+impl From<&str> for Value {
+ fn from(v: &str) -> Self {
+ Self::Str(v.into())
+ }
+}
+
+impl From<String> for Value {
+ fn from(v: String) -> Self {
+ Self::Str(v.into())
+ }
+}
+
+impl From<RgbaColor> for Value {
+ fn from(v: RgbaColor) -> Self {
+ Self::Color(Color::Rgba(v))
+ }
+}
+
+impl From<Dynamic> for Value {
+ fn from(v: Dynamic) -> Self {
+ Self::Dyn(v)
}
}
@@ -122,16 +155,17 @@ impl PartialOrd for Value {
}
}
-/// A wrapper around a dynamic value.
-pub struct AnyValue(Box<dyn Bounds>);
+/// A dynamic value.
+#[derive(Clone)]
+pub struct Dynamic(Rc<dyn Bounds>);
-impl AnyValue {
+impl Dynamic {
/// Create a new instance from any value that satisifies the required bounds.
pub fn new<T>(any: T) -> Self
where
T: Type + Debug + Display + Clone + PartialEq + 'static,
{
- Self(Box::new(any))
+ Self(Rc::new(any))
}
/// Whether the wrapped type is `T`.
@@ -139,15 +173,6 @@ impl AnyValue {
self.0.as_any().is::<T>()
}
- /// Try to downcast to a specific type.
- pub fn downcast<T: 'static>(self) -> Result<T, Self> {
- if self.is::<T>() {
- Ok(*self.0.into_any().downcast().unwrap())
- } else {
- Err(self)
- }
- }
-
/// Try to downcast to a reference to a specific type.
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
self.0.as_any().downcast_ref()
@@ -159,25 +184,19 @@ impl AnyValue {
}
}
-impl Display for AnyValue {
+impl Display for Dynamic {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
-impl Debug for AnyValue {
+impl Debug for Dynamic {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_tuple("ValueAny").field(&self.0).finish()
}
}
-impl Clone for AnyValue {
- fn clone(&self) -> Self {
- Self(self.0.dyn_clone())
- }
-}
-
-impl PartialEq for AnyValue {
+impl PartialEq for Dynamic {
fn eq(&self, other: &Self) -> bool {
self.0.dyn_eq(other)
}
@@ -185,9 +204,7 @@ impl PartialEq for AnyValue {
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: &AnyValue) -> bool;
- fn dyn_clone(&self) -> Box<dyn Bounds>;
+ fn dyn_eq(&self, other: &Dynamic) -> bool;
fn dyn_type_name(&self) -> &'static str;
}
@@ -199,11 +216,7 @@ where
self
}
- fn into_any(self: Box<Self>) -> Box<dyn Any> {
- self
- }
-
- fn dyn_eq(&self, other: &AnyValue) -> bool {
+ fn dyn_eq(&self, other: &Dynamic) -> bool {
if let Some(other) = other.downcast_ref::<Self>() {
self == other
} else {
@@ -211,40 +224,32 @@ where
}
}
- fn dyn_clone(&self) -> Box<dyn Bounds> {
- Box::new(self.clone())
- }
-
fn dyn_type_name(&self) -> &'static str {
T::TYPE_NAME
}
}
-/// Types that can be stored in values.
+/// The type of a value.
pub trait Type {
/// The name of the type.
const TYPE_NAME: &'static str;
}
-impl<T> Type for Spanned<T>
-where
- T: Type,
-{
- const TYPE_NAME: &'static str = T::TYPE_NAME;
-}
-
/// Cast from a value to a specific type.
-pub trait Cast<V>: Type + Sized {
- /// Try to cast the value into an instance of `Self`.
- fn cast(value: V) -> Result<Self, V>;
-}
+pub trait Cast<V>: Sized {
+ /// Check whether the value is castable to `Self`.
+ fn is(value: &V) -> bool;
-impl Type for Value {
- const TYPE_NAME: &'static str = "value";
+ /// Try to cast the value into an instance of `Self`.
+ fn cast(value: V) -> Result<Self, String>;
}
impl Cast<Value> for Value {
- fn cast(value: Value) -> Result<Self, Value> {
+ fn is(_: &Value) -> bool {
+ true
+ }
+
+ fn cast(value: Value) -> Result<Self, String> {
Ok(value)
}
}
@@ -253,12 +258,12 @@ impl<T> Cast<Spanned<Value>> for T
where
T: Cast<Value>,
{
- fn cast(value: Spanned<Value>) -> Result<Self, Spanned<Value>> {
- let span = value.span;
- match T::cast(value.v) {
- Ok(t) => Ok(t),
- Err(v) => Err(Spanned::new(v, span)),
- }
+ fn is(value: &Spanned<Value>) -> bool {
+ T::is(&value.v)
+ }
+
+ fn cast(value: Spanned<Value>) -> Result<Self, String> {
+ T::cast(value.v)
}
}
@@ -266,165 +271,122 @@ impl<T> Cast<Spanned<Value>> for Spanned<T>
where
T: Cast<Value>,
{
- fn cast(value: Spanned<Value>) -> Result<Self, Spanned<Value>> {
+ fn is(value: &Spanned<Value>) -> bool {
+ T::is(&value.v)
+ }
+
+ fn cast(value: Spanned<Value>) -> Result<Self, String> {
let span = value.span;
- match T::cast(value.v) {
- Ok(t) => Ok(Spanned::new(t, span)),
- Err(v) => Err(Spanned::new(v, span)),
- }
+ T::cast(value.v).map(|t| Spanned::new(t, span))
}
}
+/// Implement traits for primitives.
macro_rules! primitive {
- ($type:ty:
- $type_name:literal,
- $variant:path
- $(, $pattern:pat => $out:expr)* $(,)?
+ (
+ $type:ty: $name:literal, $variant:ident
+ $(, $other:ident($binding:ident) => $out:expr)*
) => {
impl Type for $type {
- const TYPE_NAME: &'static str = $type_name;
+ const TYPE_NAME: &'static str = $name;
}
impl From<$type> for Value {
fn from(v: $type) -> Self {
- $variant(v)
+ Value::$variant(v)
}
}
impl Cast<Value> for $type {
- fn cast(value: Value) -> Result<Self, Value> {
+ fn is(value: &Value) -> bool {
+ matches!(value, Value::$variant(_) $(| Value::$other(_))*)
+ }
+
+ fn cast(value: Value) -> Result<Self, String> {
match value {
- $variant(v) => Ok(v),
- $($pattern => Ok($out),)*
- v => Err(v),
+ Value::$variant(v) => Ok(v),
+ $(Value::$other($binding) => Ok($out),)*
+ v => Err(format!(
+ "expected {}, found {}",
+ Self::TYPE_NAME,
+ v.type_name(),
+ )),
}
}
}
};
}
-primitive! { bool: "boolean", Value::Bool }
-primitive! { i64: "integer", Value::Int }
-primitive! {
- f64: "float",
- Value::Float,
- Value::Int(v) => v as f64,
-}
-primitive! { Length: "length", Value::Length }
-primitive! { Angle: "angle", Value::Angle }
-primitive! { Relative: "relative", Value::Relative }
-primitive! {
- Linear: "linear",
- Value::Linear,
- Value::Length(v) => v.into(),
- Value::Relative(v) => v.into(),
-}
-primitive! { Fractional: "fractional", Value::Fractional }
-primitive! { Color: "color", Value::Color }
-primitive! { EcoString: "string", Value::Str }
-primitive! { Array: "array", Value::Array }
-primitive! { Dict: "dictionary", Value::Dict }
-primitive! {
- Template: "template",
- Value::Template,
- Value::Str(v) => v.into(),
-}
-primitive! { Function: "function", Value::Func }
-
-impl From<i32> for Value {
- fn from(v: i32) -> Self {
- Self::Int(v as i64)
- }
-}
-
-impl From<usize> for Value {
- fn from(v: usize) -> Self {
- Self::Int(v as i64)
- }
-}
-
-impl From<String> for Value {
- fn from(v: String) -> Self {
- Self::Str(v.into())
- }
-}
-
-impl From<&str> for Value {
- fn from(v: &str) -> Self {
- Self::Str(v.into())
- }
-}
+/// Implement traits for dynamic types.
+macro_rules! dynamic {
+ ($type:ty: $name:literal, $($tts:tt)*) => {
+ impl $crate::eval::Type for $type {
+ const TYPE_NAME: &'static str = $name;
+ }
-impl From<RgbaColor> for Value {
- fn from(v: RgbaColor) -> Self {
- Self::Color(Color::Rgba(v))
- }
-}
+ impl From<$type> for $crate::eval::Value {
+ fn from(v: $type) -> Self {
+ $crate::eval::Value::Dyn($crate::eval::Dynamic::new(v))
+ }
+ }
-impl From<AnyValue> for Value {
- fn from(v: AnyValue) -> Self {
- Self::Any(v)
- }
+ castable! {
+ $type: Self::TYPE_NAME,
+ $($tts)*
+ @this: Self => this.clone(),
+ }
+ };
}
/// Make a type castable from a value.
-///
-/// Given a type `T`, this implements the following traits:
-/// - [`Type`] for `T`,
-/// - [`Cast<Value>`](Cast) for `T`.
-///
-/// # Example
-/// ```
-/// # use typst::value;
-/// enum FontFamily {
-/// Serif,
-/// Named(String),
-/// }
-///
-/// value! {
-/// FontFamily: "font family",
-/// Value::Str(string) => Self::Named(string),
-/// }
-/// ```
-/// This would allow the type `FontFamily` to be cast from:
-/// - a [`Value::Any`] variant already containing a `FontFamily`,
-/// - a string, producing a named font family.
macro_rules! castable {
- ($type:ty:
- $type_name:literal
- $(, $pattern:pat => $out:expr)*
- $(, #($anyvar:ident: $anytype:ty) => $anyout:expr)*
- $(,)?
+ (
+ $type:ty:
+ $expected:expr,
+ $($pattern:pat => $out:expr,)*
+ $(@$dyn_in:ident: $dyn_type:ty => $dyn_out:expr,)*
) => {
- impl $crate::eval::Type for $type {
- const TYPE_NAME: &'static str = $type_name;
- }
-
impl $crate::eval::Cast<$crate::eval::Value> for $type {
- fn cast(
- value: $crate::eval::Value,
- ) -> Result<Self, $crate::eval::Value> {
- use $crate::eval::*;
-
- #[allow(unreachable_code)]
+ fn is(value: &Value) -> bool {
+ #[allow(unused_variables)]
match value {
- $($pattern => Ok($out),)*
- Value::Any(mut any) => {
- any = match any.downcast::<Self>() {
- Ok(t) => return Ok(t),
- Err(any) => any,
- };
-
- $(any = match any.downcast::<$anytype>() {
- Ok($anyvar) => return Ok($anyout),
- Err(any) => any,
- };)*
-
- Err(Value::Any(any))
- },
- v => Err(v),
+ $($pattern => true,)*
+ $crate::eval::Value::Dyn(dynamic) => {
+ false $(|| dynamic.is::<$dyn_type>())*
+ }
+ _ => false,
}
}
+
+ fn cast(value: $crate::eval::Value) -> Result<Self, String> {
+ let found = match value {
+ $($pattern => return Ok($out),)*
+ $crate::eval::Value::Dyn(dynamic) => {
+ $(if let Some($dyn_in) = dynamic.downcast_ref::<$dyn_type>() {
+ return Ok($dyn_out);
+ })*
+ dynamic.type_name()
+ }
+ v => v.type_name(),
+ };
+
+ Err(format!("expected {}, found {}", $expected, found))
+ }
}
};
}
+
+primitive! { bool: "boolean", Bool }
+primitive! { i64: "integer", Int }
+primitive! { Length: "length", Length }
+primitive! { Angle: "angle", Angle }
+primitive! { Relative: "relative", Relative }
+primitive! { Linear: "linear", Linear, Length(v) => v.into(), Relative(v) => v.into() }
+primitive! { Fractional: "fractional", Fractional }
+primitive! { Color: "color", Color }
+primitive! { EcoString: "string", Str }
+primitive! { Array: "array", Array }
+primitive! { Dict: "dictionary", Dict }
+primitive! { Template: "template", Template, Str(v) => v.into() }
+primitive! { Function: "function", Func }
+primitive! { f64: "float", Float, Int(v) => v as f64 }
diff --git a/src/library/layout.rs b/src/library/layout.rs
index 19352062..cbc5ff94 100644
--- a/src/library/layout.rs
+++ b/src/library/layout.rs
@@ -199,7 +199,7 @@ impl Display for AlignValue {
}
}
-castable! {
+dynamic! {
AlignValue: "alignment",
}
diff --git a/src/library/mod.rs b/src/library/mod.rs
index 28387218..3c1d752d 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -18,7 +18,7 @@ use std::rc::Rc;
use crate::color::{Color, RgbaColor};
use crate::eco::EcoString;
-use crate::eval::{EvalContext, FuncArgs, Scope, Template, Value};
+use crate::eval::{EvalContext, FuncArgs, Scope, Template, Type, Value};
use crate::exec::{Exec, FontFamily};
use crate::font::{FontStyle, FontWeight, VerticalFontMetric};
use crate::geom::*;
@@ -71,34 +71,34 @@ pub fn new() -> Scope {
std.def_const("forest", RgbaColor::new(0x43, 0xA1, 0x27, 0xFF));
// Arbitrary constants.
- std.def_any("start", AlignValue::Start);
- std.def_any("center", AlignValue::Center);
- std.def_any("end", AlignValue::End);
- std.def_any("left", AlignValue::Left);
- std.def_any("right", AlignValue::Right);
- std.def_any("top", AlignValue::Top);
- std.def_any("bottom", AlignValue::Bottom);
- std.def_any("ltr", Dir::LTR);
- std.def_any("rtl", Dir::RTL);
- std.def_any("ttb", Dir::TTB);
- std.def_any("btt", Dir::BTT);
- std.def_any("serif", FontFamily::Serif);
- std.def_any("sans-serif", FontFamily::SansSerif);
- std.def_any("monospace", FontFamily::Monospace);
- std.def_any("normal", FontStyle::Normal);
- std.def_any("italic", FontStyle::Italic);
- std.def_any("oblique", FontStyle::Oblique);
- std.def_any("regular", FontWeight::REGULAR);
- std.def_any("bold", FontWeight::BOLD);
- std.def_any("ascender", VerticalFontMetric::Ascender);
- std.def_any("cap-height", VerticalFontMetric::CapHeight);
- std.def_any("x-height", VerticalFontMetric::XHeight);
- std.def_any("baseline", VerticalFontMetric::Baseline);
- std.def_any("descender", VerticalFontMetric::Descender);
+ std.def_const("start", AlignValue::Start);
+ std.def_const("center", AlignValue::Center);
+ std.def_const("end", AlignValue::End);
+ std.def_const("left", AlignValue::Left);
+ std.def_const("right", AlignValue::Right);
+ std.def_const("top", AlignValue::Top);
+ std.def_const("bottom", AlignValue::Bottom);
+ std.def_const("ltr", Dir::LTR);
+ std.def_const("rtl", Dir::RTL);
+ std.def_const("ttb", Dir::TTB);
+ std.def_const("btt", Dir::BTT);
+ std.def_const("serif", FontFamily::Serif);
+ std.def_const("sans-serif", FontFamily::SansSerif);
+ std.def_const("monospace", FontFamily::Monospace);
+ std.def_const("normal", FontStyle::Normal);
+ std.def_const("italic", FontStyle::Italic);
+ std.def_const("oblique", FontStyle::Oblique);
+ std.def_const("regular", FontWeight::REGULAR);
+ std.def_const("bold", FontWeight::BOLD);
+ std.def_const("ascender", VerticalFontMetric::Ascender);
+ std.def_const("cap-height", VerticalFontMetric::CapHeight);
+ std.def_const("x-height", VerticalFontMetric::XHeight);
+ std.def_const("baseline", VerticalFontMetric::Baseline);
+ std.def_const("descender", VerticalFontMetric::Descender);
std
}
-castable! {
- Dir: "direction"
+dynamic! {
+ Dir: "direction",
}
diff --git a/src/library/text.rs b/src/library/text.rs
index 0f6f3ec1..14a0ee9a 100644
--- a/src/library/text.rs
+++ b/src/library/text.rs
@@ -78,7 +78,6 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
})
}
-#[derive(Debug)]
struct FontDef(Vec<FontFamily>);
castable! {
@@ -89,10 +88,9 @@ castable! {
.filter_map(|v| v.cast().ok())
.collect()
),
- #(family: FontFamily) => Self(vec![family]),
+ @family: FontFamily => Self(vec![family.clone()]),
}
-#[derive(Debug)]
struct FamilyDef(Vec<String>);
castable! {
@@ -106,28 +104,28 @@ castable! {
),
}
-castable! {
+dynamic! {
FontFamily: "font family",
- Value::Str(string) => Self::Named(string.to_lowercase())
+ Value::Str(string) => Self::Named(string.to_lowercase()),
}
-castable! {
+dynamic! {
FontStyle: "font style",
}
-castable! {
+dynamic! {
FontWeight: "font weight",
Value::Int(number) => {
u16::try_from(number).map_or(Self::BLACK, Self::from_number)
- }
+ },
}
-castable! {
+dynamic! {
FontStretch: "font stretch",
Value::Relative(relative) => Self::from_ratio(relative.get() as f32),
}
-castable! {
+dynamic! {
VerticalFontMetric: "vertical font metric",
}
diff --git a/src/pretty.rs b/src/pretty.rs
index 2a825b14..10e4fbcb 100644
--- a/src/pretty.rs
+++ b/src/pretty.rs
@@ -487,7 +487,7 @@ impl Pretty for Value {
Self::Dict(v) => v.pretty(p),
Self::Template(v) => v.pretty(p),
Self::Func(v) => v.pretty(p),
- Self::Any(v) => v.pretty(p),
+ Self::Dyn(v) => v.pretty(p),
Self::Error => p.push_str("<error>"),
}
}
@@ -603,7 +603,7 @@ pretty_display! {
Fractional,
RgbaColor,
Color,
- AnyValue,
+ Dynamic,
}
#[cfg(test)]
@@ -757,7 +757,7 @@ mod tests {
Function::new(Some("nil".into()), |_, _| Value::None),
"<function nil>",
);
- test_value(AnyValue::new(1), "1");
+ test_value(Dynamic::new(1), "1");
test_value(Value::Error, "<error>");
}
}