diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-01-01 17:54:31 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-01-01 17:54:31 +0100 |
| commit | 8cad78481cd52680317032c3bb84cacda5666489 (patch) | |
| tree | 7cc0d17b2ec6d231c33205fa4765de1d63ee32ea /src/eval | |
| parent | 2b6ccd82489afbcd679fb3199de2618fa8811325 (diff) | |
A few small improvements ♻
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/args.rs | 22 | ||||
| -rw-r--r-- | src/eval/mod.rs | 170 | ||||
| -rw-r--r-- | src/eval/value.rs | 8 |
3 files changed, 113 insertions, 87 deletions
diff --git a/src/eval/args.rs b/src/eval/args.rs index b379b975..43c30daf 100644 --- a/src/eval/args.rs +++ b/src/eval/args.rs @@ -4,7 +4,7 @@ use std::mem; use super::{Conv, EvalContext, RefKey, TryFromValue, Value, ValueDict}; use crate::diag::Diag; -use crate::syntax::{Span, SpanVec, SpanWith, Spanned}; +use crate::syntax::{Span, SpanVec, Spanned, WithSpan}; /// A wrapper around a dictionary value that simplifies argument parsing in /// functions. @@ -23,7 +23,11 @@ impl Args { { self.0.v.remove(key).and_then(|entry| { let span = entry.value.span; - conv_diag(T::try_from_value(entry.value), &mut ctx.f.diags, span) + conv_diag( + T::try_from_value(entry.value), + &mut ctx.feedback.diags, + span, + ) }) } @@ -41,9 +45,13 @@ impl Args { { if let Some(entry) = self.0.v.remove(key) { let span = entry.value.span; - conv_diag(T::try_from_value(entry.value), &mut ctx.f.diags, span) + conv_diag( + T::try_from_value(entry.value), + &mut ctx.feedback.diags, + span, + ) } else { - ctx.f.diags.push(error!(self.0.span, "missing argument: {}", name)); + ctx.diag(error!(self.0.span, "missing argument: {}", name)); None } } @@ -122,11 +130,11 @@ fn conv_diag<T>(conv: Conv<T>, diags: &mut SpanVec<Diag>, span: Span) -> Option< match conv { Conv::Ok(t) => Some(t), Conv::Warn(t, warn) => { - diags.push(warn.span_with(span)); + diags.push(warn.with_span(span)); Some(t) } Conv::Err(_, err) => { - diags.push(err.span_with(span)); + diags.push(err.with_span(span)); None } } @@ -137,7 +145,7 @@ fn conv_put_back<T>(conv: Conv<T>, slot: &mut Spanned<Value>, span: Span) -> Opt Conv::Ok(t) => Some(t), Conv::Warn(t, _) => Some(t), Conv::Err(v, _) => { - *slot = v.span_with(span); + *slot = v.with_span(span); None } } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index c4da1fe0..56946210 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -48,7 +48,7 @@ pub struct EvalContext { /// The active evaluation state. pub state: State, /// The accumulated feedback. - f: Feedback, + feedback: Feedback, /// The finished page runs. runs: Vec<Pages>, /// The stack of logical groups (paragraphs and such). @@ -71,24 +71,24 @@ impl EvalContext { groups: vec![], inner: vec![], runs: vec![], - f: Feedback::new(), + feedback: Feedback::new(), } } /// Finish evaluation and return the created document. pub fn finish(self) -> Pass<Document> { assert!(self.groups.is_empty(), "unfinished group"); - Pass::new(Document { runs: self.runs }, self.f) + Pass::new(Document { runs: self.runs }, self.feedback) } /// Add a diagnostic to the feedback. pub fn diag(&mut self, diag: Spanned<Diag>) { - self.f.diags.push(diag); + self.feedback.diags.push(diag); } /// Add a decoration to the feedback. pub fn deco(&mut self, deco: Spanned<Deco>) { - self.f.decos.push(deco); + self.feedback.decos.push(deco); } /// Push a layout node to the active group. @@ -246,6 +246,23 @@ impl EvalContext { } } + /// Apply a forced line break. + pub fn apply_linebreak(&mut self) { + self.end_par_group(); + self.start_par_group(); + } + + /// Apply a forced paragraph break. + pub fn apply_parbreak(&mut self) { + self.end_par_group(); + let em = self.state.font.font_size(); + self.push(Spacing { + amount: self.state.par.par_spacing.resolve(em), + softness: Softness::Soft, + }); + self.start_par_group(); + } + /// Construct a text node from the given string based on the active text /// state. pub fn make_text_node(&self, text: String) -> Text { @@ -293,12 +310,12 @@ struct ParGroup { line_spacing: Length, } -/// Defines how items interact with surrounding items. +/// Defines how an item interact with surrounding items. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] pub enum Softness { - /// Soft items can be skipped in some circumstances. + /// A soft item can be skipped in some circumstances. Soft, - /// Hard items are always retained. + /// A hard item is always retained. Hard, } @@ -310,24 +327,35 @@ pub trait Eval { type Output; /// Evaluate the item to the output value. - fn eval(&self, ctx: &mut EvalContext) -> Self::Output; + fn eval(self, ctx: &mut EvalContext) -> Self::Output; } -impl Eval for SynTree { +impl<'a, T> Eval for &'a Box<Spanned<T>> +where + Spanned<&'a T>: Eval, +{ + type Output = <Spanned<&'a T> as Eval>::Output; + + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + (**self).as_ref().eval(ctx) + } +} + +impl Eval for &[Spanned<SynNode>] { type Output = (); - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { for node in self { - node.v.eval(ctx); + node.as_ref().eval(ctx); } } } -impl Eval for SynNode { +impl Eval for Spanned<&SynNode> { type Output = (); - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - match self { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + match self.v { SynNode::Text(text) => { let node = ctx.make_text_node(text.clone()); ctx.push(node); @@ -340,53 +368,43 @@ impl Eval for SynNode { softness: Softness::Soft, }); } - - SynNode::Linebreak => { - ctx.end_par_group(); - ctx.start_par_group(); - } - - SynNode::Parbreak => { - ctx.end_par_group(); - let em = ctx.state.font.font_size(); - ctx.push(Spacing { - amount: ctx.state.par.par_spacing.resolve(em), - softness: Softness::Soft, - }); - ctx.start_par_group(); - } + SynNode::Linebreak => ctx.apply_linebreak(), + SynNode::Parbreak => ctx.apply_parbreak(), SynNode::Strong => ctx.state.font.strong ^= true, SynNode::Emph => ctx.state.font.emph ^= true, - SynNode::Heading(heading) => heading.eval(ctx), - SynNode::Raw(raw) => raw.eval(ctx), + SynNode::Heading(heading) => heading.with_span(self.span).eval(ctx), + SynNode::Raw(raw) => raw.with_span(self.span).eval(ctx), - SynNode::Expr(expr) => expr.eval(ctx).eval(ctx), + SynNode::Expr(expr) => { + let value = expr.with_span(self.span).eval(ctx); + value.eval(ctx) + } } } } -impl Eval for NodeHeading { +impl Eval for Spanned<&NodeHeading> { type Output = (); - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { let prev = ctx.state.clone(); - let upscale = 1.5 - 0.1 * self.level.v as f64; + let upscale = 1.5 - 0.1 * self.v.level.v as f64; ctx.state.font.scale *= upscale; ctx.state.font.strong = true; - self.contents.eval(ctx); - SynNode::Parbreak.eval(ctx); + self.v.contents.eval(ctx); + ctx.apply_parbreak(); ctx.state = prev; } } -impl Eval for NodeRaw { +impl Eval for Spanned<&NodeRaw> { type Output = (); - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { let prev = Rc::clone(&ctx.state.font.families); let families = Rc::make_mut(&mut ctx.state.font.families); families.list.insert(0, "monospace".to_string()); @@ -396,7 +414,7 @@ impl Eval for NodeRaw { let line_spacing = ctx.state.par.line_spacing.resolve(em); let mut children = vec![]; - for line in &self.lines { + for line in &self.v.lines { children.push(LayoutNode::Text(ctx.make_text_node(line.clone()))); children.push(LayoutNode::Spacing(Spacing { amount: line_spacing, @@ -415,24 +433,24 @@ impl Eval for NodeRaw { } } -impl Eval for Expr { +impl Eval for Spanned<&Expr> { type Output = Value; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - match self { - Self::Lit(lit) => lit.eval(ctx), - Self::Call(call) => call.eval(ctx), - Self::Unary(unary) => unary.eval(ctx), - Self::Binary(binary) => binary.eval(ctx), + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + match self.v { + Expr::Lit(lit) => lit.with_span(self.span).eval(ctx), + Expr::Call(call) => call.with_span(self.span).eval(ctx), + Expr::Unary(unary) => unary.with_span(self.span).eval(ctx), + Expr::Binary(binary) => binary.with_span(self.span).eval(ctx), } } } -impl Eval for Lit { +impl Eval for Spanned<&Lit> { type Output = Value; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - match *self { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + match *self.v { Lit::Ident(ref v) => Value::Ident(v.clone()), Lit::Bool(v) => Value::Bool(v), Lit::Int(v) => Value::Int(v), @@ -441,20 +459,20 @@ impl Eval for Lit { Lit::Percent(v) => Value::Relative(Relative::new(v / 100.0)), Lit::Color(v) => Value::Color(Color::Rgba(v)), Lit::Str(ref v) => Value::Str(v.clone()), - Lit::Dict(ref v) => Value::Dict(v.eval(ctx)), + Lit::Dict(ref v) => Value::Dict(v.with_span(self.span).eval(ctx)), Lit::Content(ref v) => Value::Content(v.clone()), } } } -impl Eval for LitDict { +impl Eval for Spanned<&LitDict> { type Output = ValueDict; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { let mut dict = ValueDict::new(); - for entry in &self.0 { - let val = entry.expr.v.eval(ctx); - let spanned = val.span_with(entry.expr.span); + for entry in &self.v.0 { + let val = entry.expr.as_ref().eval(ctx); + let spanned = val.with_span(entry.expr.span); if let Some(key) = &entry.key { dict.insert(&key.v, SpannedEntry::new(key.span, spanned)); } else { @@ -466,58 +484,58 @@ impl Eval for LitDict { } } -impl Eval for ExprCall { +impl Eval for Spanned<&ExprCall> { type Output = Value; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - let name = &self.name.v; - let span = self.name.span; - let dict = self.args.v.eval(ctx); + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + let name = &self.v.name.v; + let span = self.v.name.span; + let dict = self.v.args.as_ref().eval(ctx); if let Some(func) = ctx.state.scope.get(name) { - let args = Args(dict.span_with(self.args.span)); - ctx.f.decos.push(Deco::Resolved.span_with(span)); + let args = Args(dict.with_span(self.v.args.span)); + ctx.feedback.decos.push(Deco::Resolved.with_span(span)); (func.clone())(args, ctx) } else { if !name.is_empty() { ctx.diag(error!(span, "unknown function")); - ctx.f.decos.push(Deco::Unresolved.span_with(span)); + ctx.feedback.decos.push(Deco::Unresolved.with_span(span)); } Value::Dict(dict) } } } -impl Eval for ExprUnary { +impl Eval for Spanned<&ExprUnary> { type Output = Value; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - let value = self.expr.v.eval(ctx); + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + let value = self.v.expr.eval(ctx); if let Value::Error = value { return Value::Error; } - let span = self.op.span.join(self.expr.span); - match self.op.v { + let span = self.v.op.span.join(self.v.expr.span); + match self.v.op.v { UnOp::Neg => neg(ctx, span, value), } } } -impl Eval for ExprBinary { +impl Eval for Spanned<&ExprBinary> { type Output = Value; - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { - let lhs = self.lhs.v.eval(ctx); - let rhs = self.rhs.v.eval(ctx); + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + let lhs = self.v.lhs.eval(ctx); + let rhs = self.v.rhs.eval(ctx); if lhs == Value::Error || rhs == Value::Error { return Value::Error; } - let span = self.lhs.span.join(self.rhs.span); - match self.op.v { + let span = self.v.lhs.span.join(self.v.rhs.span); + match self.v.op.v { BinOp::Add => add(ctx, span, lhs, rhs), BinOp::Sub => sub(ctx, span, lhs, rhs), BinOp::Mul => mul(ctx, span, lhs, rhs), diff --git a/src/eval/value.rs b/src/eval/value.rs index f15ae0c5..a009e891 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -11,7 +11,7 @@ use crate::color::Color; use crate::diag::Diag; use crate::geom::{Dir, Length, Linear, Relative}; use crate::paper::Paper; -use crate::syntax::{Ident, SpanWith, Spanned, SynTree}; +use crate::syntax::{Ident, Spanned, SynTree, WithSpan}; /// A computational value. #[derive(Clone, PartialEq)] @@ -69,11 +69,11 @@ impl Value { } } -impl Eval for Value { +impl Eval for &Value { type Output = (); /// Evaluate everything contained in this value. - fn eval(&self, ctx: &mut EvalContext) -> Self::Output { + fn eval(self, ctx: &mut EvalContext) -> Self::Output { match self { // Don't print out none values. Value::None => {} @@ -206,7 +206,7 @@ impl<T> Conv<T> { impl<T: TryFromValue> TryFromValue for Spanned<T> { fn try_from_value(value: Spanned<Value>) -> Conv<Self> { let span = value.span; - T::try_from_value(value).map(|v| v.span_with(span)) + T::try_from_value(value).map(|v| v.with_span(span)) } } |
