19#ifndef TVM_SCRIPT_PRINTER_DOC_TRANSLATOR_H_
20#define TVM_SCRIPT_PRINTER_DOC_TRANSLATOR_H_
22#include <tvm/ffi/container/dict.h>
23#include <tvm/ffi/container/list.h>
24#include <tvm/ffi/container/map.h>
25#include <tvm/ffi/expected.h>
26#include <tvm/ffi/reflection/accessor.h>
38class DocTranslatorObj;
53 const ffi::Object* destination)
noexcept;
69 bool explicit_def)
noexcept;
100using FDocTranslate = ffi::reflection::NativeFunctionView<ffi::Optional<ExprDoc>(
101 DocTranslatorObj* translator, ffi::AnyView value,
const ffi::Object* destination)>;
131 const ffi::Optional<Var> bind_var = std::nullopt) {
132 auto result = ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<ffi::Optional<ExprDoc>>(
134 bind_var.has_value() ? bind_var.value().get() :
nullptr))
136 if (result.has_value()) {
137 if (
const auto* origin = value.as<ffi::Object>()) {
138 RecordOrigin(result.value(), ffi::GetRef<ffi::ObjectRef>(origin));
148 void Emit(
const Doc& doc, ffi::Optional<ffi::ObjectRef> origin = std::nullopt) {
150 if (origin.has_value())
RecordOrigin(doc, origin.value());
160 return ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<IdDoc>(
170 return ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<IdDoc>(vtable_->
alloc_id(
this, hint))
178 return ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<ffi::Dict<Var, IdDoc>>(
190 template <
typename T>
192 auto it = extra_config_.find(name);
193 return it == extra_config_.end() ? fallback : (*it).second.as_or_throw<T>();
201 template <
typename T>
203 auto it = extra_state_.find(name);
204 if (it != extra_state_.end())
return (*it).second.as_or_throw<T>();
206 extra_state_.Set(name, value);
214 void SetExtraState(
const ffi::String& name, std::optional<ffi::Any> value) {
215 if (value.has_value()) {
216 extra_state_.Set(name, std::move(value.value()));
218 extra_state_.erase(name);
226 ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<void>(vtable_->
begin_var_scope(
this)).value();
235 ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<void>(vtable_->
end_var_scope(
this)).value();
256 <<
"printer emission requires a collection scope";
265 template <
typename Callback>
270 std::forward<Callback>(callback)();
271 TVM_FFI_CHECK(
doc_scopes_.size() == depth + 1, ValueError)
272 <<
"printer unbalanced Doc collection scopes";
284 ffi::Dict<Doc, ffi::ObjectRef>
GetDocOrigins()
const {
return doc_origins_; }
290 void RecordOrigin(
const Doc& doc,
const ffi::ObjectRef& origin) { doc_origins_.Set(doc, origin); }
298 const ffi::Object* destination =
nullptr);
310 ffi::Map<ffi::String, ffi::Any> extra_config = {})
311 : extra_config_(std::move(extra_config)), vtable_(vtable) {}
323 ffi::Map<ffi::String, ffi::Any> extra_config_;
328 ffi::Dict<ffi::String, ffi::Any> extra_state_;
332 ffi::Dict<Doc, ffi::ObjectRef> doc_origins_;
347 ffi::Array<StmtDoc> statements;
348 for (
const auto& doc : docs) {
350 for (
const auto& stmt : block.value()->stmts) statements.push_back(stmt);
352 statements.push_back(doc.as_or_throw<
StmtDoc>());
378 ffi::Dict<Doc, ffi::ObjectRef>* doc_origins =
nullptr,
379 ffi::Map<ffi::String, ffi::Any> extra_config = {});
396 const ffi::Object* destination) {
398 ffi::AnyView attr = column[value.type_index()];
399 if (attr.type_index() == ffi::TypeIndex::kTVMFFIOpaquePtr) {
400 return ffi::details::ExpectedUnsafe::MoveFromTVMFFIAny<ffi::Optional<ExprDoc>>(
402 this, value, destination))
405 if (attr.type_index() == ffi::TypeIndex::kTVMFFIFunction) {
406 ffi::Any destination_arg =
nullptr;
407 if (destination) destination_arg = ffi::GetRef<ffi::ObjectRef>(destination);
408 return attr.cast<ffi::Function>()
409 .CallExpected<ffi::Optional<ExprDoc>>(
this, value, destination_arg)
412 TVM_FFI_THROW(TypeError) << (attr.type_index() == ffi::TypeIndex::kTVMFFINone
413 ? std::string(
"printer has no Doc hook for ") +
415 :
"printer Doc hook must be a native pointer or ffi.Function");
Managed reference to VarNode.
Definition expr.h:714
Eager translation context shared by registered hooks. Hooks construct Docs, use explicit lexical scop...
Definition doc_translator.h:120
ffi::Dict< Doc, ffi::ObjectRef > GetDocOrigins() const
Get the owned Doc-to-original-object associations.
Definition doc_translator.h:284
TVM_FFI_DECLARE_OBJECT_INFO("script.printer.DocTranslator", DocTranslatorObj, ffi::Object)
T GetExtraConfig(const ffi::String &name, T fallback) const
Read a typed extension option.
Definition doc_translator.h:191
ffi::Dict< Var, IdDoc > GetImplicitDefs()
Get the current variable scope's pending definitions.
Definition doc_translator.h:177
void SetExtraState(const ffi::String &name, std::optional< ffi::Any > value)
Replace or remove extension state.
Definition doc_translator.h:214
static constexpr bool _type_mutable
Definition doc_translator.h:300
DocTranslatorObj(const DocTranslatorVTable *vtable, ffi::Map< ffi::String, ffi::Any > extra_config={})
Initialize an engine's translation context.
Definition doc_translator.h:309
void RecordOrigin(const Doc &doc, const ffi::ObjectRef &origin)
Set a Doc's original IR object, replacing any previous association.
Definition doc_translator.h:290
T GetOrCreateExtraState(const ffi::String &name)
Get or initialize typed extension state.
Definition doc_translator.h:202
ffi::List< ffi::List< Doc > > doc_scopes_
Active Doc collections, independent of lexical variable scopes.
Definition doc_translator.h:316
void BeginVarScope()
Begin a lexical variable scope independent of Doc collection.
Definition doc_translator.h:225
ffi::List< Doc > EndDocScope()
Pop the latest Doc collection.
Definition doc_translator.h:245
ffi::Optional< ExprDoc > DefaultTranslate(ffi::AnyView value, const ffi::Object *destination=nullptr)
Dispatch directly to the registered native or packed hook.
Definition doc_translator.h:395
IdDoc AllocId(const ffi::String &hint)
Reserve a fresh identifier without mapping a variable.
Definition doc_translator.h:169
void Emit(const Doc &doc, ffi::Optional< ffi::ObjectRef > origin=std::nullopt)
Append a completed Doc and record its optional origin.
Definition doc_translator.h:148
ffi::List< Doc > WithDocScope(Callback &&callback)
Run a callback in a balanced Doc collection scope.
Definition doc_translator.h:266
void EndVarScope()
End the latest naming region, retaining the root region. Explicit local bindings expire....
Definition doc_translator.h:234
ffi::Optional< ExprDoc > Translate(ffi::AnyView value, const ffi::Optional< Var > bind_var=std::nullopt)
Translate a value with an optional pre-mapped binding variable.
Definition doc_translator.h:130
void BeginDocScope()
Push an empty Doc collection.
Definition doc_translator.h:240
ffi::List< Doc > CurrentScopeDocs() const
Get the current Doc collection without popping it.
Definition doc_translator.h:254
IdDoc VarGetOrAllocId(const Var &var, bool explicit_def)
Reuse or allocate a variable's stable identifier.
Definition doc_translator.h:159
Owning reference to a hook translation context.
Definition doc_translator.h:361
TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(DocTranslator, ffi::ObjectRef, DocTranslatorObj)
Retain a translation context.
Reference type of DocNode.
Definition doc.h:77
Reference type of IdDocNode.
Definition doc.h:386
Reference type of StmtBlockDocNode.
Definition doc.h:212
Reference type of StmtDocNode.
Definition doc.h:182
constexpr const char * kDocTranslateOpCall
Op-specific Call translation hook with the FDocTranslate contract.
Definition doc_translator.h:392
constexpr const char * kDocTranslate
Type attribute containing a native or packed translation hook.
Definition doc_translator.h:385
TVM_TIRX_DLL Doc DocTranslate(ffi::AnyView ir, ffi::Dict< Doc, ffi::ObjectRef > *doc_origins=nullptr, ffi::Map< ffi::String, ffi::Any > extra_config={})
Translate IR into a complete Doc including declarations and metadata setup.
ffi::reflection::NativeFunctionView< ffi::Optional< ExprDoc >(DocTranslatorObj *translator, ffi::AnyView value, const ffi::Object *destination)> FDocTranslate
Native translation hook with borrowed inputs and an owning result.
Definition doc_translator.h:101
ffi::Array< StmtDoc > ToStmtDocArray(const ffi::List< Doc > &docs)
Convert collected Docs to statements in their original order.
Definition doc_translator.h:346
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition attr.h:23
#define TVM_TIRX_DLL
Definition base.h:83
Engine callbacks borrowed for the translator's lifetime.
Definition doc_translator.h:43
TVMFFIAny(* begin_var_scope)(DocTranslatorObj *translator) noexcept
Begin a lexical variable scope.
Definition doc_translator.h:81
TVMFFIAny(* end_var_scope)(DocTranslatorObj *translator) noexcept
End the current lexical variable scope.
Definition doc_translator.h:87
TVMFFIAny(* translate)(DocTranslatorObj *translator, ffi::AnyView value, const ffi::Object *destination) noexcept
Translate a value with an optional pre-mapped destination.
Definition doc_translator.h:52
TVMFFIAny(* alloc_id)(DocTranslatorObj *translator, ffi::AnyView hint) noexcept
Reserve an identifier without mapping a variable.
Definition doc_translator.h:60
TVMFFIAny(* var_get_or_alloc_id)(DocTranslatorObj *translator, ffi::AnyView var, bool explicit_def) noexcept
Find or allocate a variable's identifier.
Definition doc_translator.h:68
TVMFFIAny(* get_implicit_defs)(DocTranslatorObj *translator) noexcept
Get the current variable scope's pending definitions.
Definition doc_translator.h:75