summaryrefslogtreecommitdiff
path: root/src/eval/methods.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-06-06 21:13:59 +0200
committerLaurenz <laurmaedje@gmail.com>2023-06-06 22:06:16 +0200
commitfd417da04f7ca4b995de7f6510abafd3e9c31307 (patch)
tree3675529c75ca7363701ac8ea306de2cc1d3cbcb3 /src/eval/methods.rs
parent168bdf35bd773e67343c965cb473492cc5cae9e7 (diff)
Improve value casting infrastructure
Diffstat (limited to 'src/eval/methods.rs')
-rw-r--r--src/eval/methods.rs153
1 files changed, 67 insertions, 86 deletions
diff --git a/src/eval/methods.rs b/src/eval/methods.rs
index f57bf84d..62ac4095 100644
--- a/src/eval/methods.rs
+++ b/src/eval/methods.rs
@@ -2,7 +2,7 @@
use ecow::EcoString;
-use super::{Args, Str, Value, Vm};
+use super::{Args, IntoValue, Str, Value, Vm};
use crate::diag::{At, SourceResult};
use crate::eval::Datetime;
use crate::model::{Location, Selector};
@@ -21,20 +21,20 @@ pub fn call(
let output = match value {
Value::Color(color) => match method {
- "lighten" => Value::Color(color.lighten(args.expect("amount")?)),
- "darken" => Value::Color(color.darken(args.expect("amount")?)),
- "negate" => Value::Color(color.negate()),
+ "lighten" => color.lighten(args.expect("amount")?).into_value(),
+ "darken" => color.darken(args.expect("amount")?).into_value(),
+ "negate" => color.negate().into_value(),
_ => return missing(),
},
Value::Str(string) => match method {
- "len" => Value::Int(string.len()),
- "first" => Value::Str(string.first().at(span)?),
- "last" => Value::Str(string.last().at(span)?),
+ "len" => string.len().into_value(),
+ "first" => string.first().at(span)?.into_value(),
+ "last" => string.last().at(span)?.into_value(),
"at" => {
let index = args.expect("index")?;
let default = args.named::<EcoString>("default")?;
- Value::Str(string.at(index, default.as_deref()).at(span)?)
+ string.at(index, default.as_deref()).at(span)?.into_value()
}
"slice" => {
let start = args.expect("start")?;
@@ -42,56 +42,50 @@ pub fn call(
if end.is_none() {
end = args.named("count")?.map(|c: i64| start + c);
}
- Value::Str(string.slice(start, end).at(span)?)
+ string.slice(start, end).at(span)?.into_value()
}
- "clusters" => Value::Array(string.clusters()),
- "codepoints" => Value::Array(string.codepoints()),
- "contains" => Value::Bool(string.contains(args.expect("pattern")?)),
- "starts-with" => Value::Bool(string.starts_with(args.expect("pattern")?)),
- "ends-with" => Value::Bool(string.ends_with(args.expect("pattern")?)),
- "find" => {
- string.find(args.expect("pattern")?).map_or(Value::None, Value::Str)
- }
- "position" => string
- .position(args.expect("pattern")?)
- .map_or(Value::None, Value::Int),
- "match" => string
- .match_(args.expect("pattern")?)
- .map_or(Value::None, Value::Dict),
- "matches" => Value::Array(string.matches(args.expect("pattern")?)),
+ "clusters" => string.clusters().into_value(),
+ "codepoints" => string.codepoints().into_value(),
+ "contains" => string.contains(args.expect("pattern")?).into_value(),
+ "starts-with" => string.starts_with(args.expect("pattern")?).into_value(),
+ "ends-with" => string.ends_with(args.expect("pattern")?).into_value(),
+ "find" => string.find(args.expect("pattern")?).into_value(),
+ "position" => string.position(args.expect("pattern")?).into_value(),
+ "match" => string.match_(args.expect("pattern")?).into_value(),
+ "matches" => string.matches(args.expect("pattern")?).into_value(),
"replace" => {
let pattern = args.expect("pattern")?;
let with = args.expect("string or function")?;
let count = args.named("count")?;
- Value::Str(string.replace(vm, pattern, with, count)?)
+ string.replace(vm, pattern, with, count)?.into_value()
}
"trim" => {
let pattern = args.eat()?;
let at = args.named("at")?;
let repeat = args.named("repeat")?.unwrap_or(true);
- Value::Str(string.trim(pattern, at, repeat))
+ string.trim(pattern, at, repeat).into_value()
}
- "split" => Value::Array(string.split(args.eat()?)),
+ "split" => string.split(args.eat()?).into_value(),
_ => return missing(),
},
Value::Content(content) => match method {
- "func" => content.func().into(),
- "has" => Value::Bool(content.has(&args.expect::<EcoString>("field")?)),
+ "func" => content.func().into_value(),
+ "has" => content.has(&args.expect::<EcoString>("field")?).into_value(),
"at" => content
.at(&args.expect::<EcoString>("field")?, args.named("default")?)
.at(span)?,
- "fields" => Value::Dict(content.dict()),
+ "fields" => content.dict().into_value(),
"location" => content
.location()
.ok_or("this method can only be called on content returned by query(..)")
.at(span)?
- .into(),
+ .into_value(),
_ => return missing(),
},
Value::Array(array) => match method {
- "len" => Value::Int(array.len()),
+ "len" => array.len().into_value(),
"first" => array.first().at(span)?.clone(),
"last" => array.last().at(span)?.clone(),
"at" => array
@@ -104,117 +98,104 @@ pub fn call(
if end.is_none() {
end = args.named("count")?.map(|c: i64| start + c);
}
- Value::Array(array.slice(start, end).at(span)?)
+ array.slice(start, end).at(span)?.into_value()
}
- "contains" => Value::Bool(array.contains(&args.expect("value")?)),
- "find" => array.find(vm, args.expect("function")?)?.unwrap_or(Value::None),
- "position" => array
- .position(vm, args.expect("function")?)?
- .map_or(Value::None, Value::Int),
- "filter" => Value::Array(array.filter(vm, args.expect("function")?)?),
- "map" => Value::Array(array.map(vm, args.expect("function")?)?),
+ "contains" => array.contains(&args.expect("value")?).into_value(),
+ "find" => array.find(vm, args.expect("function")?)?.into_value(),
+ "position" => array.position(vm, args.expect("function")?)?.into_value(),
+ "filter" => array.filter(vm, args.expect("function")?)?.into_value(),
+ "map" => array.map(vm, args.expect("function")?)?.into_value(),
"fold" => {
array.fold(vm, args.expect("initial value")?, args.expect("function")?)?
}
"sum" => array.sum(args.named("default")?, span)?,
"product" => array.product(args.named("default")?, span)?,
- "any" => Value::Bool(array.any(vm, args.expect("function")?)?),
- "all" => Value::Bool(array.all(vm, args.expect("function")?)?),
- "flatten" => Value::Array(array.flatten()),
- "rev" => Value::Array(array.rev()),
- "split" => Value::Array(array.split(args.expect("separator")?)),
+ "any" => array.any(vm, args.expect("function")?)?.into_value(),
+ "all" => array.all(vm, args.expect("function")?)?.into_value(),
+ "flatten" => array.flatten().into_value(),
+ "rev" => array.rev().into_value(),
+ "split" => array.split(args.expect("separator")?).into_value(),
"join" => {
let sep = args.eat()?;
let last = args.named("last")?;
array.join(sep, last).at(span)?
}
- "sorted" => Value::Array(array.sorted(vm, span, args.named("key")?)?),
- "zip" => Value::Array(array.zip(args.expect("other")?)),
- "enumerate" => Value::Array(array.enumerate()),
+ "sorted" => array.sorted(vm, span, args.named("key")?)?.into_value(),
+ "zip" => array.zip(args.expect("other")?).into_value(),
+ "enumerate" => array.enumerate().into_value(),
_ => return missing(),
},
Value::Dict(dict) => match method {
- "len" => Value::Int(dict.len()),
+ "len" => dict.len().into_value(),
"at" => dict
.at(&args.expect::<Str>("key")?, args.named("default")?.as_ref())
.at(span)?
.clone(),
- "keys" => Value::Array(dict.keys()),
- "values" => Value::Array(dict.values()),
- "pairs" => Value::Array(dict.pairs()),
+ "keys" => dict.keys().into_value(),
+ "values" => dict.values().into_value(),
+ "pairs" => dict.pairs().into_value(),
_ => return missing(),
},
Value::Func(func) => match method {
- "with" => Value::Func(func.with(args.take())),
+ "with" => func.with(args.take()).into_value(),
"where" => {
let fields = args.to_named();
args.items.retain(|arg| arg.name.is_none());
- Value::dynamic(
- func.element()
- .ok_or("`where()` can only be called on element functions")
- .at(span)?
- .where_(fields),
- )
+ func.element()
+ .ok_or("`where()` can only be called on element functions")
+ .at(span)?
+ .where_(fields)
+ .into_value()
}
_ => return missing(),
},
Value::Args(args) => match method {
- "pos" => Value::Array(args.to_pos()),
- "named" => Value::Dict(args.to_named()),
+ "pos" => args.to_pos().into_value(),
+ "named" => args.to_named().into_value(),
_ => return missing(),
},
Value::Dyn(dynamic) => {
if let Some(location) = dynamic.downcast::<Location>() {
match method {
- "page" => vm.vt.introspector.page(*location).into(),
- "position" => vm.vt.introspector.position(*location).into(),
+ "page" => vm.vt.introspector.page(*location).into_value(),
+ "position" => vm.vt.introspector.position(*location).into_value(),
"page-numbering" => vm.vt.introspector.page_numbering(*location),
_ => return missing(),
}
} else if let Some(selector) = dynamic.downcast::<Selector>() {
match method {
- "or" => selector.clone().or(args.all::<Selector>()?).into(),
- "and" => selector.clone().and(args.all::<Selector>()?).into(),
+ "or" => selector.clone().or(args.all::<Selector>()?).into_value(),
+ "and" => selector.clone().and(args.all::<Selector>()?).into_value(),
"before" => {
let location = args.expect::<Selector>("selector")?;
let inclusive =
args.named_or_find::<bool>("inclusive")?.unwrap_or(true);
- selector.clone().before(location, inclusive).into()
+ selector.clone().before(location, inclusive).into_value()
}
"after" => {
let location = args.expect::<Selector>("selector")?;
let inclusive =
args.named_or_find::<bool>("inclusive")?.unwrap_or(true);
- selector.clone().after(location, inclusive).into()
+ selector.clone().after(location, inclusive).into_value()
}
_ => return missing(),
}
} else if let Some(&datetime) = dynamic.downcast::<Datetime>() {
match method {
- "display" => datetime.display(args.eat()?).at(args.span)?.into(),
- "year" => {
- datetime.year().map_or(Value::None, |y| Value::Int(y.into()))
- }
- "month" => {
- datetime.month().map_or(Value::None, |m| Value::Int(m.into()))
- }
- "weekday" => {
- datetime.weekday().map_or(Value::None, |w| Value::Int(w.into()))
- }
- "day" => datetime.day().map_or(Value::None, |d| Value::Int(d.into())),
- "hour" => {
- datetime.hour().map_or(Value::None, |h| Value::Int(h.into()))
- }
- "minute" => {
- datetime.minute().map_or(Value::None, |m| Value::Int(m.into()))
- }
- "second" => {
- datetime.second().map_or(Value::None, |s| Value::Int(s.into()))
+ "display" => {
+ datetime.display(args.eat()?).at(args.span)?.into_value()
}
+ "year" => datetime.year().into_value(),
+ "month" => datetime.month().into_value(),
+ "weekday" => datetime.weekday().into_value(),
+ "day" => datetime.day().into_value(),
+ "hour" => datetime.hour().into_value(),
+ "minute" => datetime.minute().into_value(),
+ "second" => datetime.second().into_value(),
_ => return missing(),
}
} else {