pocketlang/cli/modules/std_dummy.c
2022-05-17 23:51:01 +05:30

167 lines
4.5 KiB
C

/*
* Copyright (c) 2020-2022 Thakee Nathees
* Copyright (c) 2021-2022 Pocketlang Contributors
* Distributed Under The MIT License
*/
#include "modules.h"
// A DUMMY MODULE TO TEST NATIVE INTERFACE AND CLASSES.
typedef struct {
double val;
} Dummy;
void* _newDummy() {
Dummy* dummy = NEW_OBJ(Dummy);
ASSERT(dummy != NULL, "malloc failed.");
dummy->val = 0;
return dummy;
}
void _deleteDummy(void* ptr) {
Dummy* dummy = (Dummy*)ptr;
FREE_OBJ(dummy);
}
DEF(_dummyInit, "") {
double val;
if (!pkValidateSlotNumber(vm, 1, &val)) return;
Dummy* self = (Dummy*) pkGetSelf(vm);
self->val = val;
}
DEF(_dummyGetter, "") {
const char* name = pkGetSlotString(vm, 1, NULL);
Dummy* self = (Dummy*)pkGetSelf(vm);
if (strcmp("val", name) == 0) {
pkSetSlotNumber(vm, 0, self->val);
return;
}
}
DEF(_dummySetter, "") {
const char* name = pkGetSlotString(vm, 1, NULL);
Dummy* self = (Dummy*)pkGetSelf(vm);
if (strcmp("val", name) == 0) {
double val;
if (!pkValidateSlotNumber(vm, 2, &val)) return;
self->val = val;
return;
}
}
DEF(_dummyAdd, "") {
Dummy* self = (Dummy*) pkGetSelf(vm);
pkReserveSlots(vm, 4); // Now we have slots [0, 1, 2, 3].
pkPlaceSelf(vm, 2); // slot[2] = self
pkGetClass(vm, 2, 2); // slot[2] = Dummy class.
// slots[1] = other.
if (!pkValidateSlotInstanceOf(vm, 1, 2)) return;
Dummy* other = (Dummy*) pkGetSlotNativeInstance(vm, 1);
// slot[3] = self.val + other.val
pkSetSlotNumber(vm, 3, self->val + other->val);
// slot[0] = Dummy(slot[3]) => return value.
if (!pkNewInstance(vm, 2, 0, 1, 3)) return;
}
DEF(_dummyEq, "") {
// TODO: Currently there is no way of getting another native instance
// So, it's impossible to check self == other. So for now checking with
// number.
double value;
if (!pkValidateSlotNumber(vm, 1, &value)) return;
Dummy* self = (Dummy*)pkGetSelf(vm);
pkSetSlotBool(vm, 0, value == self->val);
}
DEF(_dummyGt, "") {
// TODO: Currently there is no way of getting another native instance
// So, it's impossible to check self == other. So for now checking with
// number.
double value;
if (!pkValidateSlotNumber(vm, 1, &value)) return;
Dummy* self = (Dummy*)pkGetSelf(vm);
pkSetSlotBool(vm, 0, self->val > value);
}
DEF(_dummyMethod,
"Dummy.a_method(n1:num, n2:num) -> num\n"
"A dummy method to check dummy method calls. Will take 2 number arguments "
"and return the multiplication.") {
double n1, n2;
if (!pkValidateSlotNumber(vm, 1, &n1)) return;
if (!pkValidateSlotNumber(vm, 2, &n2)) return;
pkSetSlotNumber(vm, 0, n1 * n2);
}
DEF(_dummyFunction,
"dummy.afunc(s1:str, s2:str) -> str\n"
"A dummy function the'll return s2 + s1.") {
const char *s1, *s2;
if (!pkValidateSlotString(vm, 1, &s1, NULL)) return;
if (!pkValidateSlotString(vm, 2, &s2, NULL)) return;
pkSetSlotStringFmt(vm, 0, "%s%s", s2, s1);
}
DEF(_dummyCallNative,
"dummy.call_native(f:fn) -> void\n"
"Calls the function 'f' with arguments 'foo', 42, false.") {
if (!pkValidateSlotType(vm, 1, PK_CLOSURE)) return;
pkReserveSlots(vm, 5); // Now we have slots [0, 1, 2, 3, 4].
pkSetSlotString(vm, 2, "foo");
pkSetSlotNumber(vm, 3, 42);
pkSetSlotBool(vm, 4, false);
// slot[0] = slot[1](slot[2], slot[3], slot[4])
if (!pkCallFunction(vm, 1, 3, 2, 0)) return;
}
DEF(_dummyCallMethod,
"dummy.call_method(o:Obj, method:str, a1, a2) -> \n"
"Calls the method int the object [o] with two arguments [a1] and [a2].") {
const char* method;
if (!pkValidateSlotString(vm, 2, &method, NULL)) return;
// slots = [null, o, method, a1, a2]
if (!pkCallMethod(vm, 1, method, 2, 3, 0)) return;
}
void registerModuleDummy(PKVM* vm) {
PkHandle* dummy = pkNewModule(vm, "dummy");
pkModuleAddFunction(vm, dummy, "afunc", _dummyFunction, 2);
pkModuleAddFunction(vm, dummy, "call_native", _dummyCallNative, 1);
pkModuleAddFunction(vm, dummy, "call_method", _dummyCallMethod, 4);
PkHandle* cls_dummy = pkNewClass(vm, "Dummy", NULL, dummy,
_newDummy, _deleteDummy);
pkClassAddMethod(vm, cls_dummy, "_init", _dummyInit, 1);
pkClassAddMethod(vm, cls_dummy, "@getter", _dummyGetter, 1);
pkClassAddMethod(vm, cls_dummy, "@setter", _dummySetter, 2);
pkClassAddMethod(vm, cls_dummy, "+", _dummyAdd, 1);
pkClassAddMethod(vm, cls_dummy, "==", _dummyEq, 1);
pkClassAddMethod(vm, cls_dummy, ">", _dummyGt, 1);
pkClassAddMethod(vm, cls_dummy, "a_method", _dummyMethod, 2);
pkReleaseHandle(vm, cls_dummy);
pkRegisterModule(vm, dummy);
pkReleaseHandle(vm, dummy);
}