1use crate::compiler::prelude::*;
2
3fn pop(value: Value) -> Resolved {
4 let mut value = value.try_array()?;
5 value.pop();
6 Ok(value.into())
7}
8
9#[derive(Clone, Copy, Debug)]
10pub struct Pop;
11
12impl Function for Pop {
13 fn identifier(&self) -> &'static str {
14 "pop"
15 }
16
17 fn usage(&self) -> &'static str {
18 "Removes the last item from the `value` array."
19 }
20
21 fn category(&self) -> &'static str {
22 Category::Array.as_ref()
23 }
24
25 fn return_kind(&self) -> u16 {
26 kind::ARRAY
27 }
28
29 fn return_rules(&self) -> &'static [&'static str] {
30 &["The original `value` is not modified."]
31 }
32
33 fn parameters(&self) -> &'static [Parameter] {
34 const PARAMETERS: &[Parameter] = &[Parameter::required(
35 "value",
36 kind::ARRAY,
37 "The target array.",
38 )];
39 PARAMETERS
40 }
41
42 fn examples(&self) -> &'static [Example] {
43 &[example! {
44 title: "Pop an item from an array",
45 source: "pop([1, 2, 3])",
46 result: Ok("[1, 2]"),
47 }]
48 }
49
50 fn compile(
51 &self,
52 _state: &state::TypeState,
53 _ctx: &mut FunctionCompileContext,
54 arguments: ArgumentList,
55 ) -> Compiled {
56 let value = arguments.required("value");
57
58 Ok(PopFn { value }.as_expr())
59 }
60}
61
62#[derive(Debug, Clone)]
63struct PopFn {
64 value: Box<dyn Expression>,
65}
66
67impl FunctionExpression for PopFn {
68 fn resolve(&self, ctx: &mut Context) -> Resolved {
69 let value = self.value.resolve(ctx)?;
70
71 pop(value)
72 }
73
74 fn type_def(&self, state: &state::TypeState) -> TypeDef {
75 self.value
76 .type_def(state)
77 .fallible_unless(Kind::array(Collection::any()))
78 .restrict_array()
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use crate::{btreemap, value};
86
87 test_function![
88 pop => Pop;
89
90 empty_array {
91 args: func_args![value: value!([])],
92 want: Ok(value!([])),
93 tdef: TypeDef::array(Collection::empty()),
94 }
95
96 null_array {
97 args: func_args![value: value!(null)],
98 want: Err("expected array, got null"),
99 tdef: TypeDef::array(Collection::any()).fallible(),
100 }
101
102 mixed_array_types {
103 args: func_args![value: value!([1, 2, 3, true, 5.0, "bar"])],
104 want: Ok(value!([1, 2, 3, true, 5.0])),
105 tdef: TypeDef::array(btreemap! {
106 Index::from(0) => Kind::integer(),
107 Index::from(1) => Kind::integer(),
108 Index::from(2) => Kind::integer(),
109 Index::from(3) => Kind::boolean(),
110 Index::from(4) => Kind::float(),
111 Index::from(5) => Kind::bytes(),
112 }),
113 }
114
115 integer_array {
116 args: func_args![value: value!([0, 1, 2, 3])],
117 want: Ok(value!([0, 1, 2])),
118 tdef: TypeDef::array(btreemap! {
119 Index::from(0) => Kind::integer(),
120 Index::from(1) => Kind::integer(),
121 Index::from(2) => Kind::integer(),
122 Index::from(3) => Kind::integer(),
123 }),
124 }
125
126 ];
127}