mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-06 12:46:53 +08:00
adding globals support in native interface
pkSetGlobal function implemented to support adding globals from the native interface. Also the PKVM slots doesn't need a runtime anymore to use them (see math.PI global to see how it works).
This commit is contained in:
parent
78b7004de6
commit
b5d98ca4c3
@ -8,12 +8,8 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
// M_PI is non standard. The macro _USE_MATH_DEFINES defining before importing
|
// M_PI is non standard. For a portable solution, we're defining it ourselves.
|
||||||
// <math.h> will define the constants for MSVC. But for a portable solution,
|
#define PK_PI 3.14159265358979323846
|
||||||
// we're defining it ourselves if it isn't already.
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEF(stdMathFloor,
|
DEF(stdMathFloor,
|
||||||
"floor(value:num) -> num\n") {
|
"floor(value:num) -> num\n") {
|
||||||
@ -187,6 +183,12 @@ void registerModuleMath(PKVM* vm) {
|
|||||||
|
|
||||||
PkHandle* math = pkNewModule(vm, "math");
|
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, "floor", stdMathFloor, 1);
|
||||||
pkModuleAddFunction(vm, math, "ceil", stdMathCeil, 1);
|
pkModuleAddFunction(vm, math, "ceil", stdMathCeil, 1);
|
||||||
pkModuleAddFunction(vm, math, "pow", stdMathPow, 2);
|
pkModuleAddFunction(vm, math, "pow", stdMathPow, 2);
|
||||||
@ -205,14 +207,6 @@ void registerModuleMath(PKVM* vm) {
|
|||||||
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
|
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
|
||||||
pkModuleAddFunction(vm, math, "round", stdMathRound, 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);
|
pkRegisterModule(vm, math);
|
||||||
pkReleaseHandle(vm, math);
|
pkReleaseHandle(vm, math);
|
||||||
}
|
}
|
||||||
|
@ -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
|
// 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
|
// reclaim the ownership of the handle and you can still use it till
|
||||||
// it's released by yourself.
|
// 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
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
#define VALIDATE_ARGC(arg) \
|
#define VALIDATE_ARGC(arg) \
|
||||||
ASSERT(arg > 0 && arg <= ARGC, "Invalid argument index.")
|
ASSERT(arg > 0 && arg <= ARGC, "Invalid argument index.")
|
||||||
|
|
||||||
#define CHECK_RUNTIME() \
|
#define CHECK_FIBER_EXISTS(vm) \
|
||||||
do { \
|
do { \
|
||||||
ASSERT(vm->fiber != NULL, \
|
ASSERT(vm->fiber != NULL, \
|
||||||
"This function can only be called at runtime."); \
|
"No fiber exists. Did you forget to call pkReserveSlots()?"); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
// A convenient macro to get the nth (1 based) argument of the current
|
// A convenient macro to get the nth (1 based) argument of the current
|
||||||
@ -484,12 +484,12 @@ PkResult pkRunREPL(PKVM* vm) {
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void pkSetRuntimeError(PKVM* vm, const char* message) {
|
void pkSetRuntimeError(PKVM* vm, const char* message) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VM_SET_ERROR(vm, newString(vm, message));
|
VM_SET_ERROR(vm, newString(vm, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pkGetSelf(const PKVM* vm) {
|
void* pkGetSelf(const PKVM* vm) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
ASSERT(IS_OBJ_TYPE(vm->fiber->self, OBJ_INST), OOPS);
|
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);
|
ASSERT(inst->native != NULL, OOPS);
|
||||||
@ -497,12 +497,12 @@ void* pkGetSelf(const PKVM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int pkGetArgc(const PKVM* vm) {
|
int pkGetArgc(const PKVM* vm) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
return ARGC;
|
return ARGC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pkCheckArgcRange(PKVM* vm, int argc, int min, int max) {
|
bool pkCheckArgcRange(PKVM* vm, int argc, int min, int max) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
ASSERT(min <= max, "invalid argc range (min > max).");
|
ASSERT(min <= max, "invalid argc range (min > max).");
|
||||||
|
|
||||||
if (argc < min) {
|
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
|
// FIXME: If the user needs just the boolean value of the object, they should
|
||||||
// use pkGetSlotBool().
|
// use pkGetSlotBool().
|
||||||
PK_PUBLIC bool pkValidateSlotBool(PKVM* vm, int arg, bool* value) {
|
PK_PUBLIC bool pkValidateSlotBool(PKVM* vm, int arg, bool* value) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_ARGC(arg);
|
VALIDATE_ARGC(arg);
|
||||||
|
|
||||||
Var val = ARG(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) {
|
PK_PUBLIC bool pkValidateSlotNumber(PKVM* vm, int arg, double* value) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_ARGC(arg);
|
VALIDATE_ARGC(arg);
|
||||||
|
|
||||||
Var val = ARG(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,
|
PK_PUBLIC bool pkValidateSlotString(PKVM* vm, int arg, const char** value,
|
||||||
uint32_t* length) {
|
uint32_t* length) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_ARGC(arg);
|
VALIDATE_ARGC(arg);
|
||||||
|
|
||||||
Var val = ARG(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) {
|
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;
|
int needed = (int)(vm->fiber->ret - vm->fiber->stack) + count;
|
||||||
vmEnsureStackSize(vm, needed);
|
vmEnsureStackSize(vm, needed);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pkGetSlotsCount(PKVM* vm) {
|
int pkGetSlotsCount(PKVM* vm) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
|
return (int) ((vm->fiber->stack + vm->fiber->stack_size) - vm->fiber->ret);
|
||||||
return (int)(vm->fiber->sp - vm->fiber->ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PkVarType pkGetSlotType(PKVM* vm, int index) {
|
PkVarType pkGetSlotType(PKVM* vm, int index) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
return getVarType(SLOT(index));
|
return getVarType(SLOT(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pkGetSlotBool(PKVM* vm, int index) {
|
bool pkGetSlotBool(PKVM* vm, int index) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
Var value = SLOT(index);
|
Var value = SLOT(index);
|
||||||
return toBool(value);
|
return toBool(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
double pkGetSlotNumber(PKVM* vm, int index) {
|
double pkGetSlotNumber(PKVM* vm, int index) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
Var value = SLOT(index);
|
Var value = SLOT(index);
|
||||||
ASSERT(IS_NUM(value), "Slot value wasn't a Number.");
|
ASSERT(IS_NUM(value), "Slot value wasn't a Number.");
|
||||||
return AS_NUM(value);
|
return AS_NUM(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* pkGetSlotString(PKVM* vm, int index, uint32_t* length) {
|
const char* pkGetSlotString(PKVM* vm, int index, uint32_t* length) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
Var value = SLOT(index);
|
Var value = SLOT(index);
|
||||||
ASSERT(IS_OBJ_TYPE(value, OBJ_STRING), "Slot value wasn't a String.");
|
ASSERT(IS_OBJ_TYPE(value, OBJ_STRING), "Slot value wasn't a String.");
|
||||||
if (length != NULL) *length = ((String*)AS_OBJ(value))->length;
|
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) {
|
PkHandle* pkGetSlotHandle(PKVM* vm, int index) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
return vmNewHandle(vm, SLOT(index));
|
return vmNewHandle(vm, SLOT(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkSetSlotNull(PKVM* vm, int index) {
|
void pkSetSlotNull(PKVM* vm, int index) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
SET_SLOT(index, VAR_NULL);
|
SET_SLOT(index, VAR_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkSetSlotBool(PKVM* vm, int index, bool value) {
|
void pkSetSlotBool(PKVM* vm, int index, bool value) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
SET_SLOT(index, VAR_BOOL(value));
|
SET_SLOT(index, VAR_BOOL(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkSetSlotNumber(PKVM* vm, int index, double value) {
|
void pkSetSlotNumber(PKVM* vm, int index, double value) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
SET_SLOT(index, VAR_NUM(value));
|
SET_SLOT(index, VAR_NUM(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkSetSlotString(PKVM* vm, int index, const char* value) {
|
void pkSetSlotString(PKVM* vm, int index, const char* value) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
SET_SLOT(index, VAR_OBJ(newString(vm, value)));
|
SET_SLOT(index, VAR_OBJ(newString(vm, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
PK_PUBLIC void pkSetSlotStringLength(PKVM* vm, int index,
|
PK_PUBLIC void pkSetSlotStringLength(PKVM* vm, int index,
|
||||||
const char* value, uint32_t length) {
|
const char* value, uint32_t length) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
|
||||||
SET_SLOT(index, VAR_OBJ(newStringLength(vm, value, length)));
|
SET_SLOT(index, VAR_OBJ(newStringLength(vm, value, length)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
|
void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
|
||||||
CHECK_RUNTIME();
|
CHECK_FIBER_EXISTS(vm);
|
||||||
VALIDATE_SLOT_INDEX(index);
|
VALIDATE_SLOT_INDEX(index);
|
||||||
SET_SLOT(index, handle->value);
|
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 VALIDATE_ARGC
|
||||||
#undef ERR_INVALID_ARG_TYPE
|
#undef ERR_INVALID_ARG_TYPE
|
||||||
#undef ARG
|
#undef ARG
|
||||||
|
@ -389,7 +389,7 @@ Upvalue* newUpvalue(PKVM* vm, Var* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Fiber* newFiber(PKVM* vm, Closure* closure) {
|
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);
|
Fiber* fiber = ALLOCATE(vm, Fiber);
|
||||||
|
|
||||||
@ -401,11 +401,13 @@ Fiber* newFiber(PKVM* vm, Closure* closure) {
|
|||||||
fiber->state = FIBER_NEW;
|
fiber->state = FIBER_NEW;
|
||||||
fiber->closure = closure;
|
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,
|
// For native functions, we're only using stack for parameters,
|
||||||
// there won't be any locals or temps (which are belongs to the
|
// there won't be any locals or temps (which are belongs to the
|
||||||
// native "C" stack).
|
// 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.
|
// We need at least 1 stack slot for the return value.
|
||||||
if (stack_size == 0) stack_size++;
|
if (stack_size == 0) stack_size++;
|
||||||
|
@ -3,11 +3,7 @@
|
|||||||
##
|
##
|
||||||
## PI/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
|
## PI/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
|
||||||
|
|
||||||
from math import abs
|
from math import abs, PI
|
||||||
|
|
||||||
## Temproarly we cannot register variables on native modules
|
|
||||||
## will be implemented soon. So defining the PI here.
|
|
||||||
PI = 3.14159265358979323846
|
|
||||||
|
|
||||||
pi_by_4 = 0; sign = -1
|
pi_by_4 = 0; sign = -1
|
||||||
for i in 1..100000
|
for i in 1..100000
|
||||||
|
@ -7,18 +7,13 @@ from math import abs, round, log10,
|
|||||||
|
|
||||||
assert(ceil(1.1) == floor(2.9))
|
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(0) == 0)
|
||||||
assert(m.sin(PI/2) == 1)
|
assert(m.sin(m.PI/2) == 1)
|
||||||
|
|
||||||
threshold = 0.0000000000001
|
threshold = 0.0000000000001
|
||||||
|
|
||||||
assert(abs(m.cos(PI/3) - 0.5) < threshold )
|
assert(abs(m.cos(m.PI/3) - 0.5) < threshold )
|
||||||
assert(abs(m.tan(PI/4) - 1.0) < threshold )
|
assert(abs(m.tan(m.PI/4) - 1.0) < threshold )
|
||||||
for i in 0..1000
|
for i in 0..1000
|
||||||
assert(abs(m.sin(i) / m.cos(i) - m.tan(i)) < threshold)
|
assert(abs(m.sin(i) / m.cos(i) - m.tan(i)) < threshold)
|
||||||
end
|
end
|
||||||
@ -29,8 +24,8 @@ for i in 0..100
|
|||||||
assert(abs(m.sinh(i) / m.cosh(i) - m.tanh(i)) < threshold)
|
assert(abs(m.sinh(i) / m.cosh(i) - m.tanh(i)) < threshold)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert(abs(m.acos(PI/4) - 0.5) < 0.35)
|
assert(abs(m.acos(m.PI/4) - 0.5) < 0.35)
|
||||||
assert(abs(m.atan(PI/4) - 0.5) < 0.2)
|
assert(abs(m.atan(m.PI/4) - 0.5) < 0.2)
|
||||||
|
|
||||||
assert((m.acos(0.5) - 1.1276259652063807) < threshold)
|
assert((m.acos(0.5) - 1.1276259652063807) < threshold)
|
||||||
assert((m.atan(0.3) - 1.1276259652063807) < threshold)
|
assert((m.atan(0.3) - 1.1276259652063807) < threshold)
|
||||||
|
Loading…
Reference in New Issue
Block a user