@@ -307,4 +307,113 @@ void ExtendsStatement::Render(OutStream& os, RenderContext& values)
307307 renderer->Render (os, values);
308308}
309309
310+ void MacroStatement::PrepareMacroParams (RenderContext& values)
311+ {
312+ for (auto & p : m_params)
313+ {
314+ ArgumentInfo info (p.paramName , !p.defaultValue );
315+ if (p.defaultValue )
316+ info.defaultVal = p.defaultValue ->Evaluate (values);
317+ m_preparedParams.push_back (std::move (info));
318+ }
319+ }
320+
321+ void MacroStatement::Render (OutStream& os, RenderContext& values)
322+ {
323+ PrepareMacroParams (values);
324+
325+ values.GetCurrentScope ()[m_name] = Callable ([this ](const CallParams& callParams, OutStream& stream, RenderContext& context) {
326+ InvokeMacroRenderer (callParams, stream, context);
327+ });
328+ }
329+
330+ void MacroStatement::InvokeMacroRenderer (const CallParams& callParams, OutStream& stream, RenderContext& context)
331+ {
332+ InternalValueMap callArgs;
333+ InternalValueMap kwArgs;
334+ InternalValueList varArgs;
335+
336+ SetupCallArgs (m_preparedParams, callParams, context, callArgs, kwArgs, varArgs);
337+ InternalValueList arguments;
338+ InternalValueList defaults;
339+ for (auto & a : m_preparedParams)
340+ {
341+ arguments.emplace_back (a.name );
342+ defaults.emplace_back (a.defaultVal );
343+ }
344+
345+ auto & scope = context.EnterScope ();
346+ for (auto & a : callArgs)
347+ scope[a.first ] = std::move (a.second );
348+
349+ scope[" kwargs" ] = MapAdapter::CreateAdapter (std::move (kwArgs));
350+ scope[" varargs" ] = ListAdapter::CreateAdapter (std::move (varArgs));
351+
352+ scope[" name" ] = m_name;
353+ scope[" arguments" ] = ListAdapter::CreateAdapter (std::move (arguments));
354+ scope[" defaults" ] = ListAdapter::CreateAdapter (std::move (defaults));
355+
356+ m_mainBody->Render (stream, context);
357+
358+ context.ExitScope ();
359+ }
360+
361+ void MacroStatement::SetupCallArgs (const std::vector<ArgumentInfo>& argsInfo, const CallParams& callParams, RenderContext& context, InternalValueMap& callArgs, InternalValueMap& kwArgs, InternalValueList& varArgs)
362+ {
363+ bool isSucceeded = true ;
364+ ParsedArguments args = helpers::ParseCallParams (argsInfo, callParams, isSucceeded);
365+
366+ for (auto & a : args.args )
367+ callArgs[a.first ] = a.second ->Evaluate (context);
368+
369+ for (auto & a : args.extraKwArgs )
370+ kwArgs[a.first ] = a.second ->Evaluate (context);
371+
372+ for (auto & a : args.extraPosArgs )
373+ varArgs.push_back (a->Evaluate (context));
374+ }
375+
376+ void MacroStatement::SetupMacroScope (InternalValueMap& scope)
377+ {
378+ ;
379+ }
380+
381+ void MacroCallStatement::Render (OutStream& os, RenderContext& values)
382+ {
383+ bool isMacroFound = false ;
384+ auto macroPtr = values.FindValue (m_macroName, isMacroFound);
385+ if (!isMacroFound)
386+ return ;
387+
388+ auto & fnVal = macroPtr->second ;
389+ const Callable* callable = boost::get<Callable>(&fnVal);
390+ if (callable == nullptr || callable->GetType () == Callable::Type::Expression)
391+ return ;
392+
393+ PrepareMacroParams (values);
394+ auto & curScope = values.GetCurrentScope ();
395+ auto callerP = curScope.find (" caller" );
396+ bool hasCallerVal = callerP != curScope.end ();
397+ InternalValue prevCaller;
398+ if (hasCallerVal)
399+ prevCaller = callerP->second ;
400+
401+ curScope[" caller" ] = Callable ([this ](const CallParams& callParams, OutStream& stream, RenderContext& context) {
402+ InvokeMacroRenderer (callParams, stream, context);
403+ });
404+
405+ callable->GetStatementCallable ()(m_callParams, os, values);
406+
407+ if (hasCallerVal)
408+ curScope[" caller" ] = prevCaller;
409+ else
410+ values.GetCurrentScope ().erase (" caller" );
411+ }
412+
413+ void MacroCallStatement::SetupMacroScope (InternalValueMap& scope)
414+ {
415+
416+ }
417+
418+
310419} // jinja2
0 commit comments