Skip to content

Commit

Permalink
Implement compare for bytearray (#771)
Browse files Browse the repository at this point in the history
Fixes #748

---------

Co-authored-by: Jonathan Immanuel Brachthäuser <[email protected]>
  • Loading branch information
mattisboeckle and b-studios authored Jan 22, 2025
1 parent d9b8292 commit 454c938
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 7 deletions.
4 changes: 4 additions & 0 deletions examples/stdlib/bytearray/bytearray_compare.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Equal()
Equal()
Greater()
Less()
14 changes: 14 additions & 0 deletions examples/stdlib/bytearray/bytearray_compare.effekt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module examples/pos/bytearray_compare

import bytearray

def main() = {
val b1 = fromString("Hey")
val b2 = fromString("Hey")
val b3 = fromString("He")
val b4 = fromString("Heys")
println(compareByteArray(b1, b1))
println(compareByteArray(b1, b2))
println(compareByteArray(b1, b3))
println(compareByteArray(b1, b4))
}
31 changes: 31 additions & 0 deletions libraries/common/bytearray.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,35 @@ extern js """
bytes[index] = value;
return $effekt.unit;
}

function bytearray$compare(arr1, arr2) {
const len = Math.min(arr1.length, arr2.length);

for (let i = 0; i < len; i++) {
if (arr1[i] !== arr2[i]) {
return arr1[i] < arr2[i] ? -1 : 1;
}
}

if (arr1.length !== arr2.length) {
return arr1.length < arr2.length ? -1 : 1;
} else {
return 0;
}
}
"""

extern pure def compareByteArrayImpl(b1: ByteArray, b2: ByteArray): Int =
js "bytearray$compare(${b1}, ${b2})"
llvm """
%x = call %Int @c_bytearray_compare(%Pos ${b1}, %Pos ${b2})
ret %Int %x
"""

def compareByteArray(b1: ByteArray, b2: ByteArray): Ordering =
compareByteArrayImpl(b1, b2) match {
case -1 => Less()
case 0 => Equal()
case 1 => Greater()
case _ => <{ "Impossible: ByteArray comparison returned invalid value!" }>
}
43 changes: 36 additions & 7 deletions libraries/llvm/bytearray.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,45 @@ struct Pos c_bytearray_equal(const struct Pos left, const struct Pos right) {
erasePositive(right);
return BooleanFalse;
}
for (uint64_t j = 0; j < left_size; ++j) {
if (c_bytearray_data(left)[j] != c_bytearray_data(right)[j]) {
erasePositive(left);
erasePositive(right);
return BooleanFalse;
}

int cmp = memcmp(c_bytearray_data(left), c_bytearray_data(right), left_size);
erasePositive(left);
erasePositive(right);
return (cmp == 0 ? BooleanTrue : BooleanFalse);
}

Int c_bytearray_compare(const struct Pos left, const struct Pos right) {
uint64_t left_size = left.tag;
uint64_t right_size = right.tag;
uint64_t min_size = (left_size < right_size) ? left_size : right_size;

uint8_t* left_data = c_bytearray_data(left);
uint8_t* right_data = c_bytearray_data(right);

if (left_data == right_data) {
erasePositive(left);
erasePositive(right);
return 0;
}

int cmp = memcmp(left_data, right_data, min_size);

erasePositive(left);
erasePositive(right);
return BooleanTrue;

if (cmp < 0) {
return -1;
} else if (cmp > 0) {
return 1;
}

if (left_size < right_size) {
return -1;
} else if (left_size > right_size) {
return 1;
}

return 0;
}

// TODO deprecate
Expand Down
1 change: 1 addition & 0 deletions libraries/llvm/forward-declare-c.ll
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare %Pos @c_bytearray_show_Double(double)

declare %Pos @c_bytearray_concatenate(%Pos, %Pos)
declare %Pos @c_bytearray_equal(%Pos, %Pos)
declare %Int @c_bytearray_compare(%Pos, %Pos)

declare %Pos @c_bytearray_substring(%Pos, i64, i64)
declare %Int @c_bytearray_character_at(%Pos, i64)
Expand Down

0 comments on commit 454c938

Please sign in to comment.