// 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/callable_helper.h" #include "paddle/ap/include/axpr/interpreter_base.h" #include "paddle/ap/include/axpr/method_class.h" #include "paddle/ap/include/axpr/naive_class_ops.h" #include "paddle/ap/include/axpr/packed_args.h" #include "paddle/pir/include/dialect/shape/utils/dim_expr.h" namespace ap::axpr { template axpr::TypeImpl> GetDimExprClass(); template struct DimExprMethodClass { using This = DimExprMethodClass; using Self = symbol::DimExpr; static adt::Result ToString(const ValueT& self_val, const std::vector& args) { ADT_LET_CONST_REF(self, self_val.template CastTo()); return symbol::ToString(self); } static adt::Result Hash(const ValueT& self_val, const std::vector&) { ADT_LET_CONST_REF(self, self_val.template CastTo()); int64_t hash_value = std::hash()(self); return hash_value; } static adt::Result Add(const ValueT& self_val, const std::vector& args) { ADT_LET_CONST_REF(lhs, self_val.template CastTo()); ADT_CHECK(args.size() == 1); ADT_LET_CONST_REF(rhs, args.at(0).template CastTo()); return GetDimExprClass().New(lhs + rhs); } static adt::Result Sub(const ValueT& self_val, const std::vector& args) { ADT_LET_CONST_REF(lhs, self_val.template CastTo()); ADT_CHECK(args.size() == 1); ADT_LET_CONST_REF(rhs, args.at(0).template CastTo()); return GetDimExprClass().New(lhs - rhs); } static adt::Result Mul(const ValueT& self_val, const std::vector& args) { ADT_LET_CONST_REF(lhs, self_val.template CastTo()); ADT_CHECK(args.size() == 1); ADT_LET_CONST_REF(rhs, args.at(0).template CastTo()); return GetDimExprClass().New(lhs * rhs); } static adt::Result FloorDiv(const ValueT& self_val, const std::vector& args) { ADT_LET_CONST_REF(lhs, self_val.template CastTo()); ADT_CHECK(args.size() == 1); ADT_LET_CONST_REF(rhs, args.at(0).template CastTo()); return GetDimExprClass().New(lhs / rhs); } static adt::Result Match(axpr::InterpreterBase* interpreter, const ValueT& self_val, const std::vector& packed_args_val) { ADT_LET_CONST_REF(self, self_val.template CastTo()); const auto& packed_args = axpr::CastToPackedArgs(packed_args_val); const auto& [args, kwargs] = *packed_args; ADT_CHECK(args->size() == 0) << adt::errors::TypeError{ std::string() + "DimExpr.match() supports keyword arguments only, but " + std::to_string(args->size()) + " positional arguments were given"}; const std::string& type_name = This{}.GetTypeName(self); std::string key = type_name; if (!kwargs->Has(type_name)) { if (!kwargs->Has("_")) { return adt::errors::TypeError{std::string() + "DimExpr.match() failed. no keyword '" + type_name + "' or '_' provided"}; } key = "_"; } ADT_LET_CONST_REF(func, kwargs->Get(key)); ADT_CHECK(axpr::CallableHelper{}.IsCallable(func)) << adt::errors::TypeError{ std::string() + "the arguments of DimExpr.match() should be callable"}; if (key == "_") { return interpreter->InterpretCall(func, {}); } else { const auto& make_args = self.Match( [&](int64_t c) -> adt::List { return adt::List{c}; }, [&](const std::string& c) -> adt::List { return adt::List{c}; }, [&](const auto&) -> adt::List { return adt::List{}; }); return interpreter->InterpretCall(func, make_args.vector()); } } const char* GetTypeName(const symbol::DimExpr& dim_expr) const { return dim_expr.Match( [](int64_t) -> const char* { return "int64"; }, [&](const std::string&) -> const char* { return "symbol"; }, [&](const auto&) -> const char* { return "_"; }); } }; template axpr::TypeImpl> GetDimExprClass() { using Impl = DimExprMethodClass; static auto cls( axpr::MakeBuiltinClass("DimExpr", [&](const auto& Define) { Define("__str__", &Impl::ToString); Define("__add__", &Impl::Add); Define("__sub__", &Impl::Sub); Define("__mul__", &Impl::Mul); Define("__floordiv__", &Impl::FloorDiv); Define("__hash__", &Impl::Hash); Define("match", &Impl::Match); })); return axpr::MakeGlobalNaiveClassOps(cls); } } // namespace ap::axpr