execute method

  1. @override
JinjaValue execute(
  1. Context ctx
)
override

Executes the statement within the given ctx and returns the result as a JinjaValue.

Implementation

@override
JinjaValue execute(Context ctx) {
  // A 'call' block is equivalent to calling the target function/macro
  // with an additional keyword argument named 'caller', which is itself
  // a macro that renders the body of the call block.

  final callerMacro = JinjaFunction('caller', (callArgs, callKwargs) {
    final callerCtx = ctx.derive();
    _bindParameters(
      'caller',
      callerArgs,
      callArgs,
      callKwargs,
      callerCtx,
      ctx,
    );
    return _execCaptured(body, callerCtx);
  });

  final callExpr = call;
  // We need to execute the call expression but inject the 'caller' kwarg.
  // Instead of executing callExpr directly, we manually resolve the callee
  // and invoke it with the combined arguments.

  final callee = callExpr.callee.execute(ctx);
  if (callee is! JinjaFunction) {
    throw Exception('Callee must be a function/macro');
  }

  final args = callExpr.args
      .where((a) => a is! KeywordArgumentExpression)
      .map((a) => a.execute(ctx))
      .toList();
  final kwargs = <String, JinjaValue>{};
  for (final arg in callExpr.args.whereType<KeywordArgumentExpression>()) {
    kwargs[(arg.key as Identifier).name] = arg.val.execute(ctx);
  }

  // Inject caller
  kwargs['caller'] = callerMacro;

  return callee.handler(args, kwargs);
}