MCPcopy Create free account
hub / github.com/FastFlowLM/FastFlowLM / do_render

Method do_render

src/include/minja/minja.hpp:975–1049  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

973 : TemplateNode(loc), var_names(var_names), iterable(std::move(iterable)), condition(std::move(condition)), body(std::move(body)), recursive(recursive), else_body(std::move(else_body)) {}
974
975 void do_render(std::ostringstream & out, const std::shared_ptr<Context> & context) const override {
976 // https://jinja.palletsprojects.com/en/3.0.x/templates/#for
977 if (!iterable) throw std::runtime_error("ForNode.iterable is null");
978 if (!body) throw std::runtime_error("ForNode.body is null");
979
980 auto iterable_value = iterable->evaluate(context);
981 Value::CallableType loop_function;
982
983 std::function<void(Value&)> visit = [&](Value& iter) {
984 auto filtered_items = Value::array();
985 if (!iter.is_null()) {
986 if (!iterable_value.is_iterable()) {
987 throw std::runtime_error("For loop iterable must be iterable: " + iterable_value.dump());
988 }
989 iterable_value.for_each([&](Value & item) {
990 destructuring_assign(var_names, context, item);
991 if (!condition || condition->evaluate(context).to_bool()) {
992 filtered_items.push_back(item);
993 }
994 });
995 }
996 if (filtered_items.empty()) {
997 if (else_body) {
998 else_body->render(out, context);
999 }
1000 } else {
1001 auto loop = recursive ? Value::callable(loop_function) : Value::object();
1002 loop.set("length", (int64_t) filtered_items.size());
1003
1004 size_t cycle_index = 0;
1005 loop.set("cycle", Value::callable([&](const std::shared_ptr<Context> &, ArgumentsValue & args) {
1006 if (args.args.empty() || !args.kwargs.empty()) {
1007 throw std::runtime_error("cycle() expects at least 1 positional argument and no named arg");
1008 }
1009 auto item = args.args[cycle_index];
1010 cycle_index = (cycle_index + 1) % args.args.size();
1011 return item;
1012 }));
1013 auto loop_context = Context::make(Value::object(), context);
1014 loop_context->set("loop", loop);
1015 for (size_t i = 0, n = filtered_items.size(); i < n; ++i) {
1016 auto & item = filtered_items.at(i);
1017 destructuring_assign(var_names, loop_context, item);
1018 loop.set("index", (int64_t) i + 1);
1019 loop.set("index0", (int64_t) i);
1020 loop.set("revindex", (int64_t) (n - i));
1021 loop.set("revindex0", (int64_t) (n - i - 1));
1022 loop.set("length", (int64_t) n);
1023 loop.set("first", i == 0);
1024 loop.set("last", i == (n - 1));
1025 loop.set("previtem", i > 0 ? filtered_items.at(i - 1) : Value());
1026 loop.set("nextitem", i < n - 1 ? filtered_items.at(i + 1) : Value());
1027 try {
1028 body->render(out, loop_context);
1029 } catch (const LoopControlException & e) {
1030 if (e.control_type == LoopControlType::Break) break;
1031 if (e.control_type == LoopControlType::Continue) continue;
1032 }

Callers

nothing calls this directly

Calls 14

destructuring_assignFunction · 0.85
ValueClass · 0.85
is_nullMethod · 0.80
is_iterableMethod · 0.80
for_eachMethod · 0.80
to_boolMethod · 0.80
push_backMethod · 0.80
renderMethod · 0.80
is_arrayMethod · 0.80
evaluateMethod · 0.45
dumpMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected