Skip to content

Commit

Permalink
Improve filters
Browse files Browse the repository at this point in the history
- Fix long standing bug with owned value being passed to a filter arg
  that is a reference.

- Prepare compiler and renderer to handle computed arguments. This is
  required for list and map literals.

- Simplify filter code by implementing the piped value and the arguments
  in the same way. These are all now converted from a `&mut ValueCow`.

- Clarify lifetimes of args vs stack in filters implementation.
  • Loading branch information
rossmacarthur committed Jan 10, 2025
1 parent 97f862e commit cbc56d5
Show file tree
Hide file tree
Showing 9 changed files with 465 additions and 388 deletions.
34 changes: 21 additions & 13 deletions src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub use crate::compile::search::Searcher;

use crate::types::ast;
use crate::types::program::{Instr, Template, FIXME};
use crate::types::span::Span;
use crate::{Engine, Result};

/// Compile a template into a program.
Expand Down Expand Up @@ -60,9 +59,8 @@ impl Compiler {
}

ast::Stmt::InlineExpr(ast::InlineExpr { expr, .. }) => {
let span = expr.span();
self.compile_expr(expr);
self.pop_emit_expr(span);
self.pop_emit_expr();
}

ast::Stmt::Include(ast::Include { name, globals }) => match globals {
Expand Down Expand Up @@ -139,35 +137,45 @@ impl Compiler {
name,
args,
receiver,
..
span,
}) => {
self.compile_expr(*receiver);
self.push(Instr::Apply(name, args));
let arity = match args {
None => 0,
Some(args) => {
let arity = args.values.len();
for arg in args.values {
self.compile_base_expr(arg);
}
arity
}
};
self.push(Instr::Apply(name, arity, span));
}
}
}

fn compile_base_expr(&mut self, base_expr: ast::BaseExpr) {
match base_expr {
ast::BaseExpr::Var(var) => {
self.push(Instr::ExprStart(var));
self.push(Instr::ExprStartVar(var));
}
ast::BaseExpr::Literal(ast::Literal { value, .. }) => {
self.push(Instr::ExprStartLit(value));
ast::BaseExpr::Literal(literal) => {
self.push(Instr::ExprStartLiteral(literal));
}
}
}

fn pop_emit_expr(&mut self, span: Span) {
let emit = match self.instrs.last() {
Some(Instr::Apply(_, None)) => {
fn pop_emit_expr(&mut self) {
let emit = match self.instrs.last_mut() {
Some(Instr::Apply(_, _, _)) => {
let instr = self.instrs.pop().unwrap();
match instr {
Instr::Apply(ident, _) => Instr::EmitWith(ident, span),
Instr::Apply(ident, len, span) => Instr::EmitWith(ident, len, span),
_ => unreachable!(),
}
}
_ => Instr::Emit(span),
_ => Instr::Emit,
};
self.push(emit);
}
Expand Down
11 changes: 11 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ impl Error {
}
}

/// Constructs a new render error without pretty information.
#[cfg(feature = "filters")]
pub(crate) fn render_plain(reason: impl Into<String>) -> Self {
Self {
kind: ErrorKind::Render,
name: None,
reason: Some(reason.into()),
pretty: None,
}
}

/// Constructs a max include depth error.
pub(crate) fn max_include_depth(max: usize) -> Self {
Self {
Expand Down
Loading

0 comments on commit cbc56d5

Please sign in to comment.