Skip to content

Commit

Permalink
bit or
Browse files Browse the repository at this point in the history
Summary: this diff was split from next one

Reviewed By: stepancheg

Differential Revision: D63526269

fbshipit-source-id: b666c559a1a49f7b82b771a539589cc19e3c3eaf
  • Loading branch information
perehonchuk authored and facebook-github-bot committed Sep 30, 2024
1 parent f97eb6e commit 29090ef
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
49 changes: 49 additions & 0 deletions starlark/src/values/types/set/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use crate::values::ProvidesStaticType;
use crate::values::StarlarkValue;
use crate::values::Trace;
use crate::values::Value;
use crate::values::ValueError;
use crate::StarlarkDocs;

#[derive(
Expand Down Expand Up @@ -242,6 +243,21 @@ where
fn to_bool(&self) -> bool {
!self.0.content().is_empty()
}

// Set union
fn bit_or(&self, rhs: Value<'v>, heap: &'v Heap) -> crate::Result<Value<'v>> {
// Unlike in `union` it is not possible to `|` `set` and iterable. This is due python semantics.
let rhs = SetRef::from_value(rhs)
.map_or_else(|| ValueError::unsupported_with(self, "|", rhs), Ok)?;
if self.0.content().is_empty() {
return Ok(heap.alloc((*rhs).clone()));
}
let mut items = self.0.content().clone();
for h in rhs.iter_hashed() {
items.insert_hashed(h);
}
Ok(heap.alloc(SetData { content: items }))
}
}

impl<'v, T: SetLike<'v>> Serialize for SetGen<T> {
Expand All @@ -258,3 +274,36 @@ impl<'v, T: SetLike<'v>> Display for SetGen<T> {
fmt_container(f, "set([", "])", self.0.content().iter())
}
}

#[cfg(test)]
mod tests {
use crate::assert;

#[test]
fn test_bit_or() {
assert::eq("set([1, 2, 3]) | set([3, 4])", "set([1, 2, 3, 4])")
}

#[test]
fn test_bit_or_lhs_empty() {
assert::eq("set() | set([3, 4])", "set([3, 4])")
}

#[test]
fn test_bit_or_rhs_empty() {
assert::eq("set([1, 2, 3]) | set()", "set([1, 2, 3])")
}

#[test]
fn test_bit_or_fail_iter() {
assert::fail(
"set([1, 2, 3]) | []",
"Operation `|` not supported for types `set` and `list`",
);
}

#[test]
fn test_bit_or_ord() {
assert::eq("list(set([5, 1, 3]) | set([4, 5, 2]))", "[5, 1, 3, 4, 2]")
}
}
28 changes: 14 additions & 14 deletions starlark/testcases/eval/go/set.star
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ asserts.true(set([1, 2, 3]))
x = set([1, 2, 3])
y = set([3, 4, 5])

# # set + any is not defined
# asserts.fails(lambda : x + y, "unknown.*: set \\+ set")

# # set | set
# asserts.eq(list(set("a".elems()) | set("b".elems())), ["a", "b"])
# asserts.eq(list(set("ab".elems()) | set("bc".elems())), ["a", "b", "c"])
# asserts.fails(lambda : set() | [], "unknown binary op: set | list")
# asserts.eq(type(x | y), "set")
# asserts.eq(list(x | y), [1, 2, 3, 4, 5])
# asserts.eq(list(x | set([5, 1])), [1, 2, 3, 5])
# asserts.eq(list(x | set((6, 5, 4))), [1, 2, 3, 6, 5, 4])

# # set.union (allows any iterable for right operand)
# set + any is not defined
asserts.fails(lambda : x + y, "unknown.*: set \\+ set")

# set | set
asserts.eq(list(set("a".elems()) | set("b".elems())), ["a", "b"])
asserts.eq(list(set("ab".elems()) | set("bc".elems())), ["a", "b", "c"])
asserts.fails(lambda : set() | [], "unknown binary op: set | list")
asserts.eq(type(x | y), "set")
asserts.eq(list(x | y), [1, 2, 3, 4, 5])
asserts.eq(list(x | set([5, 1])), [1, 2, 3, 5])
asserts.eq(list(x | set((6, 5, 4))), [1, 2, 3, 6, 5, 4])

# set.union (allows any iterable for right operand)
# asserts.eq(list(set("a".elems()).union("b".elems())), ["a", "b"])
# asserts.eq(list(set("ab".elems()).union("bc".elems())), ["a", "b", "c"])
# asserts.eq(set().union([]), set())
Expand Down Expand Up @@ -92,7 +92,7 @@ y = set([3, 4, 5])
# len
asserts.eq(len(x), 3)
asserts.eq(len(y), 3)
#asserts.eq(len(x | y), 5)
asserts.eq(len(x | y), 5)

# str
asserts.eq(str(set([1])), "set([1])")
Expand Down

0 comments on commit 29090ef

Please sign in to comment.