From ff2cce57ad3ca70fb5db629b88d8cc3a729ecf8d Mon Sep 17 00:00:00 2001 From: ochafik Date: Tue, 21 Jan 2025 01:26:19 +0000 Subject: [PATCH] Update minja to https://github.com/google/minja/pull/25 --- common/minja.hpp | 61 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/common/minja.hpp b/common/minja.hpp index aa0a5019d..e8ac04ec6 100644 --- a/common/minja.hpp +++ b/common/minja.hpp @@ -206,6 +206,38 @@ public: throw std::runtime_error("Value is not an array: " + dump()); array_->push_back(v); } + Value pop(const Value& index) { + if (is_array()) { + if (array_->empty()) + throw std::runtime_error("pop from empty list"); + if (index.is_null()) { + auto ret = array_->back(); + array_->pop_back(); + return ret; + } else if (!index.is_number_integer()) { + throw std::runtime_error("pop index must be an integer: " + index.dump()); + } else { + auto i = index.get(); + if (i < 0 || i >= static_cast(array_->size())) + throw std::runtime_error("pop index out of range: " + index.dump()); + auto it = array_->begin() + (i < 0 ? array_->size() + i : i); + auto ret = *it; + array_->erase(it); + return ret; + } + } else if (is_object()) { + if (!index.is_hashable()) + throw std::runtime_error("Unashable type: " + index.dump()); + auto it = object_->find(index.primitive_); + if (it == object_->end()) + throw std::runtime_error("Key not found: " + index.dump()); + auto ret = it->second; + object_->erase(it); + return ret; + } else { + throw std::runtime_error("Value is not an array or object: " + dump()); + } + } Value get(const Value& key) { if (array_) { if (!key.is_number_integer()) { @@ -366,11 +398,13 @@ public: throw std::runtime_error("contains can only be called on arrays and objects: " + dump()); } } - Value pop(size_t index) { + void erase(size_t index) { if (!array_) throw std::runtime_error("Value is not an array: " + dump()); - auto value = array_->at(index); array_->erase(array_->begin() + index); - return value; + } + void erase(const std::string & key) { + if (!object_) throw std::runtime_error("Value is not an object: " + dump()); + object_->erase(key); } const Value& at(const Value & index) const { return const_cast(this)->at(index); @@ -1345,21 +1379,15 @@ public: vargs.expectArgs("append method", {1, 1}, {0, 0}); obj.push_back(vargs.args[0]); return Value(); + } else if (method->get_name() == "pop") { + vargs.expectArgs("pop method", {0, 1}, {0, 0}); + return obj.pop(vargs.args.empty() ? Value() : vargs.args[0]); } else if (method->get_name() == "insert") { vargs.expectArgs("insert method", {2, 2}, {0, 0}); auto index = vargs.args[0].get(); if (index < 0 || index > (int64_t) obj.size()) throw std::runtime_error("Index out of range for insert method"); obj.insert(index, vargs.args[1]); return Value(); - } else if (method->get_name() == "pop") { - vargs.expectArgs("pop method", {0, 1}, {0, 0}); - if (vargs.args.empty()) { - return obj.pop(obj.size() - 1); - } else { - auto index = vargs.args[0].get(); - if (index < 0 || index >= (int64_t) obj.size()) throw std::runtime_error("Index out of range for pop method"); - return obj.pop(index); - } } } else if (obj.is_object()) { if (method->get_name() == "items") { @@ -1369,6 +1397,9 @@ public: result.push_back(Value::array({key, obj.at(key)})); } return result; + } else if (method->get_name() == "pop") { + vargs.expectArgs("pop method", {1, 1}, {0, 0}); + return obj.pop(vargs.args[0]); } else if (method->get_name() == "get") { vargs.expectArgs("get method", {1, 2}, {0, 0}); auto key = vargs.args[0]; @@ -2546,7 +2577,7 @@ inline std::shared_ptr Context::builtins() { })); globals.set("namespace", Value::callable([=](const std::shared_ptr &, ArgumentsValue & args) { auto ns = Value::object(); - args.expectArgs("namespace", {0, 0}, {0, std::numeric_limits::max()}); + args.expectArgs("namespace", {0, 0}, {0, (std::numeric_limits::max)()}); for (auto & [name, value] : args.kwargs) { ns.set(name, value); } @@ -2601,7 +2632,7 @@ inline std::shared_ptr Context::builtins() { }; // https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.reject globals.set("reject", Value::callable([=](const std::shared_ptr & context, ArgumentsValue & args) { - args.expectArgs("reject", {2, std::numeric_limits::max()}, {0, 0}); + args.expectArgs("reject", {2, (std::numeric_limits::max)()}, {0, 0}); auto & items = args.args[0]; auto filter_fn = context->get(args.args[1]); if (filter_fn.is_null()) throw std::runtime_error("Undefined filter: " + args.args[1].dump()); @@ -2672,7 +2703,7 @@ inline std::shared_ptr Context::builtins() { return out; })); globals.set("selectattr", Value::callable([=](const std::shared_ptr & context, ArgumentsValue & args) { - args.expectArgs("selectattr", {2, std::numeric_limits::max()}, {0, 0}); + args.expectArgs("selectattr", {2, (std::numeric_limits::max)()}, {0, 0}); auto & items = args.args[0]; if (items.is_null()) return Value::array();