Skip to content

Commit

Permalink
map_like::keys
Browse files Browse the repository at this point in the history
Summary:
This diff allows a `map_like` native object to communicate that its properties are finitely enumerable, just like `whisker::map`. This is the common case.

This is useful, for example, to iterate over a map.

Differential Revision: D68007919

fbshipit-source-id: 5f43c65c67f9bf51fc67919f7518f5350021284b
  • Loading branch information
praihan authored and facebook-github-bot committed Jan 12, 2025
1 parent 6802998 commit 7f16693
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
15 changes: 11 additions & 4 deletions thrift/compiler/whisker/mstch_compat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,18 @@ class mstch_map_proxy final
return nullptr;
}

void print_to(tree_printer::scope scope, const object_print_options& options)
const override {
std::optional<std::vector<std::string>> keys() const override {
std::vector<std::string> property_names;
property_names.reserve(proxied_.size());
for (const auto& [key, _] : proxied_) {
property_names.push_back(key);
}
default_print_to(
"mstch::map", std::move(property_names), std::move(scope), options);
return property_names;
}

void print_to(tree_printer::scope scope, const object_print_options& options)
const override {
default_print_to("mstch::map", *keys(), std::move(scope), options);
}

bool operator==(const native_object& untyped_other) const override {
Expand Down Expand Up @@ -183,6 +186,10 @@ class mstch_object_proxy
return object::as_static(result->second);
}

std::optional<std::vector<std::string>> keys() const override {
return proxied_->property_names();
}

void print_to(
tree_printer::scope scope,
[[maybe_unused]] const object_print_options& options) const override {
Expand Down
18 changes: 18 additions & 0 deletions thrift/compiler/whisker/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,24 @@ object::ptr native_function::context::map_like::lookup_property(
});
}

std::optional<std::vector<std::string>>
native_function::context::map_like::keys() const {
using result = std::optional<std::vector<std::string>>;
return detail::variant_match(
which_,
[&](const native_object::map_like::ptr& m) -> result {
return m->keys();
},
[&](const managed_object_ptr<map>& m) -> result {
std::vector<std::string> keys;
keys.reserve(m->size());
for (const auto& [key, _] : *m) {
keys.push_back(key);
}
return keys;
});
}

/* static */ std::optional<native_function::context::map_like>
native_function::context::map_like::try_from(const object::ptr& o) {
if (o->is_map()) {
Expand Down
15 changes: 15 additions & 0 deletions thrift/compiler/whisker/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ class native_object {
virtual managed_object_ptr<> lookup_property(
std::string_view identifier) const = 0;

/**
* Returns an ordered list of finitely enumerable property names of this
* map-like object.
*
* If property names are not enumerable (i.e. dynamically generated), then
* this returns the empty optional.
*
* For each name returned in this list, lookup_property must not return
* nullptr.
*/
virtual std::optional<std::vector<std::string>> keys() const {
return std::nullopt;
}

protected:
/**
* A default implementation of whisker::print_to for native object
Expand Down Expand Up @@ -481,6 +495,7 @@ class native_function {
public:
managed_object_ptr<> lookup_property(
std::string_view identifier) const final;
std::optional<std::vector<std::string>> keys() const final;

// Avoids incomplete type (whisker::object) errors on MSVC.
~map_like() noexcept override;
Expand Down

0 comments on commit 7f16693

Please sign in to comment.