Files
2026-07-13 12:40:42 +08:00

153 lines
5.6 KiB
C++

// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "paddle/ap/include/axpr/builtin_func_type.h"
#include "paddle/ap/include/axpr/method_class.h"
#include "paddle/ap/include/axpr/ordered_dict.h"
#include "paddle/ap/include/axpr/to_string.h"
namespace ap::axpr {
template <typename ValueT>
struct MethodClassImpl<ValueT, OrderedDict<ValueT>> {
using Val = ValueT;
using This = MethodClassImpl<ValueT, OrderedDict<ValueT>>;
using Self = OrderedDict<ValueT>;
adt::Result<ValueT> Length(const Self& self) {
return static_cast<int64_t>(self->items().size());
}
adt::Result<ValueT> ToString(axpr::InterpreterBase<ValueT>* interpreter,
const Self& self) {
std::ostringstream ss;
ss << "OrderedDict([";
int i = 0;
for (const auto& [k, v] : self->items()) {
if (i++ > 0) {
ss << ", ";
}
ADT_LET_CONST_REF(key_str, axpr::ToString(interpreter, k));
ADT_LET_CONST_REF(value_str, axpr::ToString(interpreter, v));
ss << "[" << key_str << ", " << value_str << "]";
}
ss << "])";
return ss.str();
}
adt::Result<ValueT> Hash(axpr::InterpreterBase<ValueT>* interpreter,
const Self& self) {
int64_t hash_value = 0;
for (const auto& [k, v] : self->items()) {
ADT_LET_CONST_REF(key_hash_value, axpr::Hash<ValueT>{}(interpreter, k));
ADT_LET_CONST_REF(value_hash_value, axpr::Hash<ValueT>{}(interpreter, v));
hash_value = adt::hash_combine(hash_value, key_hash_value);
hash_value = adt::hash_combine(hash_value, value_hash_value);
}
return hash_value;
}
adt::Result<ValueT> GetItem(axpr::InterpreterBase<ValueT>* interpreter,
const Self& self,
const ValueT& key) {
ADT_LET_CONST_REF(val, self->At(interpreter, key))
<< adt::errors::KeyError{axpr::ToDebugString(interpreter, key)};
return val;
}
adt::Result<ValueT> GetAttr(const Self& self, const ValueT& attr_name_val) {
ADT_LET_CONST_REF(attr_name, attr_name_val.template TryGet<std::string>());
if (attr_name == "items") {
return axpr::Method<ValueT>{
self, &axpr::WrapAsBuiltinFuncType<This, &This::Items>};
}
if (attr_name == "contains") {
return axpr::Method<ValueT>{self, &This::Contains};
}
return adt::errors::TypeError{std::string() +
"OrderedDict object has no attribute '" +
attr_name + "'"};
}
static adt::Result<ValueT> Contains(
axpr::InterpreterBase<ValueT>* interpreter,
const ValueT& self_val,
const std::vector<ValueT>& args) {
ADT_LET_CONST_REF(self, self_val.template CastTo<Self>());
ADT_CHECK(args.size() == 1) << adt::errors::TypeError{
std::string() + "OrderedDict.contains() takes 1 argument, but " +
std::to_string(args.size()) + " were given"};
ADT_LET_CONST_REF(has_elt, self->Has(interpreter, args.at(0)));
return has_elt;
}
adt::Result<ValueT> Items(const Self& self, const std::vector<ValueT>&) {
adt::List<ValueT> lst;
lst->reserve(self->items().size());
for (const auto& [first, second] : self->items()) {
lst->emplace_back(adt::List<ValueT>{first, second});
}
return lst;
}
};
template <typename ValueT>
struct MethodClassImpl<ValueT, TypeImpl<OrderedDict<ValueT>>> {
using Val = ValueT;
using Self = TypeImpl<OrderedDict<ValueT>>;
using This = MethodClassImpl<ValueT, Self>;
adt::Result<ValueT> Call(const Self& self) {
return axpr::Method<ValueT>{self, &This::Construct};
}
static adt::Result<ValueT> Construct(
axpr::InterpreterBase<ValueT>* interpreter,
const ValueT&,
const std::vector<ValueT>& args) {
if (args.size() == 0) {
return OrderedDict<ValueT>{};
}
ADT_CHECK(args.size() == 1) << adt::errors::TypeError{
std::string() + "OrderedDict() takes 1 argument but " +
std::to_string(args.size()) + " were given."};
ADT_LET_CONST_REF(lst, args.at(0).template TryGet<adt::List<ValueT>>())
<< adt::errors::TypeError{
std::string() +
"the argument 1 of OrderedDict() should be list, " +
axpr::GetTypeName(args.at(0)) + " found."};
OrderedDict<ValueT> ordered_dict{};
int i = 0;
for (const auto& elt : *lst) {
ADT_LET_CONST_REF(pair, elt.template TryGet<adt::List<ValueT>>())
<< adt::errors::TypeError{std::string() + "sequence item " +
std::to_string(i) +
" : expected list instance, " +
axpr::GetTypeName(elt) + " found."};
ADT_CHECK(pair->size() == 2) << adt::errors::TypeError{
std::string() + "sequence item " + std::to_string(i) +
" : expected 2-item list, " + std::to_string(pair->size()) +
"-item list found."};
ADT_RETURN_IF_ERR(
ordered_dict->Insert(interpreter, pair->at(0), pair->at(1)));
++i;
}
return ordered_dict;
}
};
} // namespace ap::axpr