# References

This page contains all useful methods of VM class.

# Python Equivalents

Str py_str(PyVar obj);                              // x -> str(x)
Str py_repr(PyVar obj);                             // x -> repr(x)
Str py_json(PyVar obj);                             // x -> json.dumps(x)

PyVar py_iter(PyVar obj);                           // x -> iter(x)
PyVar py_next(PyVar);                               // x -> next(x)
PyVar _py_next(const PyTypeInfo*, PyVar);           // x -> next(x) with type info cache
PyVar py_import(Str path, bool throw_err=true);     // x -> __import__(x)
PyVar py_negate(PyVar obj);                         // x -> -x

List py_list(PyVar);                                // x -> list(x)
bool py_callable(PyVar obj);                        // x -> callable(x)
bool py_bool(PyVar obj);                            // x -> bool(x)
i64 py_hash(PyVar obj);                             // x -> hash(x)

bool py_eq(PyVar lhs, PyVar rhs);                   // (lhs, rhs) -> lhs == rhs
bool py_lt(PyVar lhs, PyVar rhs);                   // (lhs, rhs) -> lhs < rhs
bool py_le(PyVar lhs, PyVar rhs);                   // (lhs, rhs) -> lhs <= rhs
bool py_gt(PyVar lhs, PyVar rhs);                   // (lhs, rhs) -> lhs > rhs
bool py_ge(PyVar lhs, PyVar rhs);                   // (lhs, rhs) -> lhs >= rhs
bool py_ne(PyVar lhs, PyVar rhs);

PyVar py_op(std::string_view name);                 // (name) -> operator.name

void py_exec(std::string_view, PyVar, PyVar);       // exec(source, globals, locals)
PyVar py_eval(std::string_view, PyVar, PyVar);      // eval(source, globals, locals)

# Utility Methods

ArgsView cast_array_view(PyVar obj);
void set_main_argv(int argc, char** argv);
i64 normalized_index(i64 index, int size);
Str disassemble(CodeObject_ co);
void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);

# Name Lookup Methods

PyVar find_name_in_mro(Type cls, StrName name);
PyVar get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_err=true, bool fallback=false);
PyVar getattr(PyVar obj, StrName name, bool throw_err=true);
void delattr(PyVar obj, StrName name);
void setattr(PyVar obj, StrName name, PyVar value);

# Source Execution Methods

CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
Str precompile(std::string_view source, const Str& filename, CompileMode mode);
PyVar exec(std::string_view source, Str filename, CompileMode mode, PyVar _module=nullptr);
PyVar exec(std::string_view source);
PyVar eval(std::string_view source);

template<typename ...Args>
PyVar _exec(Args&&... args);

# Invocation Methods

PyVar vectorcall(int ARGC, int KWARGC=0, bool op_call=false);

template<typename... Args>
PyVar call(PyVar callable, Args&&... args);

template<typename... Args>
PyVar call_method(PyVar self, PyVar callable, Args&&... args);

template<typename... Args>
PyVar call_method(PyVar self, StrName name, Args&&... args);

# Logging Methods

virtual void stdout_write(const Str& s);
virtual void stderr_write(const Str& s);

# Magic Bindings

void bind__repr__(Type type, Str (*f)(VM*, PyVar));
void bind__str__(Type type, Str (*f)(VM*, PyVar));
void bind__iter__(Type type, PyVar (*f)(VM*, PyVar));

void bind__next__(Type type, unsigned (*f)(VM*, PyVar));
[[deprecated]] void bind__next__(Type type, PyVar (*f)(VM*, PyVar));
void bind__neg__(Type type, PyVar (*f)(VM*, PyVar));
void bind__invert__(Type type, PyVar (*f)(VM*, PyVar));
void bind__hash__(Type type, i64 (*f)(VM* vm, PyVar));
void bind__len__(Type type, i64 (*f)(VM* vm, PyVar));

void bind__eq__(Type type, BinaryFuncC f);
void bind__lt__(Type type, BinaryFuncC f);
void bind__le__(Type type, BinaryFuncC f);
void bind__gt__(Type type, BinaryFuncC f);
void bind__ge__(Type type, BinaryFuncC f);
void bind__contains__(Type type, BinaryFuncC f);

void bind__add__(Type type, BinaryFuncC f);
void bind__sub__(Type type, BinaryFuncC f);
void bind__mul__(Type type, BinaryFuncC f);
void bind__truediv__(Type type, BinaryFuncC f);
void bind__floordiv__(Type type, BinaryFuncC f);
void bind__mod__(Type type, BinaryFuncC f);
void bind__pow__(Type type, BinaryFuncC f);
void bind__matmul__(Type type, BinaryFuncC f);

void bind__lshift__(Type type, BinaryFuncC f);
void bind__rshift__(Type type, BinaryFuncC f);
void bind__and__(Type type, BinaryFuncC f);
void bind__or__(Type type, BinaryFuncC f);
void bind__xor__(Type type, BinaryFuncC f);

void bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar));
void bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar));
void bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar));

# General Bindings

PyVar bind_func(PyVar obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
PyVar bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
PyVar bind_property(PyVar, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
template<typename T, typename F, bool ReadOnly=false>
PyVar bind_field(PyVar, const char*, F T::*);

PyVar bind(PyVar, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
template<typename Ret, typename... Params>
PyVar bind(PyVar, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
template<typename Ret, typename T, typename... Params>
PyVar bind(PyVar, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);

PyVar bind(PyVar, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
template<typename Ret, typename... Params>
PyVar bind(PyVar, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
template<typename Ret, typename T, typename... Params>
PyVar bind(PyVar, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);

# Error Reporting Methods

void _error(PyVar);
void StackOverflowError() ;
void IOError(const Str& msg) ;
void NotImplementedError();
void TypeError(const Str& msg);
void TypeError(Type expected, Type actual) ;
void IndexError(const Str& msg);
void ValueError(const Str& msg);
void RuntimeError(const Str& msg);
void ZeroDivisionError(const Str& msg);
void ZeroDivisionError();
void NameError(StrName name);
void UnboundLocalError(StrName name);
void KeyError(PyVar obj);
void ImportError(const Str& msg);
void AssertionError(const Str& msg);
void AssertionError();
void BinaryOptError(const char* op, PyVar _0, PyVar _1);
void AttributeError(PyVar obj, StrName name);
void AttributeError(const Str& msg);

# Type Checking Methods

bool isinstance(PyVar obj, Type base);
bool issubclass(Type cls, Type base);
void check_type(PyVar obj, Type type);
void check_compatible_type(PyVar obj, Type type);

Type _tp(PyVar obj);
const PyTypeInfo* _tp_info(PyVar obj) ;
const PyTypeInfo* _tp_info(Type type) ;
PyVar _t(PyVar obj);
PyVar _t(Type type);

# User Type Registration

PyVar new_module(Str name, Str package="");
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled=true);

template<typename T>
Type _tp_user();
template<typename T>
bool is_user_type(PyVar obj);

template<typename T>
PyVar register_user_class(PyVar, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false);
template<typename T>
PyVar register_user_class(PyVar, StrName, Type base=tp_object, bool subclass_enabled=false);

template<typename T, typename ...Args>
PyVar new_user_object(Args&&... args);