summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-16 17:56:23 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-16 17:56:36 +0200
commita741bd6b83d1e374c8218b5439e26522499cc4ae (patch)
tree796ef8b8ae2186a082f37a2aa4732c9bba7d2bdf /src/eval
parent6536e9e069616b862ebb774c7bef1b886c069350 (diff)
Absolute paths
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/func.rs21
-rw-r--r--src/eval/mod.rs8
2 files changed, 23 insertions, 6 deletions
diff --git a/src/eval/func.rs b/src/eval/func.rs
index 4c5761ab..f15b0241 100644
--- a/src/eval/func.rs
+++ b/src/eval/func.rs
@@ -5,6 +5,7 @@ use std::sync::Arc;
use super::{Args, Eval, Flow, Scope, Scopes, Value};
use crate::diag::{StrResult, TypResult};
use crate::model::{Content, NodeId, StyleMap};
+use crate::source::SourceId;
use crate::syntax::ast::Expr;
use crate::util::EcoString;
use crate::Context;
@@ -174,6 +175,8 @@ pub trait Node: 'static {
/// A user-defined closure.
#[derive(Hash)]
pub struct Closure {
+ /// The location where the closure was defined.
+ pub location: Option<SourceId>,
/// The name of the closure.
pub name: Option<EcoString>,
/// Captured values from outer scopes.
@@ -212,18 +215,28 @@ impl Closure {
// Backup the old control flow state.
let prev_flow = ctx.flow.take();
+ let detached = ctx.route.is_empty();
+ if detached {
+ ctx.route = self.location.into_iter().collect();
+ }
// Evaluate the body.
- let mut value = self.body.eval(ctx, &mut scp)?;
+ let result = self.body.eval(ctx, &mut scp);
+
+ // Restore the old control flow state.
+ let flow = std::mem::replace(&mut ctx.flow, prev_flow);
+ if detached {
+ ctx.route.clear();
+ }
// Handle control flow.
- match std::mem::replace(&mut ctx.flow, prev_flow) {
- Some(Flow::Return(_, Some(explicit))) => value = explicit,
+ match flow {
+ Some(Flow::Return(_, Some(explicit))) => return Ok(explicit),
Some(Flow::Return(_, None)) => {}
Some(flow) => return Err(flow.forbidden())?,
None => {}
}
- Ok(value)
+ result
}
}
diff --git a/src/eval/mod.rs b/src/eval/mod.rs
index b35cf1ef..79060137 100644
--- a/src/eval/mod.rs
+++ b/src/eval/mod.rs
@@ -707,6 +707,7 @@ impl Eval for ClosureExpr {
// Define the actual function.
Ok(Value::Func(Func::from_closure(Closure {
+ location: ctx.route.last().copied(),
name,
captured,
params,
@@ -765,6 +766,7 @@ impl Eval for ShowExpr {
let body = self.body();
let span = body.span();
let func = Func::from_closure(Closure {
+ location: ctx.route.last().copied(),
name: None,
captured,
params,
@@ -945,9 +947,11 @@ impl Eval for IncludeExpr {
/// Process an import of a module relative to the current location.
fn import(ctx: &mut Context, path: &str, span: Span) -> TypResult<Module> {
// Load the source file.
- let full = ctx.complete_path(path);
+ let full = ctx.locate(&path).at(span)?;
let id = ctx.sources.load(&full).map_err(|err| match err.kind() {
- std::io::ErrorKind::NotFound => error!(span, "file not found"),
+ std::io::ErrorKind::NotFound => {
+ error!(span, "file not found (searched at {})", full.display())
+ }
_ => error!(span, "failed to load source file ({})", err),
})?;