new object creation interface
This commit is contained in:
parent
c737f41d8a
commit
e937d189df
23 changed files with 103 additions and 84 deletions
|
|
@ -135,7 +135,7 @@ obj::Object* imgui_object_create_menu(obj::TypeGroups* type_group = nullptr) {
|
|||
if (childo->key == "null") {
|
||||
newo = NDO_NULL;
|
||||
} else {
|
||||
newo = obj::NDO->create(childo->key);
|
||||
newo = objects_api::createByName(childo->key.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,9 @@ using namespace obj;
|
|||
|
||||
class ExampleGUI : public Application {
|
||||
public:
|
||||
ExampleGUI() {
|
||||
gui.cd(NDO->create("dict"), "root");
|
||||
}
|
||||
ExampleGUI() { gui.cd(objects_api::create<DictObject>(), "root"); }
|
||||
|
||||
void processFrame(EventHandler* eventHandler) override {
|
||||
}
|
||||
void processFrame(EventHandler* eventHandler) override {}
|
||||
|
||||
void drawFrame(Canvas* canvas) override {
|
||||
canvas->rect({ { 0, 0 }, mWindow->getSize() }, RGBA(0.f, 0.f, 0.f, 1.f), 0);
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ void FunctionDefinition::EvalStatement(Statement* stm) {
|
|||
mLocals.put(func.mFunctionId, mConstants.get(func.mFunctionId));
|
||||
|
||||
// create and register const func object
|
||||
auto function_obj = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto function_obj = objects_api::create<MethodObject>();
|
||||
auto method_const_obj = mConstants.addMethod(func.mFunctionId, function_obj);
|
||||
|
||||
for (auto child_stm : stm_func_def->mStatements->mStatements) {
|
||||
|
|
@ -155,7 +155,7 @@ void FunctionDefinition::EvalStatement(Statement* stm) {
|
|||
mLocals.put(func.mFunctionId, mConstants.get(func.mFunctionId));
|
||||
|
||||
// create and register const func object
|
||||
auto function_obj = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto function_obj = objects_api::create<MethodObject>();
|
||||
auto method_const_obj = mConstants.addMethod(func.mFunctionId, function_obj);
|
||||
|
||||
// compile function
|
||||
|
|
|
|||
|
|
@ -51,10 +51,8 @@ void objects_api::define(ObjectType* type) {
|
|||
type->type_methods.init();
|
||||
}
|
||||
|
||||
Object* objects_api::create(const std::string& name) {
|
||||
MODULE_SANITY_CHECK(gModuleObjects)
|
||||
|
||||
const ObjectType* type = types.get(name);
|
||||
Object* objects_api::create(const ObjectType* type) {
|
||||
ASSERT(type);
|
||||
|
||||
Object* obj_instance = ObjectMemAllocate(type);
|
||||
|
||||
|
|
@ -108,7 +106,7 @@ bool objects_api::compare(Object* first, Object* second) {
|
|||
}
|
||||
|
||||
Object* objects_api::instantiate(Object* in) {
|
||||
obj::Object* obj = NDO->create(in->type->name);
|
||||
obj::Object* obj = objects_api::createByName(in->type->name);
|
||||
tp::obj::objects_api::copy(obj, in);
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -162,8 +160,8 @@ void objects_api::destroy(Object* in) const {
|
|||
return;
|
||||
}
|
||||
|
||||
if (in->refc > 1) {
|
||||
in->refc--;
|
||||
if (in->references > 1) {
|
||||
in->references--;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Object* ObjectMemAllocate(const ObjectType* type) {
|
|||
object->down = nullptr;
|
||||
object->flags = 0;
|
||||
|
||||
object->refc = (alni) 1;
|
||||
object->references = (alni) 1;
|
||||
|
||||
if (bottom) {
|
||||
bottom->down = object;
|
||||
|
|
@ -69,7 +69,7 @@ void obj::assertNoLeaks() {
|
|||
printf("ERROR : not all objects are destroyed\n");
|
||||
ualni idx = 0;
|
||||
for (Object* object = bottom; object; object = object->up) {
|
||||
printf(" ===== Object - %llu. Ref count - %lli ===== \n", idx, object->refc);
|
||||
printf(" ===== Object - %llu. Ref count - %lli ===== \n", idx, object->references);
|
||||
logTypeData(object->type);
|
||||
idx++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ void Interpreter::exec(
|
|||
}
|
||||
}
|
||||
|
||||
bool Interpreter::finished() { return !mCallStack.len(); }
|
||||
bool Interpreter::finished() const { return !mCallStack.len(); }
|
||||
|
||||
void Interpreter::stepBytecode() {
|
||||
halni call_depth = mCallStack.len();
|
||||
|
|
@ -236,7 +236,7 @@ void Interpreter::stepBytecodeIn() {
|
|||
{
|
||||
auto type = mOperandsStack.getOperand<StringObject>();
|
||||
auto id = mOperandsStack.getOperand<StringObject>();
|
||||
mScopeStack.addLocal(NDO->create(type->val), id->val);
|
||||
mScopeStack.addLocal(objects_api::createByName(type->val.c_str()), id->val);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -253,12 +253,11 @@ void Interpreter::stepBytecodeIn() {
|
|||
case OpCode::OBJ_CREATE:
|
||||
{
|
||||
auto type = mOperandsStack.getOperand<StringObject>();
|
||||
Object* new_obj = nullptr;
|
||||
|
||||
// basic types
|
||||
auto idx = NDO->types.presents(type->val);
|
||||
if (idx) {
|
||||
auto new_obj = NDO->create(type->val);
|
||||
Object* new_obj = objects_api::createByName(type->val.c_str());
|
||||
|
||||
mOperandsStack.push(new_obj);
|
||||
mScopeStack.addTemp(new_obj);
|
||||
|
|
@ -286,7 +285,7 @@ void Interpreter::stepBytecodeIn() {
|
|||
|
||||
case OpCode::CLASS_CONSTRUCT:
|
||||
{
|
||||
auto class_obj = (ClassObject*) NDO->create("class");
|
||||
auto class_obj = NDO->create<ClassObject>();
|
||||
|
||||
for (auto local : mScopeStack.getCurrentScope()->mLocals) {
|
||||
class_obj->addMember(local->val, local->key);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ void BoolObject::constructor(BoolObject* self) { self->val = false; }
|
|||
void BoolObject::copy(BoolObject* self, const BoolObject* in) { self->val = in->val; }
|
||||
|
||||
BoolObject* BoolObject::create(bool in) {
|
||||
auto out = objects_api::cast<BoolObject>(NDO->create("bool"));
|
||||
auto out = objects_api::create<BoolObject>();
|
||||
out->val = alni(in);
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ using namespace tp;
|
|||
using namespace obj;
|
||||
|
||||
void ClassObject::constructor(ClassObject* self) {
|
||||
self->members = objects_api::cast<DictObject>(NDO->create("dict"));
|
||||
self->members = objects_api::create<DictObject>();
|
||||
|
||||
self->addMember(NDO_NULL, "__init__");
|
||||
self->addMember(NDO_NULL, "__del__");
|
||||
}
|
||||
|
||||
void ClassObject::copy(ClassObject* self, const ClassObject* blueprint) {
|
||||
NDO->copy(self->members, blueprint->members);
|
||||
objects_api::copy(self->members, blueprint->members);
|
||||
}
|
||||
|
||||
void ClassObject::destructor(ClassObject* self) { NDO->destroy(self->members); }
|
||||
|
|
@ -22,24 +22,24 @@ void ClassObject::destructor(ClassObject* self) { NDO->destroy(self->members); }
|
|||
void ClassObject::addMember(Object* obj, const std::string& id) { members->put(id, obj); }
|
||||
|
||||
void ClassObject::createMember(const std::string& type, const std::string& id) {
|
||||
auto newo = NDO->create(type);
|
||||
auto newo = tp::obj::objects_api::createByName(type.c_str());
|
||||
members->put(id, newo);
|
||||
}
|
||||
|
||||
alni ClassObject::save_size(ClassObject* self) {
|
||||
return sizeof(alni); // dict object adress
|
||||
return sizeof(alni); // dict object address
|
||||
}
|
||||
|
||||
void ClassObject::save(ClassObject* self, ArchiverOut& file_self) {
|
||||
// save dictobject
|
||||
// save dict object
|
||||
alni ndo_object_adress = NDO->save(file_self, self->members);
|
||||
file_self << ndo_object_adress;
|
||||
}
|
||||
|
||||
void ClassObject::load(ArchiverIn& file_self, ClassObject* self) {
|
||||
alni ndo_object_adress;
|
||||
file_self >> ndo_object_adress;
|
||||
self->members = objects_api::cast<DictObject>(NDO->load(file_self, ndo_object_adress));
|
||||
alni ndo_object_address;
|
||||
file_self >> ndo_object_address;
|
||||
self->members = objects_api::cast<DictObject>(NDO->load(file_self, ndo_object_address));
|
||||
tp::obj::objects_api::increaseReferenceCount(self->members);
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,8 @@ alni allocated_size_recursive(ClassObject* self) {
|
|||
return out;
|
||||
}
|
||||
|
||||
struct ObjectType ClassObject::TypeData = { .base = nullptr,
|
||||
struct ObjectType ClassObject::TypeData = {
|
||||
.base = nullptr,
|
||||
.constructor = (object_constructor) ClassObject::constructor,
|
||||
.destructor = (object_destructor) ClassObject::destructor,
|
||||
.copy = (object_copy) ClassObject::copy,
|
||||
|
|
@ -68,5 +69,5 @@ struct ObjectType ClassObject::TypeData = { .base = nullptr,
|
|||
.load = (object_load) load,
|
||||
.childs_retrival = (object_debug_all_childs_retrival) childs_retrival,
|
||||
.allocated_size = (object_allocated_size) allocated_size,
|
||||
.allocated_size_recursive =
|
||||
(object_allocated_size_recursive) allocated_size_recursive };
|
||||
.allocated_size_recursive = (object_allocated_size_recursive) allocated_size_recursive,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ void ColorObject::constructor(ColorObject* self) { self->mCol = tp::RGBA(1.f); }
|
|||
void ColorObject::copy(ColorObject* self, const ColorObject* in) { self->mCol = in->mCol; }
|
||||
|
||||
ColorObject* ColorObject::create(tp::RGBA in) {
|
||||
auto out = objects_api::cast<ColorObject>(NDO->create("RGBA"));
|
||||
auto out = objects_api::create<ColorObject>();
|
||||
out->mCol = in;
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ bool obj::EnumObject::compare(EnumObject* first, EnumObject* second) {
|
|||
}
|
||||
|
||||
EnumObject* obj::EnumObject::create(tp::InitialierList<const char*> list) {
|
||||
auto enum_object = (EnumObject*) obj::NDO->create("enum");
|
||||
auto enum_object = objects_api::create<EnumObject>();
|
||||
enum_object->init(list);
|
||||
return enum_object;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ void FloatObject::constructor(FloatObject* self) { self->val = 0; }
|
|||
void FloatObject::copy(FloatObject* self, const FloatObject* in) { self->val = in->val; }
|
||||
|
||||
FloatObject* FloatObject::create(alnf in) {
|
||||
auto out = objects_api::cast<FloatObject>(NDO->create("float"));
|
||||
auto out = objects_api::create<FloatObject>();
|
||||
out->val = alnf(in);
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ void IntObject::constructor(IntObject* self) { self->val = 0; }
|
|||
void IntObject::copy(IntObject* self, const IntObject* in) { self->val = in->val; }
|
||||
|
||||
IntObject* IntObject::create(alni in) {
|
||||
auto out = objects_api::cast<IntObject>(NDO->create("int"));
|
||||
auto out = objects_api::create<IntObject>();
|
||||
out->val = in;
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ void LinkObject::destructor(LinkObject* self) {
|
|||
void LinkObject::copy(LinkObject* self, const LinkObject* in) { self->setLink(in->link); }
|
||||
|
||||
LinkObject* LinkObject::create(Object* in) {
|
||||
auto out = objects_api::cast<LinkObject>(NDO->create("link"));
|
||||
auto out = objects_api::create<LinkObject>();
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ void MethodObject::UnInitialize() { obj::ScriptSection::uninitialize(); }
|
|||
void MethodObject::compile() { Compile(this); }
|
||||
|
||||
MethodObject* MethodObject::create(const std::string& script) {
|
||||
auto out = (MethodObject*) NDO->create(MethodObject::TypeData.name);
|
||||
auto out = objects_api::create<MethodObject>();
|
||||
out->mScript->mReadable->val = script;
|
||||
out->compile();
|
||||
return out;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ void StringObject::destructor(StringObject* self) { self->val.~basic_string(); }
|
|||
void StringObject::copy(StringObject* self, const StringObject* in) { self->val = in->val; }
|
||||
|
||||
StringObject* StringObject::create(const std::string& in) {
|
||||
auto out = objects_api::cast<StringObject>(NDO->create("str"));
|
||||
auto out = objects_api::create<StringObject>();
|
||||
out->val = in;
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using namespace tp;
|
|||
using namespace obj;
|
||||
|
||||
TypeObject* TypeObject::create(const ObjectType* type) {
|
||||
auto out = objects_api::cast<TypeObject>(NDO->create("typeobject"));
|
||||
auto out = objects_api::create<TypeObject>();
|
||||
out->mTypeRef = type;
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,20 @@ namespace tp::obj {
|
|||
|
||||
extern struct objects_api* NDO;
|
||||
|
||||
// base object
|
||||
struct Object {
|
||||
// TODO : used for saving, can be removed
|
||||
Object* up;
|
||||
Object* down;
|
||||
alni flags;
|
||||
alni refc;
|
||||
|
||||
// reference counting for memory management
|
||||
alni references;
|
||||
|
||||
// type information
|
||||
const struct ObjectType* type;
|
||||
|
||||
// additional inherited data
|
||||
};
|
||||
|
||||
typedef void (*object_from_int)(Object* self, alni in);
|
||||
|
|
@ -127,7 +134,6 @@ namespace tp::obj {
|
|||
~objects_api();
|
||||
|
||||
void define(ObjectType* type);
|
||||
Object* create(const std::string& name);
|
||||
static Object* copy(Object* self, const Object* in);
|
||||
static bool compare(Object* first, Object* second);
|
||||
static Object* instantiate(Object*);
|
||||
|
|
@ -144,11 +150,11 @@ namespace tp::obj {
|
|||
|
||||
void destroy(Object* in) const;
|
||||
|
||||
static inline void increaseReferenceCount(Object* in) { in->refc++; }
|
||||
static inline alni getReferenceCount(Object* in) { return in->refc; }
|
||||
static inline void increaseReferenceCount(Object* in) { in->references++; }
|
||||
static inline alni getReferenceCount(Object* in) { return in->references; }
|
||||
|
||||
private:
|
||||
static inline void setReferenceCount(Object* in, halni count) { in->refc = count; }
|
||||
static inline void setReferenceCount(Object* in, halni count) { in->references = count; }
|
||||
|
||||
public:
|
||||
save_load_callbacks* sl_callbacks[SAVE_LOAD_MAX_CALLBACK_SLOTS]{};
|
||||
|
|
@ -179,14 +185,18 @@ namespace tp::obj {
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Object* create(const ObjectType* type);
|
||||
|
||||
template <typename tObjectType>
|
||||
static tObjectType* create() {
|
||||
return (tObjectType*) NDO->create(&tObjectType::TypeData);
|
||||
}
|
||||
|
||||
static Object* createByName(const char* name) { return NDO->create(NDO->types.get(name)); }
|
||||
};
|
||||
|
||||
void logTypeData(const ObjectType* type);
|
||||
void assertNoLeaks();
|
||||
ualni getObjCount();
|
||||
|
||||
template <typename Type>
|
||||
Type* create() {
|
||||
return (Type*) NDO->create(Type::TypeData.name);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,16 +14,29 @@ namespace tp::obj {
|
|||
bool mIsTypeMethod = false;
|
||||
const TypeMethod* mTypeMethod = nullptr;
|
||||
|
||||
typedef struct { Object* obj; std::string id; } GlobalDef;
|
||||
typedef struct {
|
||||
Object* obj;
|
||||
std::string id;
|
||||
} GlobalDef;
|
||||
|
||||
void exec(MethodObject* method, ClassObject* self = nullptr, DictObject* globals = nullptr, InitialierList<GlobalDef> globals2 = {});
|
||||
void exec(
|
||||
MethodObject* method,
|
||||
ClassObject* self = nullptr,
|
||||
DictObject* globals = nullptr,
|
||||
InitialierList<GlobalDef> globals2 = {}
|
||||
);
|
||||
|
||||
void stepBytecode();
|
||||
void stepBytecodeIn();
|
||||
void stepBytecodeOut();
|
||||
|
||||
bool finished();
|
||||
bool finished() const;
|
||||
|
||||
void execAll(MethodObject* method, ClassObject* self = nullptr, DictObject* globals = nullptr, InitialierList<GlobalDef> globals2 = {});
|
||||
void execAll(
|
||||
MethodObject* method,
|
||||
ClassObject* self = nullptr,
|
||||
DictObject* globals = nullptr,
|
||||
InitialierList<GlobalDef> globals2 = {}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -8,13 +8,14 @@ namespace tp::obj {
|
|||
extern struct NullObject* NdoNull_globalInstance;
|
||||
|
||||
struct NullObject : Object {
|
||||
static ObjectType TypeData;
|
||||
|
||||
static void destructor(Object* self);
|
||||
static ObjectType TypeData;
|
||||
|
||||
static void uninit();
|
||||
static Object* null_return() {
|
||||
if (!NdoNull_globalInstance) {
|
||||
NdoNull_globalInstance = (NullObject*) NDO->create("null");
|
||||
NdoNull_globalInstance = NDO->create<NullObject>();
|
||||
NDO->increaseReferenceCount(NdoNull_globalInstance);
|
||||
}
|
||||
return (Object*) NdoNull_globalInstance;
|
||||
|
|
@ -26,7 +27,7 @@ namespace tp::obj {
|
|||
}
|
||||
};
|
||||
|
||||
#define NDO_NULL NullObject::null_return()
|
||||
#define NDO_NULL_REF NullObject::null_return_ref()
|
||||
#define NDO_NULL NullObject::null_return()
|
||||
#define NDO_NULL_REF NullObject::null_return_ref()
|
||||
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ SUITE(Compiler) {
|
|||
|
||||
{
|
||||
// no errors
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
|
||||
method->mScript->mReadable->val = "print 1 * 20 + 10;";
|
||||
method->compile();
|
||||
|
|
@ -30,7 +30,7 @@ SUITE(Compiler) {
|
|||
|
||||
{
|
||||
// with errors
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
|
||||
method->mScript->mReadable->val = "print undefinedVariable;";
|
||||
method->compile();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ SUITE(Core) {
|
|||
objTestModule.initialize();
|
||||
|
||||
{
|
||||
auto integer = objects_api::cast<IntObject>(NDO->create("int"));
|
||||
auto integer = objects_api::create<IntObject>();
|
||||
|
||||
integer->val = 10;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ SUITE(Interpreter) {
|
|||
objTestModule.initialize();
|
||||
|
||||
{
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto interpreter = objects_api::cast<InterpreterObject>(NDO->create("interpreter"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
auto interpreter = objects_api::create<InterpreterObject>();
|
||||
|
||||
interpreter->getMember<LinkObject>("target method")->setLink(method);
|
||||
|
||||
|
|
@ -71,8 +71,8 @@ SUITE(Interpreter) {
|
|||
objTestModule.initialize();
|
||||
|
||||
{
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto interpreter = objects_api::cast<InterpreterObject>(NDO->create("interpreter"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
auto interpreter = objects_api::create<InterpreterObject>();
|
||||
|
||||
interpreter->getMember<LinkObject>("target method")->setLink(method);
|
||||
|
||||
|
|
@ -102,8 +102,8 @@ SUITE(Interpreter) {
|
|||
{
|
||||
auto compileStartCount = getObjCount();
|
||||
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto interpreter = objects_api::cast<InterpreterObject>(NDO->create("interpreter"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
auto interpreter = objects_api::create<InterpreterObject>();
|
||||
|
||||
interpreter->getMember<LinkObject>("target method")->setLink(method);
|
||||
|
||||
|
|
@ -143,8 +143,8 @@ SUITE(Interpreter) {
|
|||
objTestModule.initialize();
|
||||
|
||||
{
|
||||
auto method = objects_api::cast<MethodObject>(NDO->create("method"));
|
||||
auto interpreter = objects_api::cast<InterpreterObject>(NDO->create("interpreter"));
|
||||
auto method = objects_api::create<MethodObject>();
|
||||
auto interpreter = objects_api::create<InterpreterObject>();
|
||||
|
||||
interpreter->getMember<LinkObject>("target method")->setLink(method);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ SUITE(PrimitiveObjects) {
|
|||
objTestModule.initialize();
|
||||
|
||||
{
|
||||
auto integer = objects_api::cast<IntObject>(NDO->create("int"));
|
||||
auto integer = objects_api::create<IntObject>();
|
||||
integer->val = 10;
|
||||
|
||||
auto dict = objects_api::cast<DictObject>(NDO->create("dict"));
|
||||
auto dict = objects_api::create<DictObject>();
|
||||
|
||||
dict->put("val", integer);
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ SUITE(PrimitiveObjects) {
|
|||
|
||||
auto dictLoaded = objects_api::cast<DictObject>(NDO->load("dict.o"));
|
||||
|
||||
CHECK(dictLoaded->presents("val").isValid());
|
||||
REQUIRE CHECK(dictLoaded->presents("val").isValid());
|
||||
CHECK(objects_api::cast<IntObject>(dictLoaded->get("val"))->val == 10);
|
||||
|
||||
NDO->destroy(dict);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue