// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2019-2025 Second State INC

//===-- wasmedge/wasmedge_vm.h - WasmEdge C API ---------------------------===//
//
// Part of the WasmEdge Project.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the functions about WASM VM in WasmEdge C API.
///
//===----------------------------------------------------------------------===//

#ifndef WASMEDGE_C_API_VM_H
#define WASMEDGE_C_API_VM_H

#include "wasmedge/wasmedge_basic.h"
#include "wasmedge/wasmedge_value.h"

#ifdef __cplusplus
extern "C" {
#endif

// >>>>>>>> WasmEdge VM functions >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

/// Creation of the WasmEdge_VMContext.
///
/// The caller owns the object and should call `WasmEdge_VMDelete` to destroy
/// it.
///
/// \param ConfCxt the WasmEdge_ConfigureContext as the configuration of VM.
/// NULL for the default configuration.
/// \param StoreCxt the WasmEdge_StoreContext as the external WASM store of VM.
/// The instantiation and execution will refer to this store context, and the
/// life cycle should be ensured until the VM context is deleted. NULL for the
/// default store owned by `WasmEdge_VMContext`.
///
/// \returns pointer to context, NULL if failed.
WASMEDGE_CAPI_EXPORT extern WasmEdge_VMContext *
WasmEdge_VMCreate(const WasmEdge_ConfigureContext *ConfCxt,
                  WasmEdge_StoreContext *StoreCxt);

/// Register and instantiate WASM into the store in VM from a WASM file.
///
/// Load a WASM file from the path, and register all exported instances and
/// instantiate them into the store into the VM with their exported name and
/// module name.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext which contains the store.
/// \param ModuleName the WasmEdge_String of module name for all exported
/// instances.
/// \param Path the NULL-terminated C string of the WASM file path.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMRegisterModuleFromFile(WasmEdge_VMContext *Cxt,
                                  const WasmEdge_String ModuleName,
                                  const char *Path);

/// Register and instantiate WASM into the store in VM from a WasmEdge_Bytes.
///
/// Load a WASM module from a WasmEdge_Bytes, and register all exported
/// instances and instantiate them into the store into the VM with their
/// exported name and module name.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext which contains the store.
/// \param ModuleName the WasmEdge_String of module name for all exported
/// instances.
/// \param Bytes the WasmEdge_Bytes of WASM binary.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMRegisterModuleFromBytes(WasmEdge_VMContext *Cxt,
                                   const WasmEdge_String ModuleName,
                                   const WasmEdge_Bytes Bytes);

/// Instantiate and register an AST Module into a named module instance in VM.
///
/// Load from the AST Module, and register all exported instances and
/// instantiate them into the store in VM with their exported name and module
/// name.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext which contains the store.
/// \param ModuleName the WasmEdge_String of module name for all exported
/// instances.
/// \param ASTCxt the WasmEdge AST Module context generated by loader or
/// compiler.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMRegisterModuleFromASTModule(WasmEdge_VMContext *Cxt,
                                       const WasmEdge_String ModuleName,
                                       const WasmEdge_ASTModuleContext *ASTCxt);

/// Register a module instance into the store in VM with exporting its module
/// name.
///
/// After calling this function, the existing module instance will be registered
/// into the store context in this VM, and the other modules can import the
/// exported instances for linking when instantiation. Developers SHOULD
/// guarantee the life cycle of this existing module instance, or the error will
/// occur when in execution after the module instance being destroyed if it has
/// been imported by other modules. That is, developers should call the
/// `WasmEdge_ModuleInstanceDelete` if this existing module instance will not be
/// used anymore or after the deletion of this VM. When the module instance is
/// deleted, it will be unregistered to the store context in this VM
/// automatically.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext which contains the store.
/// \param ImportCxt the WasmEdge_ModuleInstanceContext to register.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result WasmEdge_VMRegisterModuleFromImport(
    WasmEdge_VMContext *Cxt, const WasmEdge_ModuleInstanceContext *ImportCxt);

/// Instantiate the WASM module from a WASM file and invoke a function by name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from the file path, and then invoke a
/// function by name and parameters. If the `Returns` buffer length is smaller
/// than the arity of the function, the overflowed return values will be
/// discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Path the NULL-terminated C string of the WASM file path.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
/// \param [out] Returns the WasmEdge_Value buffer to fill the return values.
/// \param ReturnLen the return buffer length.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result WasmEdge_VMRunWasmFromFile(
    WasmEdge_VMContext *Cxt, const char *Path, const WasmEdge_String FuncName,
    const WasmEdge_Value *Params, const uint32_t ParamLen,
    WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Instantiate the WASM module from a WasmEdge_Bytes and invoke a function by
/// name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from a WasmEdge_Bytes, and then invoke
/// a function by name and parameters. If the `Returns` buffer length is smaller
/// than the arity of the function, the overflowed return values will be
/// discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Bytes the WasmEdge_Bytes of WASM binary.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
/// \param [out] Returns the WasmEdge_Value buffer to fill the return values.
/// \param ReturnLen the return buffer length.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result WasmEdge_VMRunWasmFromBytes(
    WasmEdge_VMContext *Cxt, const WasmEdge_Bytes Bytes,
    const WasmEdge_String FuncName, const WasmEdge_Value *Params,
    const uint32_t ParamLen, WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Instantiate the WASM module from a WasmEdge AST Module and invoke a function
/// by name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from the WasmEdge AST Module, and then
/// invoke the function by name and parameters. If the `Returns` buffer length
/// is smaller than the arity of the function, the overflowed return values will
/// be discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ASTCxt the WasmEdge AST Module context generated by loader or
/// compiler.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
/// \param [out] Returns the WasmEdge_Value buffer to fill the return values.
/// \param ReturnLen the return buffer length.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result WasmEdge_VMRunWasmFromASTModule(
    WasmEdge_VMContext *Cxt, const WasmEdge_ASTModuleContext *ASTCxt,
    const WasmEdge_String FuncName, const WasmEdge_Value *Params,
    const uint32_t ParamLen, WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Instantiate the WASM module from a WASM file and asynchronous invoke a
/// function by name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from the file path, and then invoke a
/// function by name and parameters. If the `Returns` buffer length is smaller
/// than the arity of the function, the overflowed return values will be
/// discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// The caller owns the object and should call `WasmEdge_AsyncDelete` to destroy
/// it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Path the NULL-terminated C string of the WASM file path.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *WasmEdge_VMAsyncRunWasmFromFile(
    WasmEdge_VMContext *Cxt, const char *Path, const WasmEdge_String FuncName,
    const WasmEdge_Value *Params, const uint32_t ParamLen);

/// Instantiate the WASM module from a WasmEdge_Bytes and asynchronous invoke a
/// function by name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from a WasmEdge_Bytes, and then invoke
/// a function by name and parameters. If the `Returns` buffer length is smaller
/// than the arity of the function, the overflowed return values will be
/// discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// The caller owns the object and should call `WasmEdge_AsyncDelete` to destroy
/// it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Bytes the WasmEdge_Bytes of WASM binary.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *WasmEdge_VMAsyncRunWasmFromBytes(
    WasmEdge_VMContext *Cxt, const WasmEdge_Bytes Bytes,
    const WasmEdge_String FuncName, const WasmEdge_Value *Params,
    const uint32_t ParamLen);

/// Instantiate the WASM module from a WasmEdge AST Module and asynchronous
/// invoke a function by name.
///
/// This is the function to invoke a WASM function rapidly.
/// Load and instantiate the WASM module from the WasmEdge AST Module, and then
/// invoke the function by name and parameters. If the `Returns` buffer length
/// is smaller than the arity of the function, the overflowed return values will
/// be discarded.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// The caller owns the object and should call `WasmEdge_AsyncDelete` to destroy
/// it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ASTCxt the WasmEdge AST Module context generated by loader or
/// compiler.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *
WasmEdge_VMAsyncRunWasmFromASTModule(WasmEdge_VMContext *Cxt,
                                     const WasmEdge_ASTModuleContext *ASTCxt,
                                     const WasmEdge_String FuncName,
                                     const WasmEdge_Value *Params,
                                     const uint32_t ParamLen);

/// Load the WASM module from a WASM file.
///
/// This is the first step to invoke a WASM function step by step.
/// Load and parse the WASM module from the file path. You can then call
/// `WasmEdge_VMValidate` for the next step.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Path the NULL-terminated C string of the WASM file path.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMLoadWasmFromFile(WasmEdge_VMContext *Cxt, const char *Path);

/// Load the WASM module from a WasmEdge_Bytes.
///
/// This is the first step to invoke a WASM function step by step.
/// Load and parse the WASM module from a WasmEdge_Bytes. You can then call
/// `WasmEdge_VMValidate` for the next step.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Bytes the WasmEdge_Bytes of WASM binary.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMLoadWasmFromBytes(WasmEdge_VMContext *Cxt,
                             const WasmEdge_Bytes Bytes);

/// Load the WASM module from loaded WasmEdge AST Module.
///
/// This is the first step to invoke a WASM function step by step.
/// Copy the loaded WasmEdge AST Module context into VM. The VM context has no
/// dependency on the input AST Module context. You can then call
/// `WasmEdge_VMValidate` for the next step.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ASTCxt the WasmEdge AST Module context generated by loader or
/// compiler.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMLoadWasmFromASTModule(WasmEdge_VMContext *Cxt,
                                 const WasmEdge_ASTModuleContext *ASTCxt);

/// Validate the WASM module loaded into the VM context.
///
/// This is the second step to invoke a WASM function step by step.
/// After loading a WASM module into VM context, You can call this function to
/// validate it. And you can then call `WasmEdge_VMInstantiate` for the next
/// step. Note that only validated WASM modules can be instantiated in the VM
/// context.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMValidate(WasmEdge_VMContext *Cxt);

/// Instantiate the validated WASM module in the VM context.
///
/// This is the third step to invoke a WASM function step by step.
/// After validating a WASM module in the VM context, You can call this function
/// to instantiate it. And you can then call `WasmEdge_VMExecute` for invoking
/// the exported function in this WASM module.
/// After calling this function, a new anonymous module instance owned by VM is
/// instantiated, and the old one will be destroyed.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMInstantiate(WasmEdge_VMContext *Cxt);

/// Invoke a WASM function by name.
///
/// This is the final step to invoke a WASM function step by step.
/// After instantiating a WASM module in the VM context, the WASM module is
/// registered into the store in the VM context as an anonymous module. Then you
/// can repeatedly call this function to invoke the exported WASM functions by
/// their names until the VM context is reset or a new WASM module is registered
/// or loaded. For calling the functions in registered WASM modules with module
/// names, please use `WasmEdge_VMExecuteRegistered` instead. If the `Returns`
/// buffer length is smaller than the arity of the function, the overflowed
/// return values will be discarded.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
/// \param [out] Returns the WasmEdge_Value buffer to fill the return values.
/// \param ReturnLen the return buffer length.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result
WasmEdge_VMExecute(WasmEdge_VMContext *Cxt, const WasmEdge_String FuncName,
                   const WasmEdge_Value *Params, const uint32_t ParamLen,
                   WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Invoke a WASM function by its module name and function name.
///
/// After registering a WASM module in the VM context, you can repeatedly call
/// this function to invoke exported WASM functions by their module names and
/// function names until the VM context is reset. If the `Returns` buffer length
/// is smaller than the arity of the function, the overflowed return values will
/// be discarded.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ModuleName the module name WasmEdge_String.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
/// \param [out] Returns the WasmEdge_Value buffer to fill the return values.
/// \param ReturnLen the return buffer length.
///
/// \returns WasmEdge_Result. Call `WasmEdge_ResultGetMessage` for the error
/// message.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Result WasmEdge_VMExecuteRegistered(
    WasmEdge_VMContext *Cxt, const WasmEdge_String ModuleName,
    const WasmEdge_String FuncName, const WasmEdge_Value *Params,
    const uint32_t ParamLen, WasmEdge_Value *Returns, const uint32_t ReturnLen);

/// Asynchronous invoke a WASM function by name.
///
/// This is the final step to invoke a WASM function step by step.
/// After instantiating a WASM module in the VM context, the WASM module is
/// registered into the store in the VM context as an anonymous module. Then you
/// can repeatedly call this function to invoke the exported WASM functions by
/// their names until the VM context is reset or a new WASM module is registered
/// or loaded. For calling the functions in registered WASM modules with module
/// names, please use `WasmEdge_VMAsyncExecuteRegistered` instead.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *
WasmEdge_VMAsyncExecute(WasmEdge_VMContext *Cxt, const WasmEdge_String FuncName,
                        const WasmEdge_Value *Params, const uint32_t ParamLen);

/// Asynchronous invoke a WASM function by its module name and function name.
///
/// After registering a WASM module in the VM context, you can repeatedly call
/// this function to invoke exported WASM functions by their module names and
/// function names until the VM context is reset.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ModuleName the module name WasmEdge_String.
/// \param FuncName the function name WasmEdge_String.
/// \param Params the WasmEdge_Value buffer with the parameter values.
/// \param ParamLen the parameter buffer length.
///
/// \returns WasmEdge_Async. Call `WasmEdge_AsyncGet` for the result, and call
/// `WasmEdge_AsyncDelete` to destroy this object.
WASMEDGE_CAPI_EXPORT extern WasmEdge_Async *WasmEdge_VMAsyncExecuteRegistered(
    WasmEdge_VMContext *Cxt, const WasmEdge_String ModuleName,
    const WasmEdge_String FuncName, const WasmEdge_Value *Params,
    const uint32_t ParamLen);

/// Get the function type by function name.
///
/// After instantiating a WASM module in the VM context, the WASM module is
/// registered into the store in the VM context as an anonymous module. Then you
/// can call this function to get the function type by the exported function
/// name until the VM context is reset or a new WASM module is registered or
/// loaded. For getting the function type of functions in registered WASM
/// modules with module names, please use `WasmEdge_VMGetFunctionTypeRegistered`
/// instead.
/// The returned function type context are linked to the context owned by the VM
/// context, and the caller should __NOT__ call the
/// `WasmEdge_FunctionTypeDelete` to destroy it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param FuncName the function name WasmEdge_String.
///
/// \returns the function type. NULL if the function not found.
WASMEDGE_CAPI_EXPORT extern const WasmEdge_FunctionTypeContext *
WasmEdge_VMGetFunctionType(const WasmEdge_VMContext *Cxt,
                           const WasmEdge_String FuncName);

/// Get the function type by function name.
///
/// After registering a WASM module in the VM context, you can call this
/// function to get the function type by the functions' exported module names
/// and function names until the VM context is reset.
/// The returned function type context are linked to the context owned by the VM
/// context, and the caller should __NOT__ call the
/// `WasmEdge_FunctionTypeDelete` to destroy it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ModuleName the module name WasmEdge_String.
/// \param FuncName the function name WasmEdge_String.
///
/// \returns the function type. NULL if the function not found.
WASMEDGE_CAPI_EXPORT extern const WasmEdge_FunctionTypeContext *
WasmEdge_VMGetFunctionTypeRegistered(const WasmEdge_VMContext *Cxt,
                                     const WasmEdge_String ModuleName,
                                     const WasmEdge_String FuncName);

/// Reset of WasmEdge_VMContext.
///
/// After calling this function, the statistics, loaded module, the instantiated
/// instances, and the registered instances except the WASI and plug-ins will
/// all be cleared.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext to reset.
WASMEDGE_CAPI_EXPORT extern void WasmEdge_VMCleanup(WasmEdge_VMContext *Cxt);

/// Get the length of exported function list.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns length of exported function list.
WASMEDGE_CAPI_EXPORT extern uint32_t
WasmEdge_VMGetFunctionListLength(const WasmEdge_VMContext *Cxt);

/// Get the exported function list.
///
/// The returned function names filled into the `Names` array link to the
/// exported names of functions owned by the vm context, and the caller should
/// __NOT__ call the `WasmEdge_StringDelete` to destroy them.
/// The function type contexts filled into the `FuncTypes` array of the
/// corresponding function names link to the context owned by the VM context.
/// The caller should __NOT__ call the `WasmEdge_FunctionTypeDelete` to destroy
/// them.
/// If the `Names` and `FuncTypes` buffer lengths are smaller than the result of
/// the exported function list size, the overflowed return values will be
/// discarded.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param [out] Names the output names WasmEdge_String buffer of exported
/// functions. Can be NULL if names are not needed.
/// \param [out] FuncTypes the function type contexts buffer. Can be NULL if
/// function types are not needed.
/// \param Len the buffer length.
///
/// \returns actual exported function list size.
WASMEDGE_CAPI_EXPORT extern uint32_t WasmEdge_VMGetFunctionList(
    const WasmEdge_VMContext *Cxt, WasmEdge_String *Names,
    const WasmEdge_FunctionTypeContext **FuncTypes, const uint32_t Len);

/// Forcibly delete a registered module from the VM context.
///
/// \warning This function does not check whether other modules depend on the
/// target. Deleting a module that is still in use may cause undefined behavior
/// or crashes.
///
/// A safer deletion API may be introduced in the future once module dependency
/// management is implemented.
///
/// \param Cxt the WasmEdge_VMContext to delete the module from.
/// \param ModuleName the name of the module to delete.
WASMEDGE_CAPI_EXPORT extern void
WasmEdge_VMForceDeleteRegisteredModule(const WasmEdge_VMContext *Cxt,
                                       const WasmEdge_String ModuleName);

/// Get the module instance corresponding to the WasmEdge_HostRegistration
/// settings.
///
/// When creating the VM context with a configuration, the built-in host module
/// will be registered according to the `WasmEdge_HostRegistration` settings
/// added into the `WasmEdge_ConfigureContext`. You can call this function to
/// get the `WasmEdge_ModuleInstanceContext` corresponding to the settings. The
/// module instance context links to the context owned by the VM context. The
/// caller should __NOT__ call the `WasmEdge_ModuleInstanceDelete`.
///
/// ```c
/// WasmEdge_ConfigureContext *Conf = WasmEdge_ConfigureCreate();
/// WasmEdge_ConfigureAddHostRegistration(Conf, WasmEdge_HostRegistration_Wasi);
/// WasmEdge_VMContext *VM = WasmEdge_VMCreate(Conf, NULL);
/// WasmEdge_ModuleInstanceContext *WasiMod =
///     WasmEdge_VMGetImportModuleContext(VM, WasmEdge_HostRegistration_Wasi);
/// ```
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param Reg the host registration value to get the import module.
///
/// \returns pointer to the module instance context. NULL if not found.
WASMEDGE_CAPI_EXPORT extern WasmEdge_ModuleInstanceContext *
WasmEdge_VMGetImportModuleContext(const WasmEdge_VMContext *Cxt,
                                  const enum WasmEdge_HostRegistration Reg);

/// Get the current instantiated module in VM.
///
/// After instantiating a module instance into the VM, developers can call this
/// API to get the active anonymous module instance to retrieve the exported
/// instances. The module instance context links to the context owned by the VM
/// context. The caller should __NOT__ call the `WasmEdge_ModuleInstanceDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the module instance context. NULL if not found.
WASMEDGE_CAPI_EXPORT extern const WasmEdge_ModuleInstanceContext *
WasmEdge_VMGetActiveModule(const WasmEdge_VMContext *Cxt);

/// Get the registered module in VM by the module name.
///
/// After registering a WASM module into the VM context, developers can call
/// this function to get the module instance by the module name. The returned
/// module instance context links to the context owned by the VM context, and
/// the caller should __NOT__ call the `WasmEdge_ModuleInstanceDelete` to
/// destroy it.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param ModuleName the module name WasmEdge_String.
///
/// \returns pointer to the module instance context. NULL if not found.
WASMEDGE_CAPI_EXPORT extern const WasmEdge_ModuleInstanceContext *
WasmEdge_VMGetRegisteredModule(const WasmEdge_VMContext *Cxt,
                               const WasmEdge_String ModuleName);

/// Get the length of registered module list in the WasmEdge_VMContext.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns length of registered module list.
WASMEDGE_CAPI_EXPORT extern uint32_t
WasmEdge_VMListRegisteredModuleLength(const WasmEdge_VMContext *Cxt);

/// List the registered module names in the WasmEdge_VMContext.
///
/// This function will list all registered module names.
/// The returned module names filled into the `Names` array are linked to the
/// registered module names in the VM context, and the caller should __NOT__
/// call the `WasmEdge_StringDelete`.
/// If the `Names` buffer length is smaller than the result of the registered
/// named module list size, the overflowed return values will be discarded.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
/// \param [out] Names the output names WasmEdge_String buffer of the registered
/// modules.
/// \param Len the buffer length.
///
/// \returns actual registered module list size.
WASMEDGE_CAPI_EXPORT extern uint32_t
WasmEdge_VMListRegisteredModule(const WasmEdge_VMContext *Cxt,
                                WasmEdge_String *Names, const uint32_t Len);

/// Get the store context used in the WasmEdge_VMContext.
///
/// The returned store context links to the store in the VM context and owned by
/// the VM context. This function will return NULL if error occurs. The caller
/// should __NOT__ call the `WasmEdge_StoreDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the store context.
WASMEDGE_CAPI_EXPORT extern WasmEdge_StoreContext *
WasmEdge_VMGetStoreContext(WasmEdge_VMContext *Cxt);

/// Get the loader context used in the WasmEdge_VMContext.
///
/// The returned loader context links to the loader in the VM context and owned
/// by the VM context. This function will return NULL if error occurs. The
/// caller should __NOT__ call the `WasmEdge_LoaderDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the loader context.
WASMEDGE_CAPI_EXPORT extern WasmEdge_LoaderContext *
WasmEdge_VMGetLoaderContext(WasmEdge_VMContext *Cxt);

/// Get the validator context used in the WasmEdge_VMContext.
///
/// The returned validator context links to the validator in the VM context and
/// owned by the VM context. This function will return NULL if error occurs. The
/// caller should __NOT__ call the `WasmEdge_ValidatorDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the validator context.
WASMEDGE_CAPI_EXPORT extern WasmEdge_ValidatorContext *
WasmEdge_VMGetValidatorContext(WasmEdge_VMContext *Cxt);

/// Get the executor context used in the WasmEdge_VMContext.
///
/// The returned executor context links to the executor in the VM context and
/// owned by the VM context. This function will return NULL if error occurs. The
/// caller should __NOT__ call the `WasmEdge_ExecutorDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the executor context.
WASMEDGE_CAPI_EXPORT extern WasmEdge_ExecutorContext *
WasmEdge_VMGetExecutorContext(WasmEdge_VMContext *Cxt);

/// Get the statistics context used in the WasmEdge_VMContext.
///
/// The statistics context links to the statistics in the VM context and owned
/// by the VM context. The caller should __NOT__ call the
/// `WasmEdge_StatisticsDelete`.
///
/// This function is thread-safe.
///
/// \param Cxt the WasmEdge_VMContext.
///
/// \returns pointer to the statistics context.
WASMEDGE_CAPI_EXPORT extern WasmEdge_StatisticsContext *
WasmEdge_VMGetStatisticsContext(WasmEdge_VMContext *Cxt);

/// Deletion of the WasmEdge_VMContext.
///
/// After calling this function, the context will be destroyed and should
/// __NOT__ be used.
///
/// \param Cxt the WasmEdge_VMContext to destroy.
WASMEDGE_CAPI_EXPORT extern void WasmEdge_VMDelete(WasmEdge_VMContext *Cxt);

// <<<<<<<< WasmEdge VM functions <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

#ifdef __cplusplus
} /// extern "C"
#endif

#endif /// WASMEDGE_C_API_VM_H
