@@ -206,6 +206,38 @@ class Value : public std::enable_shared_from_this<Value> {
206
206
throw std::runtime_error (" Value is not an array: " + dump ());
207
207
array_->push_back (v);
208
208
}
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
+ }
209
241
Value get (const Value& key) {
210
242
if (array_) {
211
243
if (!key.is_number_integer ()) {
@@ -366,11 +398,13 @@ class Value : public std::enable_shared_from_this<Value> {
366
398
throw std::runtime_error (" contains can only be called on arrays and objects: " + dump ());
367
399
}
368
400
}
369
- Value pop (size_t index) {
401
+ void erase (size_t index) {
370
402
if (!array_) throw std::runtime_error (" Value is not an array: " + dump ());
371
- auto value = array_->at (index );
372
403
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);
374
408
}
375
409
const Value& at (const Value & index) const {
376
410
return const_cast <Value*>(this )->at (index );
@@ -1345,21 +1379,15 @@ class MethodCallExpr : public Expression {
1345
1379
vargs.expectArgs (" append method" , {1 , 1 }, {0 , 0 });
1346
1380
obj.push_back (vargs.args [0 ]);
1347
1381
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 ]);
1348
1385
} else if (method->get_name () == " insert" ) {
1349
1386
vargs.expectArgs (" insert method" , {2 , 2 }, {0 , 0 });
1350
1387
auto index = vargs.args [0 ].get <int64_t >();
1351
1388
if (index < 0 || index > (int64_t ) obj.size ()) throw std::runtime_error (" Index out of range for insert method" );
1352
1389
obj.insert (index , vargs.args [1 ]);
1353
1390
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
- }
1363
1391
}
1364
1392
} else if (obj.is_object ()) {
1365
1393
if (method->get_name () == " items" ) {
@@ -1369,6 +1397,9 @@ class MethodCallExpr : public Expression {
1369
1397
result.push_back (Value::array ({key, obj.at (key)}));
1370
1398
}
1371
1399
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 ]);
1372
1403
} else if (method->get_name () == " get" ) {
1373
1404
vargs.expectArgs (" get method" , {1 , 2 }, {0 , 0 });
1374
1405
auto key = vargs.args [0 ];
@@ -2546,7 +2577,7 @@ inline std::shared_ptr<Context> Context::builtins() {
2546
2577
}));
2547
2578
globals.set (" namespace" , Value::callable ([=](const std::shared_ptr<Context> &, ArgumentsValue & args) {
2548
2579
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) ()});
2550
2581
for (auto & [name, value] : args.kwargs ) {
2551
2582
ns.set (name, value);
2552
2583
}
@@ -2601,7 +2632,7 @@ inline std::shared_ptr<Context> Context::builtins() {
2601
2632
};
2602
2633
// https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.reject
2603
2634
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 });
2605
2636
auto & items = args.args [0 ];
2606
2637
auto filter_fn = context->get (args.args [1 ]);
2607
2638
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() {
2672
2703
return out;
2673
2704
}));
2674
2705
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 });
2676
2707
auto & items = args.args [0 ];
2677
2708
if (items.is_null ())
2678
2709
return Value::array ();
0 commit comments