diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-07-10 20:42:28 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-07-10 23:14:46 +0200 |
| commit | 891e0c5fa6cd9200c24011c33b6f2115d84d4d74 (patch) | |
| tree | 3ea29dff87350d3d2020cdbb48b7acd01a33a1a2 /src | |
| parent | 982ce85976913463eed6c95d3599868c5e1a79dd (diff) | |
Remove warnings from parsing and casting
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval/function.rs | 34 | ||||
| -rw-r--r-- | src/eval/mod.rs | 8 | ||||
| -rw-r--r-- | src/eval/value.rs | 63 | ||||
| -rw-r--r-- | src/library/elements.rs | 8 | ||||
| -rw-r--r-- | src/library/layout.rs | 23 | ||||
| -rw-r--r-- | src/library/text.rs | 47 | ||||
| -rw-r--r-- | src/library/utility.rs | 27 | ||||
| -rw-r--r-- | src/parse/mod.rs | 3 | ||||
| -rw-r--r-- | src/parse/parser.rs | 5 |
9 files changed, 74 insertions, 144 deletions
diff --git a/src/eval/function.rs b/src/eval/function.rs index c986d71a..28a62873 100644 --- a/src/eval/function.rs +++ b/src/eval/function.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; use std::ops::Deref; use std::rc::Rc; -use super::{Cast, CastResult, EvalContext, Value}; +use super::{Cast, EvalContext, Value}; use crate::eco::EcoString; use crate::syntax::{Span, Spanned}; @@ -76,7 +76,7 @@ pub struct FuncArg { impl FuncArgs { /// Find and consume the first castable positional argument. - pub fn eat<T>(&mut self, ctx: &mut EvalContext) -> Option<T> + pub fn eat<T>(&mut self) -> Option<T> where T: Cast<Spanned<Value>>, { @@ -87,19 +87,12 @@ impl FuncArgs { } let value = std::mem::replace(&mut slot.value, Spanned::zero(Value::None)); - let span = value.span; - match T::cast(value) { - CastResult::Ok(t) => { - self.items.remove(index); - Some(t) - } - CastResult::Warn(t, m) => { + Ok(t) => { self.items.remove(index); - ctx.diag(warning!(span, "{}", m)); Some(t) } - CastResult::Err(value) => { + Err(value) => { slot.value = value; None } @@ -113,7 +106,7 @@ impl FuncArgs { where T: Cast<Spanned<Value>>, { - let found = self.eat(ctx); + let found = self.eat(); if found.is_none() { ctx.diag(error!(self.span, "missing argument: {}", what)); } @@ -121,16 +114,11 @@ impl FuncArgs { } /// Find, consume and collect all castable positional arguments. - /// - /// This function returns a vector instead of an iterator because the - /// iterator would require unique access to the context, rendering it rather - /// unusable. If you need to process arguments one-by-one, you probably want - /// to use a while-let loop together with [`eat()`](Self::eat). - pub fn all<T>(&mut self, ctx: &mut EvalContext) -> Vec<T> + pub fn all<T>(&mut self) -> impl Iterator<Item = T> + '_ where T: Cast<Spanned<Value>>, { - std::iter::from_fn(|| self.eat(ctx)).collect() + std::iter::from_fn(move || self.eat()) } /// Cast and remove the value for the given named argument, producing an @@ -148,12 +136,8 @@ impl FuncArgs { let span = value.span; match T::cast(value) { - CastResult::Ok(t) => Some(t), - CastResult::Warn(t, m) => { - ctx.diag(warning!(span, "{}", m)); - Some(t) - } - CastResult::Err(value) => { + Ok(t) => Some(t), + Err(value) => { ctx.diag(error!( span, "expected {}, found {}", diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 689234bd..fd4417ec 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -195,12 +195,8 @@ impl<'a> EvalContext<'a> { } match T::cast(value) { - CastResult::Ok(t) => Some(t), - CastResult::Warn(t, m) => { - self.diag(warning!(span, "{}", m)); - Some(t) - } - CastResult::Err(value) => { + Ok(t) => Some(t), + Err(value) => { self.diag(error!( span, "expected {}, found {}", diff --git a/src/eval/value.rs b/src/eval/value.rs index 7c35fdbd..8e3a1c61 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -84,7 +84,7 @@ impl Value { } /// Try to cast the value into a specific type. - pub fn cast<T>(self) -> CastResult<T, Self> + pub fn cast<T>(self) -> Result<T, Self> where T: Cast<Value>, { @@ -236,28 +236,7 @@ where /// 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) -> CastResult<Self, V>; -} - -/// The result of casting a value to a specific type. -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum CastResult<T, V> { - /// The value was cast successfully. - Ok(T), - /// The value was cast successfully, but with a warning message. - Warn(T, String), - /// The value could not be cast into the specified type. - Err(V), -} - -impl<T, V> CastResult<T, V> { - /// Access the conversion result, discarding a possibly existing warning. - pub fn ok(self) -> Option<T> { - match self { - CastResult::Ok(t) | CastResult::Warn(t, _) => Some(t), - CastResult::Err(_) => None, - } - } + fn cast(value: V) -> Result<Self, V>; } impl Type for Value { @@ -265,8 +244,8 @@ impl Type for Value { } impl Cast<Value> for Value { - fn cast(value: Value) -> CastResult<Self, Value> { - CastResult::Ok(value) + fn cast(value: Value) -> Result<Self, Value> { + Ok(value) } } @@ -274,12 +253,11 @@ impl<T> Cast<Spanned<Value>> for T where T: Cast<Value>, { - fn cast(value: Spanned<Value>) -> CastResult<Self, Spanned<Value>> { + fn cast(value: Spanned<Value>) -> Result<Self, Spanned<Value>> { let span = value.span; match T::cast(value.v) { - CastResult::Ok(t) => CastResult::Ok(t), - CastResult::Warn(t, m) => CastResult::Warn(t, m), - CastResult::Err(v) => CastResult::Err(Spanned::new(v, span)), + Ok(t) => Ok(t), + Err(v) => Err(Spanned::new(v, span)), } } } @@ -288,12 +266,11 @@ impl<T> Cast<Spanned<Value>> for Spanned<T> where T: Cast<Value>, { - fn cast(value: Spanned<Value>) -> CastResult<Self, Spanned<Value>> { + fn cast(value: Spanned<Value>) -> Result<Self, Spanned<Value>> { let span = value.span; match T::cast(value.v) { - CastResult::Ok(t) => CastResult::Ok(Spanned::new(t, span)), - CastResult::Warn(t, m) => CastResult::Warn(Spanned::new(t, span), m), - CastResult::Err(v) => CastResult::Err(Spanned::new(v, span)), + Ok(t) => Ok(Spanned::new(t, span)), + Err(v) => Err(Spanned::new(v, span)), } } } @@ -315,11 +292,11 @@ macro_rules! primitive { } impl Cast<Value> for $type { - fn cast(value: Value) -> CastResult<Self, Value> { + fn cast(value: Value) -> Result<Self, Value> { match value { - $variant(v) => CastResult::Ok(v), - $($pattern => CastResult::Ok($out),)* - v => CastResult::Err(v), + $variant(v) => Ok(v), + $($pattern => Ok($out),)* + v => Err(v), } } } @@ -426,26 +403,26 @@ macro_rules! castable { impl $crate::eval::Cast<$crate::eval::Value> for $type { fn cast( value: $crate::eval::Value, - ) -> $crate::eval::CastResult<Self, $crate::eval::Value> { + ) -> Result<Self, $crate::eval::Value> { use $crate::eval::*; #[allow(unreachable_code)] match value { - $($pattern => CastResult::Ok($out),)* + $($pattern => Ok($out),)* Value::Any(mut any) => { any = match any.downcast::<Self>() { - Ok(t) => return CastResult::Ok(t), + Ok(t) => return Ok(t), Err(any) => any, }; $(any = match any.downcast::<$anytype>() { - Ok($anyvar) => return CastResult::Ok($anyout), + Ok($anyvar) => return Ok($anyout), Err(any) => any, };)* - CastResult::Err(Value::Any(any)) + Err(Value::Any(any)) }, - v => CastResult::Err(v), + v => Err(v), } } } diff --git a/src/library/elements.rs b/src/library/elements.rs index 6c6c66db..dd2da877 100644 --- a/src/library/elements.rs +++ b/src/library/elements.rs @@ -36,7 +36,7 @@ pub fn rect(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let width = args.named(ctx, "width"); let height = args.named(ctx, "height"); let fill = args.named(ctx, "fill"); - let body = args.eat(ctx).unwrap_or_default(); + let body = args.eat().unwrap_or_default(); rect_impl(width, height, None, fill, body) } @@ -46,7 +46,7 @@ pub fn square(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let width = length.or_else(|| args.named(ctx, "width")); let height = width.is_none().then(|| args.named(ctx, "height")).flatten(); let fill = args.named(ctx, "fill"); - let body = args.eat(ctx).unwrap_or_default(); + let body = args.eat().unwrap_or_default(); rect_impl(width, height, Some(N64::from(1.0)), fill, body) } @@ -80,7 +80,7 @@ pub fn ellipse(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let width = args.named(ctx, "width"); let height = args.named(ctx, "height"); let fill = args.named(ctx, "fill"); - let body = args.eat(ctx).unwrap_or_default(); + let body = args.eat().unwrap_or_default(); ellipse_impl(width, height, None, fill, body) } @@ -90,7 +90,7 @@ pub fn circle(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let width = radius.or_else(|| args.named(ctx, "width")); let height = width.is_none().then(|| args.named(ctx, "height")).flatten(); let fill = args.named(ctx, "fill"); - let body = args.eat(ctx).unwrap_or_default(); + let body = args.eat().unwrap_or_default(); ellipse_impl(width, height, Some(N64::from(1.0)), fill, body) } diff --git a/src/library/layout.rs b/src/library/layout.rs index d7ada806..19352062 100644 --- a/src/library/layout.rs +++ b/src/library/layout.rs @@ -5,7 +5,7 @@ use crate::paper::{Paper, PaperClass}; /// `page`: Configure pages. pub fn page(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let span = args.span; - let paper = args.eat::<Spanned<EcoString>>(ctx).and_then(|name| { + let paper = args.eat::<Spanned<EcoString>>().and_then(|name| { Paper::from_name(&name.v).or_else(|| { ctx.diag(error!(name.span, "invalid paper name")); None @@ -104,8 +104,8 @@ fn spacing_impl(ctx: &mut EvalContext, args: &mut FuncArgs, axis: GenAxis) -> Va /// `align`: Configure the alignment along the layouting axes. pub fn align(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let first = args.eat::<AlignValue>(ctx); - let second = args.eat::<AlignValue>(ctx); + let first = args.eat::<AlignValue>(); + let second = args.eat::<AlignValue>(); let mut horizontal = args.named::<AlignValue>(ctx, "horizontal"); let mut vertical = args.named::<AlignValue>(ctx, "vertical"); let body = args.expect::<Template>(ctx, "body").unwrap_or_default(); @@ -207,7 +207,7 @@ castable! { pub fn boxed(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let width = args.named(ctx, "width"); let height = args.named(ctx, "height"); - let body = args.eat(ctx).unwrap_or_default(); + let body = args.eat().unwrap_or_default(); Value::template(move |ctx| { let child = ctx.exec_template_stack(&body).into(); ctx.push_into_par(FixedNode { width, height, child }); @@ -216,7 +216,7 @@ pub fn boxed(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `block`: Place content in a block. pub fn block(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let body = args.eat(ctx).unwrap_or_default(); + let body = args.expect(ctx, "body").unwrap_or_default(); Value::template(move |ctx| { let block = ctx.exec_template_stack(&body); ctx.push_into_stack(block); @@ -225,7 +225,7 @@ pub fn block(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `pad`: Pad content at the sides. pub fn pad(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let all = args.eat(ctx); + let all = args.eat(); let left = args.named(ctx, "left"); let top = args.named(ctx, "top"); let right = args.named(ctx, "right"); @@ -248,7 +248,7 @@ pub fn pad(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `stack`: Stack children along an axis. pub fn stack(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let dir = args.named::<Dir>(ctx, "dir").unwrap_or(Dir::TTB); - let children = args.all(ctx); + let children: Vec<_> = args.all().collect(); Value::template(move |ctx| { let children = children @@ -271,15 +271,18 @@ pub fn stack(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { pub fn grid(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let columns = args.named::<Tracks>(ctx, "columns").unwrap_or_default(); let rows = args.named::<Tracks>(ctx, "rows").unwrap_or_default(); + + let gutter_columns = args.named::<Tracks>(ctx, "gutter-columns"); + let gutter_rows = args.named::<Tracks>(ctx, "gutter-rows"); let gutter = args .named::<Linear>(ctx, "gutter") .map(|v| vec![TrackSizing::Linear(v)]) .unwrap_or_default(); - let gutter_columns = args.named::<Tracks>(ctx, "gutter-columns"); - let gutter_rows = args.named::<Tracks>(ctx, "gutter-rows"); + let column_dir = args.named(ctx, "column-dir"); let row_dir = args.named(ctx, "row-dir"); - let children = args.all(ctx); + + let children: Vec<_> = args.all().collect(); Value::template(move |ctx| { let children = children diff --git a/src/library/text.rs b/src/library/text.rs index e6de04a1..0f6f3ec1 100644 --- a/src/library/text.rs +++ b/src/library/text.rs @@ -1,3 +1,5 @@ +use std::convert::TryFrom; + use crate::exec::{FontState, LineState}; use crate::font::{FontStretch, FontStyle, FontWeight}; use crate::layout::Paint; @@ -6,14 +8,14 @@ use super::*; /// `font`: Configure the font. pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let families = args.all(ctx); + let families: Vec<_> = args.all().collect(); let list = if families.is_empty() { args.named(ctx, "family") } else { Some(FontDef(families)) }; - let size = args.eat(ctx).or_else(|| args.named::<Linear>(ctx, "size")); + let size = args.eat().or_else(|| args.named::<Linear>(ctx, "size")); let style = args.named(ctx, "style"); let weight = args.named(ctx, "weight"); let stretch = args.named(ctx, "stretch"); @@ -116,42 +118,13 @@ castable! { castable! { FontWeight: "font weight", Value::Int(number) => { - let [min, max] = [Self::THIN, Self::BLACK]; - let message = || format!( - "should be between {} and {}", - min.to_number(), - max.to_number(), - ); - - return if number < i64::from(min.to_number()) { - CastResult::Warn(min, message()) - } else if number > i64::from(max.to_number()) { - CastResult::Warn(max, message()) - } else { - CastResult::Ok(Self::from_number(number as u16)) - }; - }, + u16::try_from(number).map_or(Self::BLACK, Self::from_number) + } } castable! { FontStretch: "font stretch", - Value::Relative(relative) => { - let [min, max] = [Self::ULTRA_CONDENSED, Self::ULTRA_EXPANDED]; - let message = || format!( - "should be between {} and {}", - Relative::new(min.to_ratio() as f64), - Relative::new(max.to_ratio() as f64), - ); - - let ratio = relative.get() as f32; - let value = Self::from_ratio(ratio); - - return if ratio < min.to_ratio() || ratio > max.to_ratio() { - CastResult::Warn(value, message()) - } else { - CastResult::Ok(value) - }; - }, + Value::Relative(relative) => Self::from_ratio(relative.get() as f32), } castable! { @@ -185,7 +158,7 @@ pub fn par(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `lang`: Configure the language. pub fn lang(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { - let iso = args.eat::<EcoString>(ctx).map(|s| lang_dir(&s)); + let iso = args.eat::<EcoString>().map(|s| lang_dir(&s)); let dir = match args.named::<Spanned<Dir>>(ctx, "dir") { Some(dir) if dir.v.axis() == SpecAxis::Horizontal => Some(dir.v), Some(dir) => { @@ -235,8 +208,8 @@ fn line_impl( args: &mut FuncArgs, substate: fn(&mut FontState) -> &mut Option<Rc<LineState>>, ) -> Value { - let stroke = args.eat(ctx).or_else(|| args.named(ctx, "stroke")); - let thickness = args.eat(ctx).or_else(|| args.named::<Linear>(ctx, "thickness")); + let stroke = args.eat().or_else(|| args.named(ctx, "stroke")); + let thickness = args.eat().or_else(|| args.named::<Linear>(ctx, "thickness")); let offset = args.named(ctx, "offset"); let extent = args.named(ctx, "extent").unwrap_or_default(); let body = args.expect::<Template>(ctx, "body").unwrap_or_default(); diff --git a/src/library/utility.rs b/src/library/utility.rs index eaa6146d..ce45aae7 100644 --- a/src/library/utility.rs +++ b/src/library/utility.rs @@ -39,7 +39,7 @@ pub fn len(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// `rgb`: Create an RGB(A) color. pub fn rgb(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { Value::Color(Color::Rgba( - if let Some(string) = args.eat::<Spanned<EcoString>>(ctx) { + if let Some(string) = args.eat::<Spanned<EcoString>>() { match RgbaColor::from_str(&string.v) { Ok(color) => color, Err(_) => { @@ -48,20 +48,12 @@ pub fn rgb(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { } } } else { - let r = args.expect(ctx, "red component"); - let g = args.expect(ctx, "green component"); - let b = args.expect(ctx, "blue component"); - let a = args.eat(ctx); - let mut clamp = |component: Option<Spanned<f64>>, default| { - component.map_or(default, |c| { - if c.v < 0.0 || c.v > 1.0 { - ctx.diag(warning!(c.span, "should be between 0.0 and 1.0")); - } - (c.v.max(0.0).min(1.0) * 255.0).round() as u8 - }) - }; - - RgbaColor::new(clamp(r, 0), clamp(g, 0), clamp(b, 0), clamp(a, 255)) + 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 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)) }, )) } @@ -78,16 +70,17 @@ pub fn max(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { /// 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; - while let Some(value) = args.eat::<Value>(ctx) { + 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!( - args.span, + span, "cannot compare {} with {}", prev.type_name(), value.type_name(), diff --git a/src/parse/mod.rs b/src/parse/mod.rs index ecce0138..6724c559 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -193,8 +193,7 @@ fn heading(p: &mut Parser) -> SyntaxNode { } if level > 6 { - p.diag(warning!(start .. p.prev_end(), "should not exceed depth 6")); - level = 6; + return SyntaxNode::Text(p.eaten_from(start).into()); } let body = tree_indented(p); diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 1e0f2f5d..d4192b50 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -322,6 +322,11 @@ impl<'s> Parser<'s> { Span::new(start, self.prev_end()) } + /// Return the source string from `start` to the end of the previous token. + pub fn eaten_from(&self, start: usize) -> &'s str { + self.tokens.scanner().get(start .. self.prev_end()) + } + /// Jump to an index in the string. /// /// You need to know the correct column. |
