diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-07-30 18:04:08 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-07-30 18:49:19 +0200 |
| commit | 1ee1d078e2480ddd08d40915bc7a74a8352acff0 (patch) | |
| tree | 1e7ff367278a19fead3e404cf06d65bfb80a6cd9 /src/library/utility.rs | |
| parent | 42a27b48df427edf8dbb624c51551a90ecf2e7ea (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.rs | 96 |
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) } |
