diff options
Diffstat (limited to 'src/eval/mod.rs')
| -rw-r--r-- | src/eval/mod.rs | 135 |
1 files changed, 5 insertions, 130 deletions
diff --git a/src/eval/mod.rs b/src/eval/mod.rs index f7a32127..b8561a87 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -13,6 +13,7 @@ mod scope; mod state; mod str; mod template; +mod walk; pub use self::str::*; pub use array::*; @@ -23,25 +24,24 @@ pub use scope::*; pub use state::*; pub use template::*; pub use value::*; +pub use walk::*; use std::cell::RefMut; use std::collections::HashMap; -use std::fmt::Write; use std::io; use std::mem; use std::path::PathBuf; use std::rc::Rc; use crate::diag::{At, Error, StrResult, Trace, Tracepoint, TypResult}; -use crate::geom::{Angle, Fractional, Gen, Length, Relative}; +use crate::geom::{Angle, Fractional, Length, Relative}; use crate::image::ImageStore; -use crate::layout::{ParChild, ParNode, StackChild, StackNode}; use crate::loading::Loader; use crate::parse::parse; use crate::source::{SourceId, SourceStore}; use crate::syntax::visit::Visit; use crate::syntax::*; -use crate::util::{EcoString, RefMutExt}; +use crate::util::RefMutExt; use crate::Context; /// Evaluate a parsed source file into a module. @@ -52,7 +52,7 @@ pub fn eval(ctx: &mut Context, source: SourceId, ast: &SyntaxTree) -> TypResult< } /// An evaluated module, ready for importing or instantiation. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Default, Clone)] pub struct Module { /// The top-level definitions that were bound in this module. pub scope: Scope, @@ -717,128 +717,3 @@ impl Access for CallExpr { }) } } - -/// Walk a syntax node and fill the currently built template. -pub trait Walk { - /// Walk the node. - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()>; -} - -impl Walk for SyntaxTree { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - for node in self.iter() { - node.walk(ctx)?; - } - Ok(()) - } -} - -impl Walk for SyntaxNode { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - match self { - Self::Space => ctx.template.space(), - Self::Linebreak(_) => ctx.template.linebreak(), - Self::Parbreak(_) => ctx.template.parbreak(), - Self::Strong(_) => { - ctx.template.modify(|state| state.font_mut().strong ^= true); - } - Self::Emph(_) => { - ctx.template.modify(|state| state.font_mut().emph ^= true); - } - Self::Text(text) => ctx.template.text(text), - Self::Raw(raw) => raw.walk(ctx)?, - Self::Heading(heading) => heading.walk(ctx)?, - Self::List(list) => list.walk(ctx)?, - Self::Enum(enum_) => enum_.walk(ctx)?, - Self::Expr(expr) => match expr.eval(ctx)? { - Value::None => {} - Value::Int(v) => ctx.template.text(v.to_string()), - Value::Float(v) => ctx.template.text(v.to_string()), - Value::Str(v) => ctx.template.text(v), - Value::Template(v) => ctx.template += v, - // For values which can't be shown "naturally", we print the - // representation in monospace. - other => ctx.template.monospace(other.to_string()), - }, - } - Ok(()) - } -} - -impl Walk for RawNode { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - if self.block { - ctx.template.parbreak(); - } - - ctx.template.monospace(&self.text); - - if self.block { - ctx.template.parbreak(); - } - - Ok(()) - } -} - -impl Walk for HeadingNode { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - let level = self.level; - let body = self.body.eval(ctx)?; - - ctx.template.parbreak(); - ctx.template.save(); - ctx.template.modify(move |state| { - let font = state.font_mut(); - let upscale = 1.6 - 0.1 * level as f64; - font.size *= upscale; - font.strong = true; - }); - ctx.template += body; - ctx.template.restore(); - ctx.template.parbreak(); - - Ok(()) - } -} - -impl Walk for ListItem { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - let body = self.body.eval(ctx)?; - walk_item(ctx, '•'.into(), body); - Ok(()) - } -} - -impl Walk for EnumItem { - fn walk(&self, ctx: &mut EvalContext) -> TypResult<()> { - let body = self.body.eval(ctx)?; - let mut label = EcoString::new(); - write!(&mut label, "{}.", self.number.unwrap_or(1)).unwrap(); - walk_item(ctx, label, body); - Ok(()) - } -} - -/// Walk a list or enum item, converting it into a stack. -fn walk_item(ctx: &mut EvalContext, label: EcoString, body: Template) { - ctx.template += Template::from_block(move |state| { - let label = ParNode { - dir: state.dirs.cross, - line_spacing: state.line_spacing(), - children: vec![ParChild::Text( - label.clone(), - state.aligns.cross, - Rc::clone(&state.font), - )], - }; - StackNode { - dirs: Gen::new(state.dirs.main, state.dirs.cross), - children: vec![ - StackChild::Any(label.into(), Gen::default()), - StackChild::Spacing((state.font.size / 2.0).into()), - StackChild::Any(body.to_stack(&state).into(), Gen::default()), - ], - } - }); -} |
