summaryrefslogtreecommitdiff
path: root/src/eval/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval/mod.rs')
-rw-r--r--src/eval/mod.rs135
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()),
- ],
- }
- });
-}