pocketlang/tests/native/example2.c

160 lines
4.5 KiB
C
Raw Normal View History

2021-07-01 17:23:16 +08:00
/*
* Copyright (c) 2020-2021 Thakee Nathees
* Distributed Under The MIT License
*/
// This is an example on how to write your own custom type (Vector here) and
// bind it with with the pocket VM.
#include <pocketlang.h>
2022-04-22 00:07:38 +08:00
#include <stdlib.h> /* For malloc */
#include <string.h> /* For strncmp */
#include <math.h> /* For sqrt */
// The script we're using to test the native Vector type.
2021-07-01 17:23:16 +08:00
static const char* code =
2022-04-22 00:07:38 +08:00
" from vector import Vec2 \n"
" print('Class = $Vec2') \n"
" \n"
" v1 = Vec2(1, 2) \n"
" print('v1 = $v1') \n"
" print('v1.length = ${v1.length}') \n"
" print() \n"
" \n"
" v1.x = 3; v1.y = 4; \n"
2022-05-16 19:58:10 +08:00
" print('v1 = $v1') \n"
2022-04-22 00:07:38 +08:00
" print('v1.length = ${v1.length}') \n"
" print() \n"
" \n"
" v2 = Vec2(5, 6) \n"
2022-05-16 19:58:10 +08:00
" print('v2 = $v2') \n"
2022-05-04 14:28:23 +08:00
" v3 = v1 + v2 \n"
2022-05-16 19:58:10 +08:00
" print('v3 = $v3') \n"
2022-04-22 00:07:38 +08:00
" \n"
2021-07-01 17:23:16 +08:00
;
/*****************************************************************************/
2022-04-22 00:07:38 +08:00
/* VECTOR MODULE FUNCTIONS REGISTER */
/*****************************************************************************/
typedef struct {
2022-04-22 00:07:38 +08:00
double x, y;
} Vector;
2022-04-22 00:07:38 +08:00
// Native instance allocation callback.
void* _newVec() {
Vector* vec = (Vector*)malloc(sizeof(Vector));
2022-04-22 00:07:38 +08:00
vec->x = 0;
vec->y = 0;
return vec;
}
2022-04-22 00:07:38 +08:00
// Native instance de-allocatoion callback.
void _deleteVec(void* vector) {
free(vector);
}
2022-05-04 14:28:23 +08:00
void _vecGetter(PKVM* vm) {
const char* name = pkGetSlotString(vm, 1, NULL);
Vector* self = (Vector*)pkGetSelf(vm);
if (strcmp("x", name) == 0) {
pkSetSlotNumber(vm, 0, self->x);
return;
} else if (strcmp("y", name) == 0) {
pkSetSlotNumber(vm, 0, self->y);
return;
2022-05-16 19:58:10 +08:00
} else if (strcmp("length", name) == 0) {
double length = sqrt(pow(self->x, 2) + pow(self->y, 2));
pkSetSlotNumber(vm, 0, length);
return;
2022-05-04 14:28:23 +08:00
}
2022-05-16 19:58:10 +08:00
2022-05-04 14:28:23 +08:00
}
void _vecSetter(PKVM* vm) {
const char* name = pkGetSlotString(vm, 1, NULL);
Vector* self = (Vector*)pkGetSelf(vm);
if (strcmp("x", name) == 0) {
double x;
if (!pkValidateSlotNumber(vm, 2, &x)) return;
self->x = x;
return;
} else if (strcmp("y", name) == 0) {
double y;
if (!pkValidateSlotNumber(vm, 2, &y)) return;
self->y = y;
return;
}
}
2022-05-16 19:58:10 +08:00
void _vecInit(PKVM* vm) {
double x, y;
if (!pkValidateSlotNumber(vm, 1, &x)) return;
if (!pkValidateSlotNumber(vm, 2, &y)) return;
Vector* self = (Vector*) pkGetSelf(vm);
self->x = x;
self->y = y;
}
2022-05-04 14:28:23 +08:00
// Vec2 '+' operator method.
void _vecAdd(PKVM* vm) {
2022-05-16 19:58:10 +08:00
Vector* self = (Vector*) pkGetSelf(vm);
pkReserveSlots(vm, 5); // Now we have slots [0, 1, 2, 3, 4].
pkPlaceSelf(vm, 2); // slot[2] = self
pkGetClass(vm, 2, 2); // slot[2] = Vec2 class.
// slot[1] is slot[2] == other is Vec2 ?
if (!pkValidateSlotInstanceOf(vm, 1, 2)) return;
Vector* other = (Vector*) pkGetSlotNativeInstance(vm, 1);
// slot[3] = new.x
pkSetSlotNumber(vm, 3, self->x + other->x);
// slot[4] = new.y
pkSetSlotNumber(vm, 4, self->y + other->y);
// slot[0] = Vec2(slot[3], slot[4]) => return value.
if (!pkNewInstance(vm, 2, 0, 2, 3)) return;
}
void _vecStr(PKVM* vm) {
2022-04-22 00:07:38 +08:00
Vector* self = (Vector*)pkGetSelf(vm);
2022-05-16 19:58:10 +08:00
pkSetSlotStringFmt(vm, 0, "[%g, %g]", self->x, self->y);
}
// Register the 'Vector' module and it's functions.
void registerVector(PKVM* vm) {
2022-04-22 00:07:38 +08:00
PkHandle* vector = pkNewModule(vm, "vector");
2022-04-22 00:07:38 +08:00
PkHandle* Vec2 = pkNewClass(vm, "Vec2", NULL /*Base Class*/,
vector, _newVec, _deleteVec);
2022-05-16 19:58:10 +08:00
pkClassAddMethod(vm, Vec2, "@getter", _vecGetter, 1);
pkClassAddMethod(vm, Vec2, "@setter", _vecSetter, 2);
pkClassAddMethod(vm, Vec2, "_init", _vecInit, 2);
pkClassAddMethod(vm, Vec2, "_str", _vecStr, 0);
pkClassAddMethod(vm, Vec2, "+", _vecAdd, 1);
2022-04-22 00:07:38 +08:00
pkReleaseHandle(vm, Vec2);
2022-04-22 00:07:38 +08:00
pkRegisterModule(vm, vector);
pkReleaseHandle(vm, vector);
}
/*****************************************************************************/
/* POCKET VM CALLBACKS */
/*****************************************************************************/
int main(int argc, char** argv) {
2022-05-04 14:28:23 +08:00
PKVM* vm = pkNewVM(NULL);
registerVector(vm);
2022-05-04 14:28:23 +08:00
pkRunString(vm, code);
pkFreeVM(vm);
2022-05-04 14:28:23 +08:00
return 0;
}