Merge pull request #227 from ThakeeNathees/native-globals

adding globals support in native interface
This commit is contained in:
Thakee Nathees 2022-05-09 23:32:27 +05:30 committed by GitHub
commit 2727f010ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 73 deletions

View File

@ -8,12 +8,8 @@
#include <math.h>
// M_PI is non standard. The macro _USE_MATH_DEFINES defining before importing
// <math.h> will define the constants for MSVC. But for a portable solution,
// we're defining it ourselves if it isn't already.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// M_PI is non standard. For a portable solution, we're defining it ourselves.
#define PK_PI 3.14159265358979323846
DEF(stdMathFloor,
"floor(value:num) -> num\n") {
@ -187,6 +183,12 @@ void registerModuleMath(PKVM* vm) {
PkHandle* math = pkNewModule(vm, "math");
// Set global value PI.
pkReserveSlots(vm, 2);
pkSetSlotHandle(vm, 0, math); // slot[0] = math
pkSetSlotNumber(vm, 1, PK_PI); // slot[1] = 3.14
pkSetGlobal(vm, 0, 1, "PI"); // slot[0].PI = slot[1]
pkModuleAddFunction(vm, math, "floor", stdMathFloor, 1);
pkModuleAddFunction(vm, math, "ceil", stdMathCeil, 1);
pkModuleAddFunction(vm, math, "pow", stdMathPow, 2);
@ -205,14 +207,6 @@ void registerModuleMath(PKVM* vm) {
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
pkModuleAddFunction(vm, math, "round", stdMathRound, 1);
// FIXME:
// Refactor native type interface and add PI as a global to the module.
//
// Note that currently it's mutable (since it's a global variable, not
// constant and pocketlang doesn't support constant) so the user shouldn't
// modify the PI, like in python.
//pkModuleAddGlobal(vm, math, "PI", Handle-Of-PI);
pkRegisterModule(vm, math);
pkReleaseHandle(vm, math);
}

View File

@ -348,7 +348,11 @@ PK_PUBLIC void pkSetSlotStringLength(PKVM* vm, int index,
// Set the [index] slot's value as the given [handle]. The function won't
// reclaim the ownership of the handle and you can still use it till
// it's released by yourself.
PK_PUBLIC void PkSetSlotHandle(PKVM* vm, int index, PkHandle* handle);
PK_PUBLIC void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle);
// Assign a global variable to a module at [module] slot, with the value at the
// [global] slot with the given [name].
PK_PUBLIC void pkSetGlobal(PKVM* vm, int module, int global, const char* name);
#ifdef __cplusplus
} // extern "C"

View File

@ -36,10 +36,10 @@
#define VALIDATE_ARGC(arg) \
ASSERT(arg > 0 && arg <= ARGC, "Invalid argument index.")
#define CHECK_RUNTIME() \
#define CHECK_FIBER_EXISTS(vm) \
do { \
ASSERT(vm->fiber != NULL, \
"This function can only be called at runtime."); \
"No fiber exists. Did you forget to call pkReserveSlots()?"); \
} while (false)
// A convenient macro to get the nth (1 based) argument of the current
@ -484,25 +484,25 @@ PkResult pkRunREPL(PKVM* vm) {
/*****************************************************************************/
void pkSetRuntimeError(PKVM* vm, const char* message) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VM_SET_ERROR(vm, newString(vm, message));
}
void* pkGetSelf(const PKVM* vm) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
ASSERT(IS_OBJ_TYPE(vm->fiber->self, OBJ_INST), OOPS);
Instance* inst = (Instance*)AS_OBJ(vm->fiber->self);
Instance* inst = (Instance*) AS_OBJ(vm->fiber->self);
ASSERT(inst->native != NULL, OOPS);
return inst->native;
}
int pkGetArgc(const PKVM* vm) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
return ARGC;
}
bool pkCheckArgcRange(PKVM* vm, int argc, int min, int max) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
ASSERT(min <= max, "invalid argc range (min > max).");
if (argc < min) {
@ -533,7 +533,7 @@ bool pkCheckArgcRange(PKVM* vm, int argc, int min, int max) {
// FIXME: If the user needs just the boolean value of the object, they should
// use pkGetSlotBool().
PK_PUBLIC bool pkValidateSlotBool(PKVM* vm, int arg, bool* value) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_ARGC(arg);
Var val = ARG(arg);
@ -547,7 +547,7 @@ PK_PUBLIC bool pkValidateSlotBool(PKVM* vm, int arg, bool* value) {
}
PK_PUBLIC bool pkValidateSlotNumber(PKVM* vm, int arg, double* value) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_ARGC(arg);
Var val = ARG(arg);
@ -562,7 +562,7 @@ PK_PUBLIC bool pkValidateSlotNumber(PKVM* vm, int arg, double* value) {
PK_PUBLIC bool pkValidateSlotString(PKVM* vm, int arg, const char** value,
uint32_t* length) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_ARGC(arg);
Var val = ARG(arg);
@ -577,46 +577,40 @@ PK_PUBLIC bool pkValidateSlotString(PKVM* vm, int arg, const char** value,
}
void pkReserveSlots(PKVM* vm, int count) {
CHECK_RUNTIME();
if (vm->fiber == NULL) vm->fiber = newFiber(vm, NULL);
int needed = (int)(vm->fiber->ret - vm->fiber->stack) + count;
vmEnsureStackSize(vm, needed);
}
int pkGetSlotsCount(PKVM* vm) {
CHECK_RUNTIME();
return (int)(vm->fiber->sp - vm->fiber->ret);
CHECK_FIBER_EXISTS(vm);
return (int) ((vm->fiber->stack + vm->fiber->stack_size) - vm->fiber->ret);
}
PkVarType pkGetSlotType(PKVM* vm, int index) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
return getVarType(SLOT(index));
}
bool pkGetSlotBool(PKVM* vm, int index) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
Var value = SLOT(index);
return toBool(value);
}
double pkGetSlotNumber(PKVM* vm, int index) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
Var value = SLOT(index);
ASSERT(IS_NUM(value), "Slot value wasn't a Number.");
return AS_NUM(value);
}
const char* pkGetSlotString(PKVM* vm, int index, uint32_t* length) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
Var value = SLOT(index);
ASSERT(IS_OBJ_TYPE(value, OBJ_STRING), "Slot value wasn't a String.");
if (length != NULL) *length = ((String*)AS_OBJ(value))->length;
@ -624,55 +618,61 @@ const char* pkGetSlotString(PKVM* vm, int index, uint32_t* length) {
}
PkHandle* pkGetSlotHandle(PKVM* vm, int index) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
return vmNewHandle(vm, SLOT(index));
}
void pkSetSlotNull(PKVM* vm, int index) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, VAR_NULL);
}
void pkSetSlotBool(PKVM* vm, int index, bool value) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, VAR_BOOL(value));
}
void pkSetSlotNumber(PKVM* vm, int index, double value) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, VAR_NUM(value));
}
void pkSetSlotString(PKVM* vm, int index, const char* value) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, VAR_OBJ(newString(vm, value)));
}
PK_PUBLIC void pkSetSlotStringLength(PKVM* vm, int index,
const char* value, uint32_t length) {
CHECK_RUNTIME();
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, VAR_OBJ(newStringLength(vm, value, length)));
}
void PkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
CHECK_RUNTIME();
void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
CHECK_FIBER_EXISTS(vm);
VALIDATE_SLOT_INDEX(index);
SET_SLOT(index, handle->value);
}
#undef CHECK_RUNTIME
void pkSetGlobal(PKVM* vm, int module, int global, const char* name) {
CHECK_FIBER_EXISTS(vm);
CHECK_ARG_NULL(name);
VALIDATE_SLOT_INDEX(module);
VALIDATE_SLOT_INDEX(global);
Var value = SLOT(module);
ASSERT(IS_OBJ_TYPE(value, OBJ_MODULE), "Slot value wasn't a module.");
Module* m = (Module*) AS_OBJ(value);
(void) moduleAddGlobal(vm, m, name, (uint32_t) strlen(name), SLOT(global));
}
#undef CHECK_FIBER_EXISTS
#undef VALIDATE_ARGC
#undef ERR_INVALID_ARG_TYPE
#undef ARG

View File

@ -389,7 +389,7 @@ Upvalue* newUpvalue(PKVM* vm, Var* value) {
}
Fiber* newFiber(PKVM* vm, Closure* closure) {
ASSERT(closure->fn->arity >= -1, OOPS);
ASSERT(closure == NULL || closure->fn->arity >= -1, OOPS);
Fiber* fiber = ALLOCATE(vm, Fiber);
@ -401,11 +401,13 @@ Fiber* newFiber(PKVM* vm, Closure* closure) {
fiber->state = FIBER_NEW;
fiber->closure = closure;
if (closure->fn->is_native) {
if (closure == NULL || closure->fn->is_native) {
// For native functions, we're only using stack for parameters,
// there won't be any locals or temps (which are belongs to the
// native "C" stack).
int stack_size = utilPowerOf2Ceil(closure->fn->arity + 1);
int stack_size = (closure == NULL) ? 1 : closure->fn->arity + 1;
stack_size = utilPowerOf2Ceil(stack_size);
// We need at least 1 stack slot for the return value.
if (stack_size == 0) stack_size++;

View File

@ -3,11 +3,7 @@
##
## PI/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
from math import abs
## Temproarly we cannot register variables on native modules
## will be implemented soon. So defining the PI here.
PI = 3.14159265358979323846
from math import abs, PI
pi_by_4 = 0; sign = -1
for i in 1..100000

View File

@ -7,18 +7,13 @@ from math import abs, round, log10,
assert(ceil(1.1) == floor(2.9))
## FIXME:
## temproarly modules cannot define globals via native interface
## and it'll be fixed soon.
PI = 3.14159265358979323846
assert(m.sin(0) == 0)
assert(m.sin(PI/2) == 1)
assert(m.sin(m.PI/2) == 1)
threshold = 0.0000000000001
assert(abs(m.cos(PI/3) - 0.5) < threshold )
assert(abs(m.tan(PI/4) - 1.0) < threshold )
assert(abs(m.cos(m.PI/3) - 0.5) < threshold )
assert(abs(m.tan(m.PI/4) - 1.0) < threshold )
for i in 0..1000
assert(abs(m.sin(i) / m.cos(i) - m.tan(i)) < threshold)
end
@ -29,8 +24,8 @@ for i in 0..100
assert(abs(m.sinh(i) / m.cosh(i) - m.tanh(i)) < threshold)
end
assert(abs(m.acos(PI/4) - 0.5) < 0.35)
assert(abs(m.atan(PI/4) - 0.5) < 0.2)
assert(abs(m.acos(m.PI/4) - 0.5) < 0.35)
assert(abs(m.atan(m.PI/4) - 0.5) < 0.2)
assert((m.acos(0.5) - 1.1276259652063807) < threshold)
assert((m.atan(0.3) - 1.1276259652063807) < threshold)