Skip to content

Commit

Permalink
library/array: Add std.array.ksort()
Browse files Browse the repository at this point in the history
  • Loading branch information
lhmouse committed Aug 25, 2021
1 parent 660bced commit 642f114
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 0 deletions.
22 changes: 22 additions & 0 deletions asteria/doc/standard-library.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,28 @@
that in this case there is no guarantee whether an exception
will be thrown or not.

`std.array.ksort(object, [comparator])`

* Creates an array by sorting elements in `object` by key, as if
this function was defined as

```
std.array.ksort = func(object, comparator) {
var pairs = [];
for(each k, v -> object)
pairs[$] = [k, v];
return this.sort(pairs,
func(x, y) {
return (comparator == null)
? x[0] <=> y[0]
: comparator(x[0], y[0]);
});
};
```

* Returns a new array of sorted key-value pairs as nested arrays
of two elements.

`std.array.max_of(data, [comparator])`

* Finds the maximum element in `data`. The principle of
Expand Down
48 changes: 48 additions & 0 deletions asteria/src/library/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,40 @@ std_array_sortu(Global_Context& global, V_array data, optV_function comparator)
return temp;
}

V_array
std_array_ksort(Global_Context& global, V_object object, optV_function comparator)
{
// Collect key-value pairs.
V_array data;
data.reserve(object.size());

for(const auto& r : object) {
V_array pair(2);
pair.mut(0) = r.first.rdstr();
pair.mut(1) = r.second;
data.emplace_back(::std::move(pair));
}

// Use reference counting as our advantage.
if(data.size() <= 1)
return data;

// Merge blocks of exponential sizes. Keys are known to be unique.
Reference_Stack stack;
auto compare = [&](const Value& lhs, const Value& rhs)
{ return do_compare(global, stack, comparator,
lhs.as_array().at(0), rhs.as_array().at(0)); };

V_array temp(data.size());
ptrdiff_t bsize = 1;
while(bsize < data.ssize()) {
do_merge_blocks(temp, data, compare, bsize, false);
data.swap(temp);
bsize *= 2;
}
return data;
}

Value
std_array_max_of(Global_Context& global, V_array data, optV_function comparator)
{
Expand Down Expand Up @@ -1200,6 +1234,20 @@ create_bindings_array(V_object& result, API_Version /*version*/)
}
ASTERIA_BINDING_END);

result.insert_or_assign(sref("ksort"),
ASTERIA_BINDING_BEGIN("std.array.ksort", self, global, reader) {
V_object object;
optV_function comp;

reader.start_overload();
reader.required(object); // object
reader.optional(comp); // [comparator]
if(reader.end_overload())
ASTERIA_BINDING_RETURN_MOVE(self,
std_array_ksort, global, object, comp);
}
ASTERIA_BINDING_END);

result.insert_or_assign(sref("max_of"),
ASTERIA_BINDING_BEGIN("std.array.max_of", self, global, reader) {
V_array data;
Expand Down
4 changes: 4 additions & 0 deletions asteria/src/library/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ std_array_sort(Global_Context& global, V_array data, optV_function comparator);
V_array
std_array_sortu(Global_Context& global, V_array data, optV_function comparator);

// `std.array.ksort`
V_array
std_array_ksort(Global_Context& global, V_object object, optV_function comparator);

// `std.array.max_of`
Value
std_array_max_of(Global_Context& global, V_array data, optV_function comparator);
Expand Down
5 changes: 5 additions & 0 deletions asteria/test/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ int main()
assert std.array.sort(std.array.copy_keys({a:1,b:2,c:3,d:4})) == ['a','b','c','d'];
assert std.array.sort(std.array.copy_values({a:1,b:2,c:3,d:4})) == [1,2,3,4];
assert std.array.ksort({}) == [];
assert std.array.ksort({foo:1}) == [['foo',1]];
assert std.array.ksort({foo:1,bar:2}) == [['bar',2],['foo',1]];
assert std.array.ksort({foo:1,bar:2,def:false}) == [['bar',2],['def',false],['foo',1]];
///////////////////////////////////////////////////////////////////////////////
)__"));
code.execute();
Expand Down

0 comments on commit 642f114

Please sign in to comment.