summaryrefslogtreecommitdiff
path: root/src/exec
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-06-09 00:37:13 +0200
committerLaurenz <laurmaedje@gmail.com>2021-06-09 00:37:13 +0200
commit5afb42ad89abb518a01a09051f0f9b6f75bd383e (patch)
treeb12368a287f22de711df8d759c20ee742ed5b4c2 /src/exec
parentd69dfa84ec957ac4037f60a3335416a9f73b97c8 (diff)
Lists with indent-based parsing
- Unordered lists with indent-based parsing and basic layout using stacks - Headings are now also indent based - Removes syntax functions since they will be superseded by select & transform
Diffstat (limited to 'src/exec')
-rw-r--r--src/exec/context.rs20
-rw-r--r--src/exec/mod.rs91
-rw-r--r--src/exec/state.rs2
3 files changed, 95 insertions, 18 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs
index 016b092a..63008260 100644
--- a/src/exec/context.rs
+++ b/src/exec/context.rs
@@ -1,13 +1,13 @@
use std::mem;
-use super::{Exec, FontFamily, State};
+use super::{Exec, ExecWithMap, FontFamily, State};
use crate::diag::{Diag, DiagSet, Pass};
-use crate::eval::TemplateValue;
+use crate::eval::{ExprMap, TemplateValue};
use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size};
use crate::layout::{
AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, Tree,
};
-use crate::syntax::Span;
+use crate::syntax::{self, Span};
/// The context for execution.
pub struct ExecContext {
@@ -48,12 +48,22 @@ impl ExecContext {
}
/// Execute a template and return the result as a stack node.
- pub fn exec_template(&mut self, template: &TemplateValue) -> StackNode {
+ pub fn exec_template_stack(&mut self, template: &TemplateValue) -> StackNode {
+ self.exec_stack(|ctx| template.exec(ctx))
+ }
+
+ /// Execute a tree with a map and return the result as a stack node.
+ pub fn exec_tree_stack(&mut self, tree: &syntax::Tree, map: &ExprMap) -> StackNode {
+ self.exec_stack(|ctx| tree.exec_with_map(ctx, map))
+ }
+
+ /// Execute something and return the result as a stack node.
+ pub fn exec_stack(&mut self, f: impl FnOnce(&mut Self)) -> StackNode {
let snapshot = self.state.clone();
let page = self.page.take();
let stack = mem::replace(&mut self.stack, StackBuilder::new(&self.state));
- template.exec(self);
+ f(self);
self.state = snapshot;
self.page = page;
diff --git a/src/exec/mod.rs b/src/exec/mod.rs
index 35e6b55c..a13d8c5e 100644
--- a/src/exec/mod.rs
+++ b/src/exec/mod.rs
@@ -9,10 +9,11 @@ pub use state::*;
use std::rc::Rc;
use crate::diag::Pass;
-use crate::eval::{NodeMap, TemplateFunc, TemplateNode, TemplateValue, Value};
-use crate::layout;
+use crate::eval::{ExprMap, TemplateFunc, TemplateNode, TemplateValue, Value};
+use crate::geom::{Dir, Gen};
+use crate::layout::{self, FixedNode, StackChild, StackNode};
use crate::pretty::pretty;
-use crate::syntax::*;
+use crate::syntax;
/// Execute a template to produce a layout tree.
pub fn exec(template: &TemplateValue, state: State) -> Pass<layout::Tree> {
@@ -33,30 +34,96 @@ pub trait Exec {
fn exec(&self, ctx: &mut ExecContext);
}
-/// Execute a node with a node map that applies to it.
+/// Execute a node with an expression map that applies to it.
pub trait ExecWithMap {
/// Execute the node.
- fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap);
+ fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap);
}
-impl ExecWithMap for Tree {
- fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) {
+impl ExecWithMap for syntax::Tree {
+ fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
for node in self {
node.exec_with_map(ctx, map);
}
}
}
-impl ExecWithMap for Node {
- fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) {
+impl ExecWithMap for syntax::Node {
+ fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
match self {
- Node::Text(text) => ctx.push_text(text),
- Node::Space => ctx.push_word_space(),
- _ => map[&(self as *const _)].exec(ctx),
+ Self::Text(text) => ctx.push_text(text),
+ Self::Space => ctx.push_word_space(),
+ Self::Linebreak(_) => ctx.linebreak(),
+ Self::Parbreak(_) => ctx.parbreak(),
+ Self::Strong(_) => ctx.state.font.strong ^= true,
+ Self::Emph(_) => ctx.state.font.emph ^= true,
+ Self::Raw(raw) => raw.exec(ctx),
+ Self::Heading(heading) => heading.exec_with_map(ctx, map),
+ Self::List(list) => list.exec_with_map(ctx, map),
+ Self::Expr(expr) => map[&(expr as *const _)].exec(ctx),
}
}
}
+impl Exec for syntax::RawNode {
+ fn exec(&self, ctx: &mut ExecContext) {
+ if self.block {
+ ctx.parbreak();
+ }
+
+ let snapshot = ctx.state.clone();
+ ctx.set_monospace();
+ ctx.push_text(&self.text);
+ ctx.state = snapshot;
+
+ if self.block {
+ ctx.parbreak();
+ }
+ }
+}
+
+impl ExecWithMap for syntax::HeadingNode {
+ fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
+ let snapshot = ctx.state.clone();
+
+ let upscale = 1.6 - 0.1 * self.level as f64;
+ ctx.state.font.scale *= upscale;
+ ctx.state.font.strong = true;
+
+ self.body.exec_with_map(ctx, map);
+
+ ctx.state = snapshot;
+ ctx.parbreak();
+ }
+}
+
+impl ExecWithMap for syntax::ListNode {
+ fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) {
+ ctx.parbreak();
+
+ let bullet = ctx.exec_stack(|ctx| ctx.push_text("•"));
+ let body = ctx.exec_tree_stack(&self.body, map);
+
+ let stack = StackNode {
+ dirs: Gen::new(Dir::TTB, ctx.state.lang.dir),
+ aspect: None,
+ children: vec![
+ StackChild::Any(bullet.into(), Gen::default()),
+ StackChild::Spacing(ctx.state.font.resolve_size() / 2.0),
+ StackChild::Any(body.into(), Gen::default()),
+ ],
+ };
+
+ ctx.push(FixedNode {
+ width: None,
+ height: None,
+ child: stack.into(),
+ });
+
+ ctx.parbreak();
+ }
+}
+
impl Exec for Value {
fn exec(&self, ctx: &mut ExecContext) {
match self {
diff --git a/src/exec/state.rs b/src/exec/state.rs
index 9a8971cc..aeeeaed5 100644
--- a/src/exec/state.rs
+++ b/src/exec/state.rs
@@ -7,7 +7,7 @@ use crate::geom::*;
use crate::layout::Fill;
use crate::paper::{Paper, PaperClass, PAPER_A4};
-/// The evaluation state.
+/// The execution state.
#[derive(Debug, Clone, PartialEq)]
pub struct State {
/// The current language-related settings.