Skip to main content

Module fold

Module fold 

Source
Expand description

Arena-to-arena AST transformation via the Fold trait.

§Overview

Fold is the transformation counterpart of crate::visitor::Visitor. Where Visitor walks a tree read-only, Fold rebuilds it — reading from an input node (in any arena '_) and writing into a caller-supplied output arena 'new. This is the only sound design for arena-allocated ASTs: in-place mutation (VisitorMut) would let you write a &'new Expr into a slot that requires a &'old Expr, silently breaking the arena lifetime invariant.

§Lifetimes

  • 'src — the source-text lifetime, bound on the Fold trait. &'src str slices that point directly into the original PHP source are passed through unchanged across the fold; they are never re-allocated.
  • 'new — the output arena lifetime; a generic on each method so one impl Fold<'src> can fold into different arenas over its lifetime.
  • '_ — the input arena lifetime, intentionally erased. The fold never reads back through output-arena pointers, so the input and output arenas are fully independent.

§Arena-allocated strings

Several AST nodes store &'arena str values that were not borrowed from the source buffer — for example string literals, StmtKind::Label, and ExprKind::Nowdoc values. The identity fold re-allocates these via arena.alloc_str(s) so the output nodes are self-contained within the new arena. Source-borrowed NameStr values (NameStr::__src) are preserved as-is without copying.

§Usage

use bumpalo::Bump;
use php_ast::fold::{Fold, fold_program};
use php_ast::ast::*;

/// An identity fold — rebuilds the AST without changes.
struct Identity;
impl<'src> Fold<'src> for Identity {}

// Fold `program` (in `src_arena`) into `out_arena`:
// let folded = Identity.fold_program(&out_arena, &program);

To transform specific nodes, override the corresponding method and call the free fold_* function for the default recursion:

use bumpalo::Bump;
use php_ast::fold::{Fold, fold_expr};
use php_ast::ast::*;

struct NegateInts;

impl<'src> Fold<'src> for NegateInts {
    fn fold_expr<'new>(&mut self, arena: &'new Bump, expr: &Expr<'_, 'src>) -> Expr<'new, 'src> {
        if let ExprKind::Int(n) = expr.kind {
            return Expr { kind: ExprKind::Int(-n), span: expr.span };
        }
        fold_expr(self, arena, expr)
    }
}

Traits§

Fold
Trait for arena-to-arena PHP AST transformation.

Functions§

fold_arg
Folds a call argument.
fold_attribute
Folds an attribute.
fold_block
Folds a block of statements.
fold_catch_clause
Folds a catch clause.
fold_class_member
Folds a class-like member.
fold_enum_member
Folds an enum member.
fold_expr
Folds an expression.
fold_match_arm
Folds a match arm.
fold_name
Folds a name reference.
fold_name_str
Copies a name string into the new arena.
fold_param
Folds a function parameter.
fold_program
Folds the root program node.
fold_property_hook
Folds a property hook.
fold_stmt
Folds a statement.
fold_trait_adaptation
Folds a trait insteadof/as adaptation.
fold_trait_use
Folds a use Trait; declaration.
fold_type_hint
Folds a type hint.