mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 13:15:55 +08:00
Merge pull request #237 from ThakeeNathees/term
new Fiber objects falsely garbage collected -- fixed
This commit is contained in:
commit
e458682486
@ -62,12 +62,13 @@ def log(*msg):
|
||||
sys.stderr.write(message + '\n')
|
||||
|
||||
def parse(path):
|
||||
dir = dirname(path).replace('\\', '/') ## Windows.
|
||||
text = ""
|
||||
with open(path, 'r') as fp:
|
||||
for line in fp.readlines():
|
||||
if "//<< AMALG_INLINE >>" in line:
|
||||
path = join(dirname(path), _get_include_path(line))
|
||||
path = path.replace('\\', '/') ## Aaah windows path.
|
||||
path = join(dir, _get_include_path(line))
|
||||
path = path.replace('\\', '/')
|
||||
text += parse(path) + '\n'
|
||||
else: text += line
|
||||
|
||||
|
@ -34,8 +34,7 @@ ALLOW_LONG_LINES = ('http://', 'https://', '<script ', '<link ', '<svg ')
|
||||
IGNORE_FILES = (
|
||||
"cli/modules/pknative.gen.c", ## FIXME: set gen path.
|
||||
"cli/argparse.h", ## FIXME: collect all thirdparty files.
|
||||
"src/libs/tp_dirent.h",
|
||||
"src/libs/tp_cwalk.h",
|
||||
"src/libs/ext_term.c",
|
||||
)
|
||||
|
||||
## A list of directory, contains C source files to perform static checks.
|
||||
|
@ -2734,9 +2734,12 @@ static void compileFunction(Compiler* compiler, FuncType fn_type) {
|
||||
|
||||
if (compiler->parser.has_syntax_error) return;
|
||||
|
||||
// The function will register itself in the owner's constant pool and it's
|
||||
// GC root so we don't need to push it to temp references.
|
||||
int fn_index;
|
||||
Function* func = newFunction(compiler->parser.vm, name, name_length,
|
||||
compiler->module, false, NULL, &fn_index);
|
||||
|
||||
func->is_method = (fn_type == FUNC_METHOD || fn_type == FUNC_CONSTRUCTOR);
|
||||
|
||||
checkMaxConstantsReached(compiler, fn_index);
|
||||
|
@ -81,6 +81,7 @@ static char* stdinRead(PKVM* vm);
|
||||
static char* loadScript(PKVM* vm, const char* path);
|
||||
|
||||
void* pkRealloc(PKVM* vm, void* ptr, size_t size) {
|
||||
|
||||
ASSERT(vm->config.realloc_fn != NULL, "PKVM's allocator was NULL.");
|
||||
#if TRACE_MEMORY
|
||||
void* newptr = vm->config.realloc_fn(ptr, size, vm->config.user_data);
|
||||
@ -123,6 +124,7 @@ PKVM* pkNewVM(PkConfiguration* config) {
|
||||
vm->working_set = (Object**)vm->config.realloc_fn(
|
||||
NULL, sizeof(Object*) * vm->working_set_capacity, NULL);
|
||||
vm->next_gc = INITIAL_GC_SIZE;
|
||||
vm->collecting_garbage = false;
|
||||
vm->min_heap_size = MIN_HEAP_SIZE;
|
||||
vm->heap_fill_percent = HEAP_FILL_PERCENT;
|
||||
|
||||
@ -178,7 +180,12 @@ void pkSetUserData(PKVM* vm, void* user_data) {
|
||||
PkHandle* pkNewModule(PKVM* vm, const char* name) {
|
||||
CHECK_ARG_NULL(name);
|
||||
Module* module = newModuleInternal(vm, name);
|
||||
return vmNewHandle(vm, VAR_OBJ(module));
|
||||
|
||||
vmPushTempRef(vm, &module->_super); // module.
|
||||
PkHandle* handle = vmNewHandle(vm, VAR_OBJ(module));
|
||||
vmPopTempRef(vm); // module.
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void pkRegisterModule(PKVM* vm, PkHandle* module) {
|
||||
@ -218,7 +225,10 @@ PkHandle* pkNewClass(PKVM* vm, const char* name,
|
||||
class_->new_fn = new_fn;
|
||||
class_->delete_fn = delete_fn;
|
||||
|
||||
return vmNewHandle(vm, VAR_OBJ(class_));
|
||||
vmPushTempRef(vm, &class_->_super); // class_.
|
||||
PkHandle* handle = vmNewHandle(vm, VAR_OBJ(class_));
|
||||
vmPopTempRef(vm); // class_.
|
||||
return handle;
|
||||
}
|
||||
|
||||
void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||
@ -236,6 +246,8 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||
|
||||
Function* fn = newFunction(vm, name, (int)strlen(name),
|
||||
class_->owner, true, NULL, NULL);
|
||||
vmPushTempRef(vm, &fn->_super); // fn.
|
||||
|
||||
fn->arity = arity;
|
||||
fn->is_method = true;
|
||||
fn->native = fptr;
|
||||
@ -245,7 +257,9 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||
// won't be garbage collected (class handle has reference to the module).
|
||||
|
||||
Closure* method = newClosure(vm, fn);
|
||||
|
||||
vmPopTempRef(vm); // fn.
|
||||
vmPushTempRef(vm, &method->_super); // method.
|
||||
{
|
||||
if (strcmp(name, CTOR_NAME) == 0) {
|
||||
class_->ctor = method;
|
||||
|
||||
@ -254,6 +268,8 @@ void pkClassAddMethod(PKVM* vm, PkHandle* cls,
|
||||
pkClosureBufferWrite(&class_->methods, vm, method);
|
||||
vmPopTempRef(vm); // method.
|
||||
}
|
||||
}
|
||||
vmPopTempRef(vm); // method.
|
||||
}
|
||||
|
||||
void pkReleaseHandle(PKVM* vm, PkHandle* handle) {
|
||||
@ -765,7 +781,11 @@ bool pkSetAttribute(PKVM* vm, int instance, const char* name, int value) {
|
||||
VALIDATE_SLOT_INDEX(instance);
|
||||
VALIDATE_SLOT_INDEX(value);
|
||||
|
||||
varSetAttrib(vm, SLOT(instance), newString(vm, name), SLOT(value));
|
||||
String* sname = newString(vm, name);
|
||||
vmPushTempRef(vm, &sname->_super); // sname.
|
||||
varSetAttrib(vm, SLOT(instance), sname, SLOT(value));
|
||||
vmPopTempRef(vm); // sname.
|
||||
|
||||
return !VM_HAS_ERROR(vm);
|
||||
}
|
||||
|
||||
@ -776,12 +796,19 @@ bool pkGetAttribute(PKVM* vm, int instance, const char* name,
|
||||
VALIDATE_SLOT_INDEX(instance);
|
||||
VALIDATE_SLOT_INDEX(index);
|
||||
|
||||
SET_SLOT(index, varGetAttrib(vm, SLOT(instance), newString(vm, name)));
|
||||
String* sname = newString(vm, name);
|
||||
vmPushTempRef(vm, &sname->_super); // sname.
|
||||
SET_SLOT(index, varGetAttrib(vm, SLOT(instance), sname));
|
||||
vmPopTempRef(vm); // sname.
|
||||
|
||||
return !VM_HAS_ERROR(vm);
|
||||
}
|
||||
|
||||
static Var _newInstance(PKVM* vm, Class* cls, int argc, Var* argv) {
|
||||
Var instance = preConstructSelf(vm, cls);
|
||||
if (VM_HAS_ERROR(vm)) return VAR_NULL;
|
||||
|
||||
if (IS_OBJ(instance)) vmPushTempRef(vm, AS_OBJ(instance)); // instance.
|
||||
|
||||
Closure* ctor = cls->ctor;
|
||||
while (ctor == NULL) {
|
||||
@ -791,6 +818,7 @@ static Var _newInstance(PKVM* vm, Class* cls, int argc, Var* argv) {
|
||||
}
|
||||
|
||||
if (ctor != NULL) vmCallMethod(vm, instance, ctor, argc, argv, NULL);
|
||||
if (IS_OBJ(instance)) vmPopTempRef(vm); // instance.
|
||||
|
||||
return instance;
|
||||
}
|
||||
@ -860,8 +888,12 @@ bool pkCallMethod(PKVM* vm, int instance, const char* method,
|
||||
if (ret >= 0) VALIDATE_SLOT_INDEX(ret);
|
||||
|
||||
bool is_method = false;
|
||||
Var callable = getMethod(vm, SLOT(instance), newString(vm, method),
|
||||
String* smethod = newString(vm, method);
|
||||
vmPushTempRef(vm, &smethod->_super); // smethod.
|
||||
Var callable = getMethod(vm, SLOT(instance), smethod,
|
||||
&is_method);
|
||||
vmPopTempRef(vm); // smethod.
|
||||
|
||||
if (VM_HAS_ERROR(vm)) return false;
|
||||
|
||||
// Calls a class == construct.
|
||||
|
@ -97,7 +97,7 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) {
|
||||
switch (obj->type) {
|
||||
case OBJ_STRING: {
|
||||
vm->bytes_allocated += sizeof(String);
|
||||
vm->bytes_allocated += ((size_t)((String*)obj)->length + 1);
|
||||
vm->bytes_allocated += ((size_t)((String*)obj)->capacity);
|
||||
} break;
|
||||
|
||||
case OBJ_LIST: {
|
||||
@ -149,11 +149,13 @@ static void popMarkedObjectsInternal(Object* obj, PKVM* vm) {
|
||||
|
||||
markObject(vm, &func->owner->_super);
|
||||
|
||||
if (!func->is_native) {
|
||||
// If a garbage collection is triggered when allocating a name string
|
||||
// for this function, it's [fn] property will be NULL.
|
||||
if (!func->is_native && func->fn != NULL) {
|
||||
Fn* fn = func->fn;
|
||||
vm->bytes_allocated += sizeof(Fn);
|
||||
|
||||
vm->bytes_allocated += sizeof(uint8_t)* fn->opcodes.capacity;
|
||||
vm->bytes_allocated += sizeof(uint8_t) * fn->opcodes.capacity;
|
||||
vm->bytes_allocated += sizeof(uint32_t) * fn->oplines.capacity;
|
||||
}
|
||||
} break;
|
||||
@ -293,14 +295,14 @@ String* newStringVaArgs(PKVM* vm, const char* fmt, va_list args) {
|
||||
|
||||
List* newList(PKVM* vm, uint32_t size) {
|
||||
List* list = ALLOCATE(vm, List);
|
||||
vmPushTempRef(vm, &list->_super);
|
||||
vmPushTempRef(vm, &list->_super); // list.
|
||||
varInitObject(&list->_super, vm, OBJ_LIST);
|
||||
pkVarBufferInit(&list->elements);
|
||||
if (size > 0) {
|
||||
pkVarBufferFill(&list->elements, vm, VAR_NULL, size);
|
||||
list->elements.count = 0;
|
||||
}
|
||||
vmPopTempRef(vm);
|
||||
vmPopTempRef(vm); // list.
|
||||
return list;
|
||||
}
|
||||
|
||||
@ -323,13 +325,9 @@ Range* newRange(PKVM* vm, double from, double to) {
|
||||
|
||||
Module* newModule(PKVM* vm) {
|
||||
Module* module = ALLOCATE(vm, Module);
|
||||
memset(module, 0, sizeof(Module));
|
||||
varInitObject(&module->_super, vm, OBJ_MODULE);
|
||||
|
||||
module->path = NULL;
|
||||
module->name = NULL;
|
||||
module->initialized = false;
|
||||
module->body = NULL;
|
||||
|
||||
pkVarBufferInit(&module->globals);
|
||||
pkUintBufferInit(&module->global_names);
|
||||
pkVarBufferInit(&module->constants);
|
||||
@ -343,6 +341,7 @@ Function* newFunction(PKVM* vm, const char* name, int length,
|
||||
int* fn_index) {
|
||||
|
||||
Function* func = ALLOCATE(vm, Function);
|
||||
memset(func, 0, sizeof(Function));
|
||||
varInitObject(&func->_super, vm, OBJ_FUNC);
|
||||
|
||||
vmPushTempRef(vm, &func->_super); // func
|
||||
@ -388,10 +387,7 @@ Closure* newClosure(PKVM* vm, Function* fn) {
|
||||
varInitObject(&closure->_super, vm, OBJ_CLOSURE);
|
||||
|
||||
closure->fn = fn;
|
||||
|
||||
for (int i = 0; i < fn->upvalue_count; i++) {
|
||||
closure->upvalues[i] = NULL;
|
||||
}
|
||||
memset(closure->upvalues, 0, sizeof(Upvalue*) * fn->upvalue_count);
|
||||
|
||||
return closure;
|
||||
}
|
||||
@ -411,11 +407,15 @@ Fiber* newFiber(PKVM* vm, Closure* closure) {
|
||||
|
||||
Fiber* fiber = ALLOCATE(vm, Fiber);
|
||||
|
||||
// Not sure why this memset is needed here. If it doesn't then remove it.
|
||||
// If a garbage collection is triggered here, and the fiber isn't fully
|
||||
// constructed -> it's fields are not intialized yet, would cause a crash
|
||||
// so we need to memset here.
|
||||
memset(fiber, 0, sizeof(Fiber));
|
||||
|
||||
varInitObject(&fiber->_super, vm, OBJ_FIBER);
|
||||
|
||||
vmPushTempRef(vm, &fiber->_super); // fiber.
|
||||
|
||||
fiber->state = FIBER_NEW;
|
||||
fiber->closure = closure;
|
||||
|
||||
@ -431,6 +431,7 @@ Fiber* newFiber(PKVM* vm, Closure* closure) {
|
||||
if (stack_size == 0) stack_size++;
|
||||
|
||||
fiber->stack = ALLOCATE_ARRAY(vm, Var, stack_size);
|
||||
ASSERT(fiber->stack != NULL, "Out of memory");
|
||||
fiber->stack_size = stack_size;
|
||||
fiber->ret = fiber->stack;
|
||||
fiber->sp = fiber->stack + 1;
|
||||
@ -462,6 +463,8 @@ Fiber* newFiber(PKVM* vm, Closure* closure) {
|
||||
// but if we're trying to debut it may crash when dumping the return value).
|
||||
*fiber->ret = VAR_NULL;
|
||||
|
||||
vmPopTempRef(vm); // fiber.
|
||||
|
||||
return fiber;
|
||||
}
|
||||
|
||||
@ -470,6 +473,12 @@ Class* newClass(PKVM* vm, const char* name, int length,
|
||||
const char* docstring, int* cls_index) {
|
||||
|
||||
Class* cls = ALLOCATE(vm, Class);
|
||||
|
||||
// If the garbage collection trigged bellow while allocating for
|
||||
// [cls->name] or other properties, the calss is in the root (temp ref)
|
||||
// and it's property [cls->name] is un initialized, which cause a crash.
|
||||
memset(cls, 0, sizeof(Class));
|
||||
|
||||
varInitObject(&cls->_super, vm, OBJ_CLASS);
|
||||
|
||||
vmPushTempRef(vm, &cls->_super); // class.
|
||||
@ -477,12 +486,7 @@ Class* newClass(PKVM* vm, const char* name, int length,
|
||||
pkClosureBufferInit(&cls->methods);
|
||||
|
||||
cls->class_of = PK_INSTANCE;
|
||||
cls->owner = NULL;
|
||||
cls->super_class = super;
|
||||
cls->docstring = NULL;
|
||||
cls->ctor = NULL;
|
||||
cls->new_fn = NULL;
|
||||
cls->delete_fn = NULL;
|
||||
|
||||
// Builtin types doesn't belongs to a module.
|
||||
if (module != NULL) {
|
||||
@ -504,36 +508,38 @@ Instance* newInstance(PKVM* vm, Class* cls) {
|
||||
"class with newInstance() function.");
|
||||
|
||||
Instance* inst = ALLOCATE(vm, Instance);
|
||||
memset(inst, 0, sizeof(Instance));
|
||||
varInitObject(&inst->_super, vm, OBJ_INST);
|
||||
|
||||
vmPushTempRef(vm, &inst->_super); // inst.
|
||||
|
||||
inst->cls = cls;
|
||||
inst->attribs = newMap(vm);
|
||||
|
||||
if (cls->new_fn != NULL) {
|
||||
inst->native = cls->new_fn(vm);
|
||||
} else {
|
||||
inst->native = NULL;
|
||||
}
|
||||
|
||||
inst->attribs = newMap(vm);
|
||||
|
||||
vmPopTempRef(vm); // inst.
|
||||
return inst;
|
||||
}
|
||||
|
||||
List* rangeAsList(PKVM* vm, Range* self) {
|
||||
List* list;
|
||||
|
||||
if (self->from < self->to) {
|
||||
list = newList(vm, (uint32_t)(self->to - self->from));
|
||||
List* list = newList(vm, (uint32_t)(self->to - self->from));
|
||||
vmPushTempRef(vm, &list->_super); // list.
|
||||
for (double i = self->from; i < self->to; i++) {
|
||||
pkVarBufferWrite(&list->elements, vm, VAR_NUM(i));
|
||||
}
|
||||
return list;
|
||||
vmPopTempRef(vm); // list.
|
||||
|
||||
} else {
|
||||
list = newList(vm, 0);
|
||||
return list;
|
||||
}
|
||||
|
||||
return list;
|
||||
return newList(vm, 0);
|
||||
}
|
||||
|
||||
String* stringLower(PKVM* vm, String* self) {
|
||||
|
@ -27,10 +27,24 @@ void* vmRealloc(PKVM* vm, void* memory, size_t old_size, size_t new_size) {
|
||||
// Track the total allocated memory of the VM to trigger the GC.
|
||||
// if vmRealloc is called for freeing, the old_size would be 0 since
|
||||
// deallocated bytes are traced by garbage collector.
|
||||
//
|
||||
// If we're running a garbage collection, VM's byte allocated will be
|
||||
// re-calculated at vmCollectGarbage() which is equal to the remaining
|
||||
// objects after clening the garbage. And clearing a garbage will
|
||||
// recursively invoke this function so we shouldn't modify it.
|
||||
if (!vm->collecting_garbage) {
|
||||
vm->bytes_allocated += new_size - old_size;
|
||||
}
|
||||
|
||||
// If we're garbage collecting no new allocation is allowed.
|
||||
ASSERT(!vm->collecting_garbage || new_size == 0,
|
||||
"No new allocation is allowed while garbage collection is running.");
|
||||
|
||||
if (new_size > 0 && vm->bytes_allocated > vm->next_gc) {
|
||||
ASSERT(vm->collecting_garbage == false, OOPS);
|
||||
vm->collecting_garbage = true;
|
||||
vmCollectGarbage(vm);
|
||||
vm->collecting_garbage = false;
|
||||
}
|
||||
|
||||
#if TRACE_MEMORY
|
||||
@ -99,10 +113,6 @@ Module* vmGetModule(PKVM* vm, String* key) {
|
||||
|
||||
void vmCollectGarbage(PKVM* vm) {
|
||||
|
||||
// Reset VM's bytes_allocated value and count it again so that we don't
|
||||
// required to know the size of each object that'll be freeing.
|
||||
vm->bytes_allocated = 0;
|
||||
|
||||
// Mark builtin functions.
|
||||
for (int i = 0; i < vm->builtins_count; i++) {
|
||||
markObject(vm, &vm->builtins_funcs[i]->_super);
|
||||
@ -139,11 +149,23 @@ void vmCollectGarbage(PKVM* vm) {
|
||||
markObject(vm, &vm->fiber->_super);
|
||||
}
|
||||
|
||||
// Reset VM's bytes_allocated value and count it again so that we don't
|
||||
// required to know the size of each object that'll be freeing.
|
||||
vm->bytes_allocated = 0;
|
||||
|
||||
// Pop the marked objects from the working set and push all of it's
|
||||
// referenced objects. This will repeat till no more objects left in the
|
||||
// working set.
|
||||
popMarkedObjects(vm);
|
||||
|
||||
// Now [vm->bytes_allocated] is equal to the number of bytes allocated for
|
||||
// the root objects which are marked above. Since we're garbage collecting
|
||||
// freeObject() shouldn't modify vm->bytes_allocated. We ensure this by
|
||||
// copying the value to [bytes_allocated] and check after freeing.
|
||||
#ifdef DEBUG
|
||||
size_t bytes_allocated = vm->bytes_allocated;
|
||||
#endif
|
||||
|
||||
// Now sweep all the un-marked objects in then link list and remove them
|
||||
// from the chain.
|
||||
|
||||
@ -166,6 +188,10 @@ void vmCollectGarbage(PKVM* vm) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ASSERT(bytes_allocated = vm->bytes_allocated, OOPS);
|
||||
#endif
|
||||
|
||||
// Next GC heap size will be change depends on the byte we've left with now,
|
||||
// and the [heap_fill_percent].
|
||||
vm->next_gc = vm->bytes_allocated + (
|
||||
@ -937,7 +963,9 @@ L_vm_main_loop:
|
||||
ASSERT_INDEX(index, module->constants.count);
|
||||
ASSERT(IS_OBJ_TYPE(module->constants.data[index], OBJ_FUNC), OOPS);
|
||||
Function* fn = (Function*)AS_OBJ(module->constants.data[index]);
|
||||
|
||||
Closure* closure = newClosure(vm, fn);
|
||||
vmPushTempRef(vm, &closure->_super); // closure.
|
||||
|
||||
// Capture the vaupes.
|
||||
for (int i = 0; i < fn->upvalue_count; i++) {
|
||||
@ -954,6 +982,8 @@ L_vm_main_loop:
|
||||
}
|
||||
|
||||
PUSH(VAR_OBJ(closure));
|
||||
vmPopTempRef(vm); // closure.
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,10 @@ struct PKVM {
|
||||
// The number of bytes that'll trigger the next GC.
|
||||
size_t next_gc;
|
||||
|
||||
// True if PKVM is running a garbage collection, and no new allocation is
|
||||
// allowed in this phase.
|
||||
bool collecting_garbage;
|
||||
|
||||
// Minimum size the heap could get.
|
||||
size_t min_heap_size;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#include "libs.h"
|
||||
#endif
|
||||
|
||||
// Standard libraries.
|
||||
|
||||
void registerModuleMath(PKVM* vm);
|
||||
void registerModuleTypes(PKVM* vm);
|
||||
void registerModuleTime(PKVM* vm);
|
||||
@ -15,6 +17,7 @@ void registerModuleIO(PKVM* vm);
|
||||
void registerModulePath(PKVM* vm);
|
||||
void registerModuleDummy(PKVM* vm);
|
||||
|
||||
// Registers the modules.
|
||||
void registerLibs(PKVM* vm) {
|
||||
registerModuleMath(vm);
|
||||
registerModuleTypes(vm);
|
||||
@ -24,6 +27,6 @@ void registerLibs(PKVM* vm) {
|
||||
registerModuleDummy(vm);
|
||||
}
|
||||
|
||||
// Cleanup the modules.
|
||||
void cleanupLibs(PKVM* vm) {
|
||||
|
||||
}
|
||||
|
@ -144,6 +144,10 @@ DEF(_dummyCallMethod,
|
||||
if (!pkCallMethod(vm, 1, method, 2, 3, 0)) return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleDummy(PKVM* vm) {
|
||||
|
||||
PkHandle* dummy = pkNewModule(vm, "dummy");
|
||||
|
@ -402,6 +402,10 @@ DEF(_fileTell, "") {
|
||||
pkSetSlotNumber(vm, 0, (double) ftell(file->fp));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleIO(PKVM* vm) {
|
||||
|
||||
PkHandle* io = pkNewModule(vm, "io");
|
||||
|
@ -181,6 +181,20 @@ DEF(stdMathRound,
|
||||
pkSetSlotNumber(vm, 0, round(num));
|
||||
}
|
||||
|
||||
DEF(stdMathRand,
|
||||
"rand() -> num\n"
|
||||
"Return a random runber in the range of 0..0x7fff.") {
|
||||
|
||||
// RAND_MAX is implementation dependent but is guaranteed to be at least
|
||||
// 0x7fff on any standard library implementation.
|
||||
// https://www.cplusplus.com/reference/cstdlib/RAND_MAX/
|
||||
pkSetSlotNumber(vm, 0, rand() % 0x7fff);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleMath(PKVM* vm) {
|
||||
|
||||
PkHandle* math = pkNewModule(vm, "math");
|
||||
@ -208,6 +222,7 @@ void registerModuleMath(PKVM* vm) {
|
||||
pkModuleAddFunction(vm, math, "atan", stdMathArcTangent, 1);
|
||||
pkModuleAddFunction(vm, math, "log10", stdMathLog10, 1);
|
||||
pkModuleAddFunction(vm, math, "round", stdMathRound, 1);
|
||||
pkModuleAddFunction(vm, math, "rand", stdMathRand, 0);
|
||||
|
||||
pkRegisterModule(vm, math);
|
||||
pkReleaseHandle(vm, math);
|
||||
|
@ -14,7 +14,7 @@
|
||||
// Refactor the bellow macro includes.
|
||||
|
||||
#define _CWALK_IMPL
|
||||
#include "tp_cwalk.h" //<< AMALG_INLINE >>
|
||||
#include "thirdparty/cwalk/cwalk.h" //<< AMALG_INLINE >>
|
||||
#undef _CWALK_IMPL
|
||||
|
||||
#include <errno.h>
|
||||
@ -28,7 +28,7 @@
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "tp_dirent.h" //<< AMALG_INLINE >>
|
||||
#include "thirdparty/dirent/dirent.h" //<< AMALG_INLINE >>
|
||||
|
||||
// access() function flag defines for windows.
|
||||
// Reference :https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=msvc-170#remarks
|
||||
@ -339,6 +339,10 @@ DEF(_pathIsDir, "") {
|
||||
pkSetSlotBool(vm, 0, pathIsDir(path));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModulePath(PKVM* vm) {
|
||||
PkHandle* path = pkNewModule(vm, "path");
|
||||
|
||||
|
@ -47,6 +47,10 @@ DEF(_timeSleep,
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleTime(PKVM* vm) {
|
||||
PkHandle* time = pkNewModule(vm, "time");
|
||||
|
||||
|
@ -257,7 +257,7 @@ void _vectorRepr(PKVM* vm) {
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* REGISTER TYPES */
|
||||
/* MODULE REGISTER */
|
||||
/*****************************************************************************/
|
||||
|
||||
void registerModuleTypes(PKVM* vm) {
|
||||
|
21
src/libs/thirdparty/cwalk/LICENSE
vendored
Normal file
21
src/libs/thirdparty/cwalk/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Leonard Iklé
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,27 +1,3 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020 Leonard Iklé
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CWK_LIBRARY_H
|
||||
#define CWK_LIBRARY_H
|
||||
|
21
src/libs/thirdparty/dirent/LICENSE
vendored
Normal file
21
src/libs/thirdparty/dirent/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 1998-2019 Toni Ronkko
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,27 +1,3 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 1998-2019 Toni Ronkko
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dirent interface for Microsoft Visual Studio
|
||||
*
|
Loading…
Reference in New Issue
Block a user