summaryrefslogtreecommitdiff
path: root/src/library/utility.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-07-30 18:04:08 +0200
committerLaurenz <laurmaedje@gmail.com>2021-07-30 18:49:19 +0200
commit1ee1d078e2480ddd08d40915bc7a74a8352acff0 (patch)
tree1e7ff367278a19fead3e404cf06d65bfb80a6cd9 /src/library/utility.rs
parent42a27b48df427edf8dbb624c51551a90ecf2e7ea (diff)
Fatal errors
- Makes errors fatal, so that a phase is only reached when all previous phases were error-free - Parsing still recovers and can produce multiple errors - Evaluation fails fast and can thus produce only a single error (except for parse errors due to an import) - The single error that could occur during execution is removed for now - Removes Value::Error variant
Diffstat (limited to 'src/library/utility.rs')
-rw-r--r--src/library/utility.rs96
1 files changed, 40 insertions, 56 deletions
diff --git a/src/library/utility.rs b/src/library/utility.rs
index 4001d14f..fb39fce3 100644
--- a/src/library/utility.rs
+++ b/src/library/utility.rs
@@ -7,94 +7,78 @@ use crate::pretty::pretty;
use super::*;
/// `type`: The name of a value's type.
-pub fn type_(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- match args.expect::<Value>(ctx, "value") {
- Some(value) => value.type_name().into(),
- None => Value::Error,
- }
+pub fn type_(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ let value = args.expect::<Value>("value")?;
+ Ok(value.type_name().into())
}
/// `repr`: The string representation of a value.
-pub fn repr(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- match args.expect::<Value>(ctx, "value") {
- Some(value) => pretty(&value).into(),
- None => Value::Error,
- }
+pub fn repr(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ let value = args.expect::<Value>("value")?;
+ Ok(pretty(&value).into())
}
/// `len`: The length of a string, an array or a dictionary.
-pub fn len(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- match args.expect(ctx, "collection") {
- Some(Spanned { v: Value::Str(v), .. }) => Value::Int(v.len() as i64),
- Some(Spanned { v: Value::Array(v), .. }) => Value::Int(v.len() as i64),
- Some(Spanned { v: Value::Dict(v), .. }) => Value::Int(v.len() as i64),
- Some(other) if other.v != Value::Error => {
- ctx.diag(error!(other.span, "expected string, array or dictionary"));
- Value::Error
- }
- _ => Value::Error,
- }
+pub fn len(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ let Spanned { v, span } = args.expect("collection")?;
+ Ok(match v {
+ Value::Str(v) => Value::Int(v.len() as i64),
+ Value::Array(v) => Value::Int(v.len() as i64),
+ Value::Dict(v) => Value::Int(v.len() as i64),
+ _ => bail!(args.file, span, "expected string, array or dictionary"),
+ })
}
/// `rgb`: Create an RGB(A) color.
-pub fn rgb(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- Value::Color(Color::Rgba(
+pub fn rgb(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ Ok(Value::Color(Color::Rgba(
if let Some(string) = args.eat::<Spanned<EcoString>>() {
match RgbaColor::from_str(&string.v) {
Ok(color) => color,
- Err(_) => {
- ctx.diag(error!(string.span, "invalid color"));
- return Value::Error;
- }
+ Err(_) => bail!(args.file, string.span, "invalid color"),
}
} else {
- let r = args.expect(ctx, "red component").unwrap_or(0.0);
- let g = args.expect(ctx, "green component").unwrap_or(0.0);
- let b = args.expect(ctx, "blue component").unwrap_or(0.0);
+ let r = args.expect("red component")?;
+ let g = args.expect("green component")?;
+ let b = args.expect("blue component")?;
let a = args.eat().unwrap_or(1.0);
let f = |v: f64| (v.clamp(0.0, 1.0) * 255.0).round() as u8;
RgbaColor::new(f(r), f(g), f(b), f(a))
},
- ))
+ )))
}
/// `min`: The minimum of a sequence of values.
-pub fn min(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- minmax(ctx, args, Ordering::Less)
+pub fn min(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ minmax(args, Ordering::Less)
}
/// `max`: The maximum of a sequence of values.
-pub fn max(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value {
- minmax(ctx, args, Ordering::Greater)
+pub fn max(_: &mut EvalContext, args: &mut FuncArgs) -> TypResult<Value> {
+ minmax(args, Ordering::Greater)
}
/// Find the minimum or maximum of a sequence of values.
-fn minmax(ctx: &mut EvalContext, args: &mut FuncArgs, goal: Ordering) -> Value {
- let span = args.span;
- let mut extremum = None;
+fn minmax(args: &mut FuncArgs, goal: Ordering) -> TypResult<Value> {
+ let &mut FuncArgs { file, span, .. } = args;
+ let mut extremum = args.expect::<Value>("value")?;
for value in args.all::<Value>() {
- if let Some(prev) = &extremum {
- match value.partial_cmp(&prev) {
- Some(ordering) if ordering == goal => extremum = Some(value),
- Some(_) => {}
- None => {
- ctx.diag(error!(
- span,
- "cannot compare {} with {}",
- prev.type_name(),
- value.type_name(),
- ));
- return Value::Error;
+ match value.partial_cmp(&extremum) {
+ Some(ordering) => {
+ if ordering == goal {
+ extremum = value;
}
}
- } else {
- extremum = Some(value);
+ None => bail!(
+ file,
+ span,
+ "cannot compare {} with {}",
+ extremum.type_name(),
+ value.type_name(),
+ ),
}
}
- extremum.unwrap_or_else(|| {
- args.expect::<Value>(ctx, "value");
- Value::Error
- })
+ Ok(extremum)
}