Repository: MiSawa/xq (rust)

Issue:
Get placeholder error on del/1 function
```sh
❯ jq -n '{x:[1]} | del(.x[0],.x)'
{}

❯ xq -n '{x:[1]} | del(.x[0],.x)'
Error: IndexOnNonIndexable("placeholder")
```

Pull request description:
Fix placeholder error
Fix #71 

Patch:
diff --git a/src/compile/compiler.rs b/src/compile/compiler.rs
index 329c905..4fc0556 100644
--- a/src/compile/compiler.rs
+++ b/src/compile/compiler.rs
@@ -252,7 +252,9 @@ impl Scope {
     }
 
     fn require_slot(&self) -> bool {
-        self.next_variable_slot_id > 0 || self.next_closure_slot_id > 0 || self.next_label_slot_id > 0
+        self.next_variable_slot_id > 0
+            || self.next_closure_slot_id > 0
+            || self.next_label_slot_id > 0
     }
 
     fn has_slot_leaked_scope(&self) -> bool {
diff --git a/src/intrinsic/path.rs b/src/intrinsic/path.rs
index 6125889..82292fa 100644
--- a/src/intrinsic/path.rs
+++ b/src/intrinsic/path.rs
@@ -33,7 +33,24 @@ pub(crate) fn del_paths(context: Value, paths: Value) -> Result<Value> {
                     v => return Err(QueryExecutionError::PathNotArray(v.clone())),
                 }
             }
-            paths.sort_by_key(|p| p.len());
+            fn depth(path: &[Value]) -> usize {
+                // Indexing or slicing preceded by a slicing doesn't increment the depth of the
+                // values that it going to delete.
+                // To calculate the depth, we can count non-slicing indexings, and increment
+                // if the last component was a slicing.
+                let non_slice_len = path
+                    .iter()
+                    .filter(|i| !matches!(i, Value::Object(_)))
+                    .count();
+                let last_slice = path
+                    .last()
+                    .filter(|i| matches!(i, Value::Object(_)))
+                    .map(|_| 1)
+                    .unwrap_or(0);
+                non_slice_len + last_slice
+            }
+            // We delete from deeper ones so we can raise errors.
+            paths.sort_by_key(|p| std::cmp::Reverse(depth(p)));
             let mut value = context.clone();
             for path in paths {
                 value =


Test patch:
diff --git a/tests/hand_written/mod.rs b/tests/hand_written/mod.rs
index fbcceb6..ca69b31 100644
--- a/tests/hand_written/mod.rs
+++ b/tests/hand_written/mod.rs
@@ -533,3 +533,56 @@ test!(
     -6
     "#
 );
+
+test!(
+    delete1,
+    r#"
+    [1,2,3] | (del(.[1:2][0]), del(.[1:2][1], .[1]))
+    "#,
+    r#"
+    null
+    "#,
+    r#"
+    [1,3]
+    [1,3]
+    "#
+);
+
+test!(
+    delete2,
+    r#"
+    {x:[1]} | del(.x[0],.x)
+    "#,
+    r#"
+    null
+    "#,
+    r#"
+    {}
+    "#
+);
+
+test!(
+    delete3,
+    r#"
+    try ({x:[1]} | del(.x.y, .x[0], .x)) catch "err"
+    "#,
+    r#"
+    null
+    "#,
+    r#"
+    "err"
+    "#
+);
+
+test!(
+    delete4,
+    r#"
+    try ({x:[1]} | del(.x[0], .x.y, .x)) catch "err"
+    "#,
+    r#"
+    null
+    "#,
+    r#"
+    "err"
+    "#
+);