Skip to content

Commit ff2cce5

Browse files
author
ochafik
committed
Update minja to google/minja#25
1 parent 8347da9 commit ff2cce5

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

common/minja.hpp

+46-15
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,38 @@ class Value : public std::enable_shared_from_this<Value> {
206206
throw std::runtime_error("Value is not an array: " + dump());
207207
array_->push_back(v);
208208
}
209+
Value pop(const Value& index) {
210+
if (is_array()) {
211+
if (array_->empty())
212+
throw std::runtime_error("pop from empty list");
213+
if (index.is_null()) {
214+
auto ret = array_->back();
215+
array_->pop_back();
216+
return ret;
217+
} else if (!index.is_number_integer()) {
218+
throw std::runtime_error("pop index must be an integer: " + index.dump());
219+
} else {
220+
auto i = index.get<int>();
221+
if (i < 0 || i >= static_cast<int>(array_->size()))
222+
throw std::runtime_error("pop index out of range: " + index.dump());
223+
auto it = array_->begin() + (i < 0 ? array_->size() + i : i);
224+
auto ret = *it;
225+
array_->erase(it);
226+
return ret;
227+
}
228+
} else if (is_object()) {
229+
if (!index.is_hashable())
230+
throw std::runtime_error("Unashable type: " + index.dump());
231+
auto it = object_->find(index.primitive_);
232+
if (it == object_->end())
233+
throw std::runtime_error("Key not found: " + index.dump());
234+
auto ret = it->second;
235+
object_->erase(it);
236+
return ret;
237+
} else {
238+
throw std::runtime_error("Value is not an array or object: " + dump());
239+
}
240+
}
209241
Value get(const Value& key) {
210242
if (array_) {
211243
if (!key.is_number_integer()) {
@@ -366,11 +398,13 @@ class Value : public std::enable_shared_from_this<Value> {
366398
throw std::runtime_error("contains can only be called on arrays and objects: " + dump());
367399
}
368400
}
369-
Value pop(size_t index) {
401+
void erase(size_t index) {
370402
if (!array_) throw std::runtime_error("Value is not an array: " + dump());
371-
auto value = array_->at(index);
372403
array_->erase(array_->begin() + index);
373-
return value;
404+
}
405+
void erase(const std::string & key) {
406+
if (!object_) throw std::runtime_error("Value is not an object: " + dump());
407+
object_->erase(key);
374408
}
375409
const Value& at(const Value & index) const {
376410
return const_cast<Value*>(this)->at(index);
@@ -1345,21 +1379,15 @@ class MethodCallExpr : public Expression {
13451379
vargs.expectArgs("append method", {1, 1}, {0, 0});
13461380
obj.push_back(vargs.args[0]);
13471381
return Value();
1382+
} else if (method->get_name() == "pop") {
1383+
vargs.expectArgs("pop method", {0, 1}, {0, 0});
1384+
return obj.pop(vargs.args.empty() ? Value() : vargs.args[0]);
13481385
} else if (method->get_name() == "insert") {
13491386
vargs.expectArgs("insert method", {2, 2}, {0, 0});
13501387
auto index = vargs.args[0].get<int64_t>();
13511388
if (index < 0 || index > (int64_t) obj.size()) throw std::runtime_error("Index out of range for insert method");
13521389
obj.insert(index, vargs.args[1]);
13531390
return Value();
1354-
} else if (method->get_name() == "pop") {
1355-
vargs.expectArgs("pop method", {0, 1}, {0, 0});
1356-
if (vargs.args.empty()) {
1357-
return obj.pop(obj.size() - 1);
1358-
} else {
1359-
auto index = vargs.args[0].get<int64_t>();
1360-
if (index < 0 || index >= (int64_t) obj.size()) throw std::runtime_error("Index out of range for pop method");
1361-
return obj.pop(index);
1362-
}
13631391
}
13641392
} else if (obj.is_object()) {
13651393
if (method->get_name() == "items") {
@@ -1369,6 +1397,9 @@ class MethodCallExpr : public Expression {
13691397
result.push_back(Value::array({key, obj.at(key)}));
13701398
}
13711399
return result;
1400+
} else if (method->get_name() == "pop") {
1401+
vargs.expectArgs("pop method", {1, 1}, {0, 0});
1402+
return obj.pop(vargs.args[0]);
13721403
} else if (method->get_name() == "get") {
13731404
vargs.expectArgs("get method", {1, 2}, {0, 0});
13741405
auto key = vargs.args[0];
@@ -2546,7 +2577,7 @@ inline std::shared_ptr<Context> Context::builtins() {
25462577
}));
25472578
globals.set("namespace", Value::callable([=](const std::shared_ptr<Context> &, ArgumentsValue & args) {
25482579
auto ns = Value::object();
2549-
args.expectArgs("namespace", {0, 0}, {0, std::numeric_limits<size_t>::max()});
2580+
args.expectArgs("namespace", {0, 0}, {0, (std::numeric_limits<size_t>::max)()});
25502581
for (auto & [name, value] : args.kwargs) {
25512582
ns.set(name, value);
25522583
}
@@ -2601,7 +2632,7 @@ inline std::shared_ptr<Context> Context::builtins() {
26012632
};
26022633
// https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.reject
26032634
globals.set("reject", Value::callable([=](const std::shared_ptr<Context> & context, ArgumentsValue & args) {
2604-
args.expectArgs("reject", {2, std::numeric_limits<size_t>::max()}, {0, 0});
2635+
args.expectArgs("reject", {2, (std::numeric_limits<size_t>::max)()}, {0, 0});
26052636
auto & items = args.args[0];
26062637
auto filter_fn = context->get(args.args[1]);
26072638
if (filter_fn.is_null()) throw std::runtime_error("Undefined filter: " + args.args[1].dump());
@@ -2672,7 +2703,7 @@ inline std::shared_ptr<Context> Context::builtins() {
26722703
return out;
26732704
}));
26742705
globals.set("selectattr", Value::callable([=](const std::shared_ptr<Context> & context, ArgumentsValue & args) {
2675-
args.expectArgs("selectattr", {2, std::numeric_limits<size_t>::max()}, {0, 0});
2706+
args.expectArgs("selectattr", {2, (std::numeric_limits<size_t>::max)()}, {0, 0});
26762707
auto & items = args.args[0];
26772708
if (items.is_null())
26782709
return Value::array();

0 commit comments

Comments
 (0)