@@ -307,4 +307,113 @@ void ExtendsStatement::Render(OutStream& os, RenderContext& values)
307
307
renderer->Render (os, values);
308
308
}
309
309
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
+
310
419
} // jinja2
0 commit comments