From 1927cc86dae1df300b3472c52f1777baf637dc6f Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 9 May 2022 00:03:57 +0200 Subject: [PATCH] Set, show, wrap in code blocks --- src/eval/array.rs | 14 +- src/eval/control.rs | 65 ------- src/eval/func.rs | 18 +- src/eval/mod.rs | 285 +++++++++++++++++++++--------- src/eval/module.rs | 21 --- src/eval/value.rs | 5 - src/lib.rs | 11 +- src/parse/mod.rs | 7 +- tests/ref/code/break-continue.png | Bin 0 -> 5885 bytes tests/ref/style/set.png | Bin 12397 -> 14415 bytes tests/ref/style/show-node.png | Bin 17385 -> 22014 bytes tests/typ/code/break-continue.typ | 57 +++++- tests/typ/code/return.typ | 35 +++- tests/typ/style/set.typ | 14 +- tests/typ/style/show-node.typ | 31 +++- tests/typ/style/wrap.typ | 11 +- 16 files changed, 372 insertions(+), 202 deletions(-) delete mode 100644 src/eval/control.rs delete mode 100644 src/eval/module.rs create mode 100644 tests/ref/code/break-continue.png diff --git a/src/eval/array.rs b/src/eval/array.rs index 9abab8cf2..86347106b 100644 --- a/src/eval/array.rs +++ b/src/eval/array.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::ops::{Add, AddAssign}; use std::sync::Arc; -use super::{Args, Func, Value}; +use super::{ops, Args, Func, Value}; use crate::diag::{At, StrResult, TypResult}; use crate::syntax::Spanned; use crate::util::ArcExt; @@ -171,18 +171,14 @@ impl Array { let mut result = Value::None; for (i, value) in self.iter().cloned().enumerate() { if i > 0 { - if i + 1 == len { - if let Some(last) = last.take() { - result = result.join(last)?; - } else { - result = result.join(sep.clone())?; - } + if i + 1 == len && last.is_some() { + result = ops::join(result, last.take().unwrap())?; } else { - result = result.join(sep.clone())?; + result = ops::join(result, sep.clone())?; } } - result = result.join(value)?; + result = ops::join(result, value)?; } Ok(result) diff --git a/src/eval/control.rs b/src/eval/control.rs deleted file mode 100644 index 166676d49..000000000 --- a/src/eval/control.rs +++ /dev/null @@ -1,65 +0,0 @@ -use super::{ops, EvalResult, Value}; -use crate::diag::{At, TypError}; -use crate::syntax::Span; - -/// A control flow event that occurred during evaluation. -#[derive(Clone, Debug, PartialEq)] -pub enum Control { - /// Stop iteration in a loop. - Break(Value, Span), - /// Skip the remainder of the current iteration in a loop. - Continue(Value, Span), - /// Stop execution of a function early, returning a value. The bool - /// indicates whether this was an explicit return with value. - Return(Value, bool, Span), - /// Stop the execution because an error occurred. - Err(TypError), -} - -impl From for Control { - fn from(error: TypError) -> Self { - Self::Err(error) - } -} - -impl From for TypError { - fn from(control: Control) -> Self { - match control { - Control::Break(_, span) => { - error!(span, "cannot break outside of loop") - } - Control::Continue(_, span) => { - error!(span, "cannot continue outside of loop") - } - Control::Return(_, _, span) => { - error!(span, "cannot return outside of function") - } - Control::Err(e) => e, - } - } -} - -/// Join a value with an evaluated result. -pub(super) fn join_result( - prev: Value, - result: EvalResult, - result_span: Span, -) -> EvalResult { - match result { - Ok(value) => Ok(ops::join(prev, value).at(result_span)?), - Err(Control::Break(value, span)) => Err(Control::Break( - ops::join(prev, value).at(result_span)?, - span, - )), - Err(Control::Continue(value, span)) => Err(Control::Continue( - ops::join(prev, value).at(result_span)?, - span, - )), - Err(Control::Return(value, false, span)) => Err(Control::Return( - ops::join(prev, value).at(result_span)?, - false, - span, - )), - other => other, - } -} diff --git a/src/eval/func.rs b/src/eval/func.rs index 73f2cac92..4c5761ab6 100644 --- a/src/eval/func.rs +++ b/src/eval/func.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use super::{Args, Control, Eval, Scope, Scopes, Value}; +use super::{Args, Eval, Flow, Scope, Scopes, Value}; use crate::diag::{StrResult, TypResult}; use crate::model::{Content, NodeId, StyleMap}; use crate::syntax::ast::Expr; @@ -210,11 +210,19 @@ impl Closure { scp.top.def_mut(sink, args.take()); } + // Backup the old control flow state. + let prev_flow = ctx.flow.take(); + // Evaluate the body. - let value = match self.body.eval(ctx, &mut scp) { - Err(Control::Return(value, _, _)) => value, - other => other?, - }; + let mut value = self.body.eval(ctx, &mut scp)?; + + // Handle control flow. + match std::mem::replace(&mut ctx.flow, prev_flow) { + Some(Flow::Return(_, Some(explicit))) => value = explicit, + Some(Flow::Return(_, None)) => {} + Some(flow) => return Err(flow.forbidden())?, + None => {} + } Ok(value) } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 677fa4aa1..0021b93ca 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -9,10 +9,8 @@ mod value; mod args; mod capture; -mod control; mod func; pub mod methods; -mod module; pub mod ops; mod raw; mod scope; @@ -22,10 +20,8 @@ pub use self::str::*; pub use args::*; pub use array::*; pub use capture::*; -pub use control::*; pub use dict::*; pub use func::*; -pub use module::*; pub use raw::*; pub use scope::*; pub use value::*; @@ -35,10 +31,11 @@ use std::collections::BTreeMap; use parking_lot::{MappedRwLockWriteGuard, RwLockWriteGuard}; use unicode_segmentation::UnicodeSegmentation; -use crate::diag::{At, StrResult, Trace, Tracepoint, TypResult}; +use crate::diag::{At, StrResult, Trace, Tracepoint, TypError, TypResult}; use crate::geom::{Angle, Em, Fraction, Length, Ratio}; use crate::library; use crate::model::{Content, Pattern, Recipe, StyleEntry, StyleMap}; +use crate::source::{SourceId, SourceStore}; use crate::syntax::ast::*; use crate::syntax::{Span, Spanned}; use crate::util::EcoString; @@ -50,16 +47,60 @@ pub trait Eval { type Output; /// Evaluate the expression to the output value. - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult; + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult; } -/// The result type for evaluating a syntactic construct. -pub type EvalResult = Result; +/// An evaluated module, ready for importing or layouting. +#[derive(Debug, Clone)] +pub struct Module { + /// The top-level definitions that were bound in this module. + pub scope: Scope, + /// The module's layoutable contents. + pub content: Content, + /// The source file revisions this module depends on. + pub deps: Vec<(SourceId, usize)>, +} + +impl Module { + /// Whether the module is still valid for the given sources. + pub fn valid(&self, sources: &SourceStore) -> bool { + self.deps.iter().all(|&(id, rev)| rev == sources.get(id).rev()) + } +} + +/// A control flow event that occurred during evaluation. +#[derive(Debug, Clone, PartialEq)] +pub enum Flow { + /// Stop iteration in a loop. + Break(Span), + /// Skip the remainder of the current iteration in a loop. + Continue(Span), + /// Stop execution of a function early, optionally returning an explicit + /// value. + Return(Span, Option), +} + +impl Flow { + /// Return an error stating that this control flow is forbidden. + pub fn forbidden(&self) -> TypError { + match *self { + Self::Break(span) => { + error!(span, "cannot break outside of loop") + } + Self::Continue(span) => { + error!(span, "cannot continue outside of loop") + } + Self::Return(span, _) => { + error!(span, "cannot return outside of function") + } + } + } +} impl Eval for Markup { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { eval_markup(ctx, scp, &mut self.nodes()) } } @@ -69,17 +110,25 @@ fn eval_markup( ctx: &mut Context, scp: &mut Scopes, nodes: &mut impl Iterator, -) -> EvalResult { +) -> TypResult { let mut seq = Vec::with_capacity(nodes.size_hint().1.unwrap_or_default()); while let Some(node) = nodes.next() { seq.push(match node { MarkupNode::Expr(Expr::Set(set)) => { let styles = set.eval(ctx, scp)?; + if ctx.flow.is_some() { + break; + } + eval_markup(ctx, scp, nodes)?.styled_with_map(styles) } MarkupNode::Expr(Expr::Show(show)) => { let recipe = show.eval(ctx, scp)?; + if ctx.flow.is_some() { + break; + } + eval_markup(ctx, scp, nodes)? .styled_with_entry(StyleEntry::Recipe(recipe).into()) } @@ -88,8 +137,13 @@ fn eval_markup( scp.top.def_mut(wrap.binding().take(), tail); wrap.body().eval(ctx, scp)?.display() } + _ => node.eval(ctx, scp)?, }); + + if ctx.flow.is_some() { + break; + } } Ok(Content::sequence(seq)) @@ -98,7 +152,7 @@ fn eval_markup( impl Eval for MarkupNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(match self { Self::Space => Content::Space, Self::Parbreak => Content::Parbreak, @@ -120,7 +174,7 @@ impl Eval for MarkupNode { impl Eval for StrongNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(Content::show(library::text::StrongNode( self.body().eval(ctx, scp)?, ))) @@ -130,7 +184,7 @@ impl Eval for StrongNode { impl Eval for EmphNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(Content::show(library::text::EmphNode( self.body().eval(ctx, scp)?, ))) @@ -140,7 +194,7 @@ impl Eval for EmphNode { impl Eval for RawNode { type Output = Content; - fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult { let content = Content::show(library::text::RawNode { text: self.text.clone(), block: self.block, @@ -155,7 +209,7 @@ impl Eval for RawNode { impl Eval for MathNode { type Output = Content; - fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult { Ok(Content::show(library::math::MathNode { formula: self.formula.clone(), display: self.display, @@ -166,7 +220,7 @@ impl Eval for MathNode { impl Eval for HeadingNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(Content::show(library::structure::HeadingNode { body: self.body().eval(ctx, scp)?, level: self.level(), @@ -177,7 +231,7 @@ impl Eval for HeadingNode { impl Eval for ListNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(Content::Item(library::structure::ListItem { kind: library::structure::UNORDERED, number: None, @@ -189,7 +243,7 @@ impl Eval for ListNode { impl Eval for EnumNode { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { Ok(Content::Item(library::structure::ListItem { kind: library::structure::ORDERED, number: self.number(), @@ -201,7 +255,14 @@ impl Eval for EnumNode { impl Eval for Expr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { + let forbidden = |name| { + error!( + self.span(), + "{} is only allowed directly in code and content blocks", name + ) + }; + match self { Self::Lit(v) => v.eval(ctx, scp), Self::Ident(v) => v.eval(ctx, scp), @@ -217,11 +278,9 @@ impl Eval for Expr { Self::Unary(v) => v.eval(ctx, scp), Self::Binary(v) => v.eval(ctx, scp), Self::Let(v) => v.eval(ctx, scp), - Self::Set(_) | Self::Show(_) | Self::Wrap(_) => { - Err("set, show and wrap are only allowed directly in markup") - .at(self.span()) - .map_err(Into::into) - } + Self::Set(_) => Err(forbidden("set")), + Self::Show(_) => Err(forbidden("show")), + Self::Wrap(_) => Err(forbidden("wrap")), Self::If(v) => v.eval(ctx, scp), Self::While(v) => v.eval(ctx, scp), Self::For(v) => v.eval(ctx, scp), @@ -237,7 +296,7 @@ impl Eval for Expr { impl Eval for Lit { type Output = Value; - fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult { + fn eval(&self, _: &mut Context, _: &mut Scopes) -> TypResult { Ok(match self.kind() { LitKind::None => Value::None, LitKind::Auto => Value::Auto, @@ -259,7 +318,7 @@ impl Eval for Lit { impl Eval for Ident { type Output = Value; - fn eval(&self, _: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, _: &mut Context, scp: &mut Scopes) -> TypResult { match scp.get(self) { Some(slot) => Ok(slot.read().clone()), None => bail!(self.span(), "unknown variable"), @@ -270,23 +329,75 @@ impl Eval for Ident { impl Eval for CodeBlock { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { scp.enter(); - - let mut output = Value::None; - for expr in self.exprs() { - output = join_result(output, expr.eval(ctx, scp), expr.span())?; - } - + let output = eval_code(ctx, scp, &mut self.exprs())?; scp.exit(); Ok(output) } } +/// Evaluate a stream of expressions. +fn eval_code( + ctx: &mut Context, + scp: &mut Scopes, + exprs: &mut impl Iterator, +) -> TypResult { + let mut output = Value::None; + + while let Some(expr) = exprs.next() { + let span = expr.span(); + let value = match expr { + Expr::Set(set) => { + let styles = set.eval(ctx, scp)?; + if ctx.flow.is_some() { + break; + } + + let tail = to_content(eval_code(ctx, scp, exprs)?).at(span)?; + Value::Content(tail.styled_with_map(styles)) + } + Expr::Show(show) => { + let recipe = show.eval(ctx, scp)?; + let entry = StyleEntry::Recipe(recipe).into(); + if ctx.flow.is_some() { + break; + } + + let tail = to_content(eval_code(ctx, scp, exprs)?).at(span)?; + Value::Content(tail.styled_with_entry(entry)) + } + Expr::Wrap(wrap) => { + let tail = to_content(eval_code(ctx, scp, exprs)?).at(span)?; + scp.top.def_mut(wrap.binding().take(), Value::Content(tail)); + wrap.body().eval(ctx, scp)? + } + + _ => expr.eval(ctx, scp)?, + }; + + output = ops::join(output, value).at(span)?; + + if ctx.flow.is_some() { + break; + } + } + + Ok(output) +} + +/// Extract content from a value. +fn to_content(value: Value) -> StrResult { + let ty = value.type_name(); + value + .cast() + .map_err(|_| format!("expected remaining block to yield content, found {ty}")) +} + impl Eval for ContentBlock { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { scp.enter(); let content = self.body().eval(ctx, scp)?; scp.exit(); @@ -297,7 +408,7 @@ impl Eval for ContentBlock { impl Eval for GroupExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { self.expr().eval(ctx, scp) } } @@ -305,7 +416,7 @@ impl Eval for GroupExpr { impl Eval for ArrayExpr { type Output = Array; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let items = self.items(); let mut vec = Vec::with_capacity(items.size_hint().0); @@ -327,7 +438,7 @@ impl Eval for ArrayExpr { impl Eval for DictExpr { type Output = Dict; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let mut map = BTreeMap::new(); for item in self.items() { @@ -357,7 +468,7 @@ impl Eval for DictExpr { impl Eval for UnaryExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let value = self.expr().eval(ctx, scp)?; let result = match self.op() { UnOp::Pos => ops::pos(value), @@ -371,7 +482,7 @@ impl Eval for UnaryExpr { impl Eval for BinaryExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { match self.op() { BinOp::Add => self.apply(ctx, scp, ops::add), BinOp::Sub => self.apply(ctx, scp, ops::sub), @@ -403,7 +514,7 @@ impl BinaryExpr { ctx: &mut Context, scp: &mut Scopes, op: fn(Value, Value) -> StrResult, - ) -> EvalResult { + ) -> TypResult { let lhs = self.lhs().eval(ctx, scp)?; // Short-circuit boolean operations. @@ -423,7 +534,7 @@ impl BinaryExpr { ctx: &mut Context, scp: &mut Scopes, op: fn(Value, Value) -> StrResult, - ) -> EvalResult { + ) -> TypResult { let rhs = self.rhs().eval(ctx, scp)?; let lhs = self.lhs(); let mut location = lhs.access(ctx, scp)?; @@ -436,7 +547,7 @@ impl BinaryExpr { impl Eval for FieldAccess { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let object = self.object().eval(ctx, scp)?; let span = self.field().span(); let field = self.field().take(); @@ -462,7 +573,7 @@ impl Eval for FieldAccess { impl Eval for FuncCall { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let callee = self.callee().eval(ctx, scp)?; let args = self.args().eval(ctx, scp)?; @@ -486,7 +597,7 @@ impl Eval for FuncCall { impl Eval for MethodCall { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let span = self.span(); let method = self.method(); let point = || Tracepoint::Call(Some(method.to_string())); @@ -507,7 +618,7 @@ impl Eval for MethodCall { impl Eval for CallArgs { type Output = Args; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let mut items = Vec::new(); for arg in self.items() { @@ -559,7 +670,7 @@ impl Eval for CallArgs { impl Eval for ClosureExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { // The closure's name is defined by its let binding if there's one. let name = self.name().map(Ident::take); @@ -606,7 +717,7 @@ impl Eval for ClosureExpr { impl Eval for LetExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let value = match self.init() { Some(expr) => expr.eval(ctx, scp)?, None => Value::None, @@ -619,7 +730,7 @@ impl Eval for LetExpr { impl Eval for SetExpr { type Output = StyleMap; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let target = self.target(); let target = target.eval(ctx, scp)?.cast::().at(target.span())?; let args = self.args().eval(ctx, scp)?; @@ -630,7 +741,7 @@ impl Eval for SetExpr { impl Eval for ShowExpr { type Output = Recipe; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { // Evaluate the target function. let pattern = self.pattern(); let pattern = pattern.eval(ctx, scp)?.cast::().at(pattern.span())?; @@ -666,7 +777,7 @@ impl Eval for ShowExpr { impl Eval for IfExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let condition = self.condition(); if condition.eval(ctx, scp)?.cast::().at(condition.span())? { self.if_body().eval(ctx, scp) @@ -681,19 +792,23 @@ impl Eval for IfExpr { impl Eval for WhileExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let mut output = Value::None; let condition = self.condition(); while condition.eval(ctx, scp)?.cast::().at(condition.span())? { let body = self.body(); - match join_result(output, body.eval(ctx, scp), body.span()) { - Err(Control::Break(value, _)) => { - output = value; + let value = body.eval(ctx, scp)?; + output = ops::join(output, value).at(body.span())?; + + match ctx.flow { + Some(Flow::Break(_)) => { + ctx.flow = None; break; } - Err(Control::Continue(value, _)) => output = value, - other => output = other?, + Some(Flow::Continue(_)) => ctx.flow = None, + Some(Flow::Return(..)) => break, + None => {} } } @@ -704,7 +819,7 @@ impl Eval for WhileExpr { impl Eval for ForExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { macro_rules! iter { (for ($($binding:ident => $value:ident),*) in $iter:expr) => {{ let mut output = Value::None; @@ -715,13 +830,17 @@ impl Eval for ForExpr { $(scp.top.def_mut(&$binding, $value);)* let body = self.body(); - match join_result(output, body.eval(ctx, scp), body.span()) { - Err(Control::Break(value, _)) => { - output = value; + let value = body.eval(ctx, scp)?; + output = ops::join(output, value).at(body.span())?; + + match ctx.flow { + Some(Flow::Break(_)) => { + ctx.flow = None; break; } - Err(Control::Continue(value, _)) => output = value, - other => output = other?, + Some(Flow::Continue(_)) => ctx.flow = None, + Some(Flow::Return(..)) => break, + None => {} } } @@ -773,7 +892,7 @@ impl Eval for ForExpr { impl Eval for ImportExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let span = self.path().span(); let path = self.path().eval(ctx, scp)?.cast::().at(span)?; let module = import(ctx, &path, span)?; @@ -802,7 +921,7 @@ impl Eval for ImportExpr { impl Eval for IncludeExpr { type Output = Content; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let span = self.path().span(); let path = self.path().eval(ctx, scp)?.cast::().at(span)?; let module = import(ctx, &path, span)?; @@ -833,30 +952,34 @@ fn import(ctx: &mut Context, path: &str, span: Span) -> TypResult { impl Eval for BreakExpr { type Output = Value; - fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult { - Err(Control::Break(Value::default(), self.span())) + fn eval(&self, ctx: &mut Context, _: &mut Scopes) -> TypResult { + if ctx.flow.is_none() { + ctx.flow = Some(Flow::Break(self.span())); + } + Ok(Value::None) } } impl Eval for ContinueExpr { type Output = Value; - fn eval(&self, _: &mut Context, _: &mut Scopes) -> EvalResult { - Err(Control::Continue(Value::default(), self.span())) + fn eval(&self, ctx: &mut Context, _: &mut Scopes) -> TypResult { + if ctx.flow.is_none() { + ctx.flow = Some(Flow::Continue(self.span())); + } + Ok(Value::None) } } impl Eval for ReturnExpr { type Output = Value; - fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> EvalResult { + fn eval(&self, ctx: &mut Context, scp: &mut Scopes) -> TypResult { let value = self.body().map(|body| body.eval(ctx, scp)).transpose()?; - let explicit = value.is_some(); - Err(Control::Return( - value.unwrap_or_default(), - explicit, - self.span(), - )) + if ctx.flow.is_none() { + ctx.flow = Some(Flow::Return(self.span(), value)); + } + Ok(Value::None) } } @@ -867,7 +990,7 @@ pub trait Access { &self, ctx: &mut Context, scp: &'a mut Scopes, - ) -> EvalResult>; + ) -> TypResult>; } impl Access for Expr { @@ -875,7 +998,7 @@ impl Access for Expr { &self, ctx: &mut Context, scp: &'a mut Scopes, - ) -> EvalResult> { + ) -> TypResult> { match self { Expr::Ident(ident) => ident.access(ctx, scp), Expr::FuncCall(call) => call.access(ctx, scp), @@ -889,7 +1012,7 @@ impl Access for Ident { &self, _: &mut Context, scp: &'a mut Scopes, - ) -> EvalResult> { + ) -> TypResult> { match scp.get(self) { Some(slot) => match slot.try_write() { Some(guard) => Ok(RwLockWriteGuard::map(guard, |v| v)), @@ -905,7 +1028,7 @@ impl Access for FuncCall { &self, ctx: &mut Context, scp: &'a mut Scopes, - ) -> EvalResult> { + ) -> TypResult> { let args = self.args().eval(ctx, scp)?; let guard = self.callee().access(ctx, scp)?; try_map(guard, |value| { @@ -928,9 +1051,9 @@ impl Access for FuncCall { type Location<'a> = MappedRwLockWriteGuard<'a, Value>; /// Map a reader-writer lock with a function. -fn try_map(location: Location, f: F) -> EvalResult +fn try_map(location: Location, f: F) -> TypResult where - F: FnOnce(&mut Value) -> EvalResult<&mut Value>, + F: FnOnce(&mut Value) -> TypResult<&mut Value>, { let mut error = None; MappedRwLockWriteGuard::try_map(location, |value| match f(value) { diff --git a/src/eval/module.rs b/src/eval/module.rs deleted file mode 100644 index d2b4c520f..000000000 --- a/src/eval/module.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::Scope; -use crate::model::Content; -use crate::source::{SourceId, SourceStore}; - -/// An evaluated module, ready for importing or layouting. -#[derive(Debug, Clone)] -pub struct Module { - /// The top-level definitions that were bound in this module. - pub scope: Scope, - /// The module's layoutable contents. - pub content: Content, - /// The source file revisions this module depends on. - pub deps: Vec<(SourceId, usize)>, -} - -impl Module { - /// Whether the module is still valid for the given sources. - pub fn valid(&self, sources: &SourceStore) -> bool { - self.deps.iter().all(|&(id, rev)| rev == sources.get(id).rev()) - } -} diff --git a/src/eval/value.rs b/src/eval/value.rs index dd1839269..8096721e8 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -102,11 +102,6 @@ impl Value { T::cast(self) } - /// Join the value with another value. - pub fn join(self, rhs: Self) -> StrResult { - ops::join(self, rhs) - } - /// Return the debug representation of the value. pub fn repr(&self) -> EcoString { format_eco!("{:?}", self) diff --git a/src/lib.rs b/src/lib.rs index 0edaeb99c..efddc239b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,7 +58,7 @@ use std::path::PathBuf; use std::sync::Arc; use crate::diag::TypResult; -use crate::eval::{Eval, Module, Scope, Scopes}; +use crate::eval::{Eval, Flow, Module, Scope, Scopes}; use crate::font::FontStore; use crate::frame::Frame; use crate::image::ImageStore; @@ -88,6 +88,8 @@ pub struct Context { route: Vec, /// The dependencies of the current evaluation process. deps: Vec<(SourceId, usize)>, + /// A control flow event that is currently happening. + flow: Option, } impl Context { @@ -145,10 +147,16 @@ impl Context { let content = ast.eval(self, &mut scp); self.route.pop().unwrap(); let deps = std::mem::replace(&mut self.deps, prev); + let flow = self.flow.take(); // Assemble the module. let module = Module { scope: scp.top, content: content?, deps }; + // Handle unhandled flow. + if let Some(flow) = flow { + return Err(flow.forbidden()); + } + // Save the evaluated module. self.modules.insert(id, module.clone()); @@ -213,6 +221,7 @@ impl ContextBuilder { cache: HashMap::new(), route: vec![], deps: vec![], + flow: None, } } } diff --git a/src/parse/mod.rs b/src/parse/mod.rs index 86d18cbac..4ef1c96f2 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -246,7 +246,10 @@ fn markup_node(p: &mut Parser, at_start: &mut bool) { | NodeKind::While | NodeKind::For | NodeKind::Import - | NodeKind::Include => markup_expr(p), + | NodeKind::Include + | NodeKind::Break + | NodeKind::Continue + | NodeKind::Return => markup_expr(p), // Code and content block. NodeKind::LeftBrace => code_block(p), @@ -965,7 +968,7 @@ fn continue_expr(p: &mut Parser) -> ParseResult { fn return_expr(p: &mut Parser) -> ParseResult { p.perform(NodeKind::ReturnExpr, |p| { p.assert(NodeKind::Return); - if !p.eof() { + if !p.at(NodeKind::Comma) && !p.eof() { expr(p)?; } Ok(()) diff --git a/tests/ref/code/break-continue.png b/tests/ref/code/break-continue.png new file mode 100644 index 0000000000000000000000000000000000000000..848f4fa60acff7bfad46b6326ec8395ea8873c76 GIT binary patch literal 5885 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 literal 12397 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 JyAVi(9j93H|snJ3IUL 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 s?0@4=>Qj3>vpueJnHA~ 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 Vw`1^N<%1ot$l3y9UT*3h^DpEt(`Enw literal 17385 zcmb`v1yq!6w?B-6h&sTaB8(z1bVv=|jg+*2NC*rdpdcX9AdPf)3Q{6SskC%SC?E|I zN~(0nw|U-goqwHk{_nTe$MRXr;hCBHzOQRvd+%RtU#Y3wCA@s|G7b(7p@O`O1`f_S zJovAX;5_^WM^!@)2S@t7f{dh=^Vsh+7hUBQs?XC4X-T&=GxQ=o5|l67KT%b z9{gzZ4J)J*6s)R`_|*|bi|wwgsJOwVhv$8Aif-=DlD?;`+_K4UGr`2hHu>S{c&TZ- zqDEg=9P9W;TO)maDSk?#|PWe1Ywk-)o}mnn4|S}DjO3S z8JS44-ZbHMlhUaMFXGav2{Qsh!dCJI*KI|2od`-%2Ia)}Pew6(DQPJwhpi{2si_n7 z9*6l98u``Z2NB6ZCzDdA{y?n&mIH#ajgYY)Gjz-}XbYpLC@r;Sb;SMi9f1s}IAB^sU2gfIee`ohgj2ha=Geq5X zM$0Y8=b8hF`Sl|{e&i2n?dt5z>VC;}Bf)sI%#3`FQ8iuO`QfATQO!IR(rL%7#jmel z(^xs|Z~SaHIauNEl0f<;B_$OVJ<-$CyVmvIdYGLkP*YnQe`dG%gnM@Q1> zpY!u{92}}U($&wGOddZTd3HaB;U0#MFLz;((YLaaw@tU{@#fBs9Ki*Ae9zK(2s#p} zz6|kGIh2pDFNxIQ?q6FeREG%}hoRpy+j>k+P7bx-`Sa&noGh)ZG&FhG+1U~Jw7k5P z-i188ya{(6e0z_O%39m`Jr3a$y^H$(?qMME^}#gZ=ec#xw)ywl53xbv;c^6{V`F?- z2s}w97M9|NABmdk_Pf^RJFofmms|A7Y*2|fOEg47WD}Xznzo1I7e>d&PgPncd_p|o zOWC{x;TpOwetJZUB%u4-iuQ|+iJ@nnsCKmO#4Q#>LC7MdG;@`s^zk8HZA^kYxBE@ACXeF z)AesGF5~$?oWEG?_dfZ$ytw!%)YQaexhSx2ftx&3I*>>KV=mx%Bp@Z9^UR~@K{-D9 zItsvm-}2BVN|EKUu14B!*TBE zxNQU4Z<)d>rsC;%eDdNGXDeP-)+=b9r(-+{dW%a-uaL0i(R4BAp76mFPEIpPtEnNS z0gZw}s=IXXHP5GG-y%#WGq=6r8#7P@W?~ zzEM#m9yWQkwfgGnc1L^bv-FT-ZY9>}mz#$rCnwW6;S&=R`yneu7?A|UMh#P+l~=wb zal^T{nXbRrC*t&n!nZNAB;3WtML|hPb7dNfdo$6JG(nQ-y3JHA%Cy#Mh=rxRqGD@# z=qsk5{5%a_njEbNk61mkVt7YOtqgy4Z*Vq|3IyLUY%rB9wdt*fmKrxLd@Hg3dX zE)w39@uD7_r`>vB+ICk%Lt{C{yA!MNw7jfrd8$rWssp~xCN?JKn$+Vaze|K2oX>tp zSa3mxRwO+<{M!IKL3oyhI(mBUYiPXAy~lRvPHbG<(pQN*i@x-R;E~)KpF>yw=(&d`~-c-eqQ<<*w>WkW$PsNeLWAx%S@% z2H?cs)SWzBDQQ?F9Qgh{UBspA%EFqC@uknw-}-=pFU+1 zo1WIaeC3K67E7leSse4A+}!c+ltEJgHge`-x0vf_j2HZq#FE$Nz?nrdy8wI_zmbi{UwBD;2t+w;hI{pQY}$;02GF{!B( z*48U~dwV6qBDA!o8}pqyC5HY?r(V(jR^diLfyY9Hhcb_XI*)}y|F2*CpKZa}Z}!li z&x_$in7%~dbl_lcsBt@RULvS*aWMb;FW@!&e|QtT2j23Zyja_&V`RK5BXj-6jiz>D zp1Ua5twnESvY5vKnNn{GziJNZonGa);o%04!xzmLp*W9?juzzS|A>HE`RW=Y0|SE; z67od=JTBUAaA-)7f+(UrMke6?TkR?jlg?;*78Vv|hRx0x#_ij!bL(5%+gxpsE!VfU z5SK6O)w@^K*1880-HwiqrY3s%i^exQJG-{_D2`Q!vn@|GBVHx|R@N>JN>Ir`_*j(# zqtxT!VuP(OYirLQJQ!ux%$1

5;`JBqY3YC+QH&za|R~#v47Zw7M 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 VxoEuU-G27}6=YRpilrX;{6C{|*kS+x diff --git a/tests/typ/code/break-continue.typ b/tests/typ/code/break-continue.typ index 60dac44d3..02c221a47 100644 --- a/tests/typ/code/break-continue.typ +++ b/tests/typ/code/break-continue.typ @@ -66,13 +66,28 @@ --- // Test break outside of loop. - #let f() = { // Error: 3-8 cannot break outside of loop break } -#f() +#for i in range(1) { + f() +} + +--- +// Test break in function call. +#let identity(x) = x +#let out = for i in range(5) { + "A" + identity({ + "B" + break + }) + "C" +} + +#test(out, "AB") --- // Test continue outside of loop. @@ -81,5 +96,41 @@ #let x = { continue } --- -// Error: 1-10 unexpected keyword `continue` +// Error: 1-10 cannot continue outside of loop #continue + +--- +// Ref: true +// Should output `Hello World 🌎`. +#for _ in range(10) { + [Hello ] + [World { + [🌎] + break + }] +} + +--- +// Ref: true +// Should output `Some` in red, `Some` in blue and `Last` in green. +// Everything should be in smallcaps. +#for color in (red, blue, green, yellow) [ + #set text("Roboto") + #wrap body in text(fill: color, body) + #smallcaps(if color != green [ + Some + ] else [ + Last + #break + ]) +] + +--- +// Ref: true +// Test break in set rule. +// Should output `Hi` in blue. +#for i in range(10) { + [Hello] + set text(blue, ..break) + [Not happening] +} diff --git a/tests/typ/code/return.typ b/tests/typ/code/return.typ index d30164447..8db99a813 100644 --- a/tests/typ/code/return.typ +++ b/tests/typ/code/return.typ @@ -35,10 +35,7 @@ #let f(text, caption: none) = { text - if caption == none { - [\.] - return - } + if caption == none [\.#return] [, ] emph(caption) [\.] @@ -55,3 +52,33 @@ // Error: 3-9 cannot return outside of function return } + +--- +// Test that the expression is evaluated to the end. +#let y = 1 +#let identity(x, ..rest) = x +#let f(x) = { + identity( + ..return, + x + 1, + y = 2, + ) + "nope" +} + +#test(f(1), 2) +#test(y, 2) + +--- +// Test value return from content. +#let x = 3 +#let f() = [ + Hello 😀 + { x = 1 } + #return "nope" + { x = 2 } + World +] + +#test(f(), "nope") +#test(x, 1) diff --git a/tests/typ/style/set.typ b/tests/typ/style/set.typ index 249666126..2c12d3e97 100644 --- a/tests/typ/style/set.typ +++ b/tests/typ/style/set.typ @@ -27,5 +27,15 @@ Hello *{x}* #text(fill: forest, x) --- -// Error: 2-10 set, show and wrap are only allowed directly in markup -{set f(x)} +// Test that scoping works as expected. +{ + if true { + set text(blue) + [Blue ] + } + [Not blue] +} + +--- +// Error: 11-25 set is only allowed directly in code and content blocks +{ let x = set text(blue) } diff --git a/tests/typ/style/show-node.typ b/tests/typ/style/show-node.typ index d0586c9d4..678ff1513 100644 --- a/tests/typ/style/show-node.typ +++ b/tests/typ/style/show-node.typ @@ -48,6 +48,33 @@ Some more text. = Task 2 Another text. +--- +// Test set and show in code blocks. +#show node: heading as { + set text(red) + show "ding" as [🛎] + node.body +} + += Heading + +--- +// Test that scoping works as expected. +{ + let world = [ World ] + show c: "W" as strong(c) + world + { + set text(blue) + wrap it in { + show "o" as "Ø" + it + } + world + } + world +} + --- // Error: 18-22 expected content, found integer #show heading as 1234 @@ -67,5 +94,5 @@ Another text. #show red as [] --- -// Error: 2-16 set, show and wrap are only allowed directly in markup -{show list as a} +// Error: 7-27 show is only allowed directly in code and content blocks +{ 1 + show heading as none } diff --git a/tests/typ/style/wrap.typ b/tests/typ/style/wrap.typ index 2a9074cb0..57f21f996 100644 --- a/tests/typ/style/wrap.typ +++ b/tests/typ/style/wrap.typ @@ -25,5 +25,12 @@ A [_B #wrap c in [*#c*]; C_] D Forest --- -// Error: 6-17 set, show and wrap are only allowed directly in markup -{1 + wrap x in y} +{ + // Error: 3-24 expected remaining block to yield content, found integer + wrap body in 2 * body + 2 +} + +--- +// Error: 4-18 wrap is only allowed directly in code and content blocks +{ (wrap body in 2) * body }