summaryrefslogtreecommitdiff
path: root/src/compute
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-17 23:45:03 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-17 23:45:03 +0200
commit6d7e7d945b315469b80bca3466a96534b2a17639 (patch)
tree1b6c5e0ae7fb683ff7f3b6b1d961151a8e467a80 /src/compute
parent3cbca56a7195bb2a7996530d584300d697c11dc8 (diff)
Tidy up library functions 🧺
Diffstat (limited to 'src/compute')
-rw-r--r--src/compute/scope.rs6
-rw-r--r--src/compute/table.rs26
-rw-r--r--src/compute/value.rs35
3 files changed, 43 insertions, 24 deletions
diff --git a/src/compute/scope.rs b/src/compute/scope.rs
index 1fd4db0b..1c297fde 100644
--- a/src/compute/scope.rs
+++ b/src/compute/scope.rs
@@ -31,12 +31,6 @@ impl Scope {
self.functions.get(name)
}
- /// Return the function with the given name or the fallback if there is no
- /// such function.
- pub fn func_or_fallback(&self, name: &str) -> &FuncValue {
- self.func(name).unwrap_or_else(|| self.fallback())
- }
-
/// Return the fallback function.
pub fn fallback(&self) -> &FuncValue {
&self.fallback
diff --git a/src/compute/table.rs b/src/compute/table.rs
index 75effd60..e8c4b307 100644
--- a/src/compute/table.rs
+++ b/src/compute/table.rs
@@ -1,7 +1,7 @@
//! A key-value map that can also model array-like structures.
use std::collections::BTreeMap;
-use std::fmt::{self, Debug, Formatter};
+use std::fmt::{self, Debug, Display, Formatter};
use std::ops::Index;
use crate::syntax::span::{Span, Spanned};
@@ -180,25 +180,31 @@ impl<V: Debug> Debug for Table<V> {
let mut builder = f.debug_tuple("");
- struct Entry<'a>(&'a dyn Debug, &'a dyn Debug);
+ struct Entry<'a>(bool, &'a dyn Display, &'a dyn Debug);
impl<'a> Debug for Entry<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- self.0.fmt(f)?;
+ if self.0 {
+ f.write_str("\"")?;
+ }
+ self.1.fmt(f)?;
+ if self.0 {
+ f.write_str("\"")?;
+ }
if f.alternate() {
f.write_str(" = ")?;
} else {
f.write_str("=")?;
}
- self.1.fmt(f)
+ self.2.fmt(f)
}
}
for (key, value) in self.nums() {
- builder.field(&Entry(&key, &value));
+ builder.field(&Entry(false, &key, &value));
}
for (key, value) in self.strs() {
- builder.field(&Entry(&key, &value));
+ builder.field(&Entry(key.contains(' '), &key, &value));
}
builder.finish()
@@ -358,21 +364,21 @@ mod tests {
#[test]
fn test_table_format_debug() {
let mut table = Table::new();
- assert_eq!(format!("{:?}", table), r#"()"#);
- assert_eq!(format!("{:#?}", table), r#"()"#);
+ assert_eq!(format!("{:?}", table), "()");
+ assert_eq!(format!("{:#?}", table), "()");
table.insert(10, "hello");
table.insert("twenty", "there");
table.insert("sp ace", "quotes");
assert_eq!(
format!("{:?}", table),
- r#"(10="hello", "sp ace"="quotes", "twenty"="there")"#,
+ r#"(10="hello", "sp ace"="quotes", twenty="there")"#,
);
assert_eq!(format!("{:#?}", table).lines().collect::<Vec<_>>(), [
"(",
r#" 10 = "hello","#,
r#" "sp ace" = "quotes","#,
- r#" "twenty" = "there","#,
+ r#" twenty = "there","#,
")",
]);
}
diff --git a/src/compute/value.rs b/src/compute/value.rs
index daa3b17b..32f2778b 100644
--- a/src/compute/value.rs
+++ b/src/compute/value.rs
@@ -1,6 +1,7 @@
//! Computational values: Syntactical expressions can be evaluated into these.
use std::fmt::{self, Debug, Formatter};
+use std::ops::Deref;
use std::rc::Rc;
use fontdock::{FontStyle, FontWeight, FontWidth};
@@ -13,7 +14,7 @@ use crate::syntax::span::{Span, Spanned};
use crate::syntax::tree::SyntaxTree;
use crate::syntax::Ident;
use crate::{DynFuture, Feedback, Pass};
-use super::table::{BorrowedKey, SpannedEntry, Table};
+use super::table::{SpannedEntry, Table};
/// A computational value.
#[derive(Clone)]
@@ -110,7 +111,7 @@ impl PartialEq for Value {
///
/// The dynamic function object is wrapped in an `Rc` to keep `Value` clonable.
pub type FuncValue = Rc<
- dyn Fn(TableValue, LayoutContext<'_>) -> DynFuture<Pass<Value>>
+ dyn Fn(Span, TableValue, LayoutContext<'_>) -> DynFuture<Pass<Value>>
>;
/// A table of values.
@@ -138,13 +139,21 @@ impl TableValue {
/// Retrieve and remove the matching value with the lowest number key,
/// removing and generating errors for all non-matching entries with lower
/// keys.
- pub fn expect<T: TryFromValue>(&mut self, f: &mut Feedback) -> Option<T> {
+ ///
+ /// Generates an error at `err_span` when no matching value was found.
+ pub fn expect<T: TryFromValue>(
+ &mut self,
+ name: &str,
+ span: Span,
+ f: &mut Feedback,
+ ) -> Option<T> {
while let Some((num, _)) = self.first() {
let entry = self.remove(num).unwrap();
if let Some(val) = T::try_from_value(entry.val.as_ref(), f) {
return Some(val);
}
}
+ error!(@f, span, "missing argument: {}", name);
None
}
@@ -152,9 +161,8 @@ impl TableValue {
/// there is any.
///
/// Generates an error if the key exists but the value does not match.
- pub fn take_with_key<'a, K, T>(&mut self, key: K, f: &mut Feedback) -> Option<T>
+ pub fn take_key<'a, T>(&mut self, key: &str, f: &mut Feedback) -> Option<T>
where
- K: Into<BorrowedKey<'a>>,
T: TryFromValue,
{
self.remove(key).and_then(|entry| {
@@ -312,6 +320,14 @@ impl_match!(ScaleLength, "number or length",
/// `Into<String>`.
pub struct StringLike(pub String);
+impl Deref for StringLike {
+ type Target = str;
+
+ fn deref(&self) -> &str {
+ self.0.as_str()
+ }
+}
+
impl From<StringLike> for String {
fn from(like: StringLike) -> String {
like.0
@@ -441,7 +457,10 @@ mod tests {
table.insert(1, entry(Value::Bool(false)));
table.insert(3, entry(Value::Str("hi".to_string())));
table.insert(5, entry(Value::Bool(true)));
- assert_eq!(table.expect::<String>(&mut f), Some("hi".to_string()));
+ assert_eq!(
+ table.expect::<String>("", Span::ZERO, &mut f),
+ Some("hi".to_string())
+ );
assert_eq!(f.diagnostics, [error!(Span::ZERO, "expected string, found bool")]);
assert_eq!(table.len(), 1);
}
@@ -452,8 +471,8 @@ mod tests {
let mut table = Table::new();
table.insert(1, entry(Value::Bool(false)));
table.insert("hi", entry(Value::Bool(true)));
- assert_eq!(table.take_with_key::<_, bool>(1, &mut f), Some(false));
- assert_eq!(table.take_with_key::<_, f64>("hi", &mut f), None);
+ assert_eq!(table.take::<bool>(), Some(false));
+ assert_eq!(table.take_key::<f64>("hi", &mut f), None);
assert_eq!(f.diagnostics, [error!(Span::ZERO, "expected number, found bool")]);
assert!(table.is_empty());
}