mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 13:15:55 +08:00
commit
3b88205b1d
@ -23,6 +23,7 @@ PK_API = "pk_api"
|
|||||||
PK_API_TYPE = "PkNativeApi"
|
PK_API_TYPE = "PkNativeApi"
|
||||||
PK_API_INIT = 'pkInitApi'
|
PK_API_INIT = 'pkInitApi'
|
||||||
PK_EXPORT_MODULE = 'pkExportModule'
|
PK_EXPORT_MODULE = 'pkExportModule'
|
||||||
|
PK_CLEANUP_MODULE = 'pkCleanupModule'
|
||||||
|
|
||||||
API_DEF = f'''\
|
API_DEF = f'''\
|
||||||
static {PK_API_TYPE} {PK_API};
|
static {PK_API_TYPE} {PK_API};
|
||||||
@ -147,6 +148,7 @@ def generate():
|
|||||||
|
|
||||||
fp.write(f'#define PK_API_INIT_FN_NAME "{PK_API_INIT}" \n')
|
fp.write(f'#define PK_API_INIT_FN_NAME "{PK_API_INIT}" \n')
|
||||||
fp.write(f'#define PK_EXPORT_FN_NAME "{PK_EXPORT_MODULE}" \n\n')
|
fp.write(f'#define PK_EXPORT_FN_NAME "{PK_EXPORT_MODULE}" \n\n')
|
||||||
|
fp.write(f'#define PK_CLEANUP_FN_NAME "{PK_CLEANUP_MODULE}" \n\n')
|
||||||
fp.write(f'typedef void (*{PK_API_INIT}Fn)({PK_API_TYPE}*);\n')
|
fp.write(f'typedef void (*{PK_API_INIT}Fn)({PK_API_TYPE}*);\n')
|
||||||
fp.write(f'typedef PkHandle* (*{PK_EXPORT_MODULE}Fn)(PKVM*);\n')
|
fp.write(f'typedef PkHandle* (*{PK_EXPORT_MODULE}Fn)(PKVM*);\n')
|
||||||
fp.write(f'\n')
|
fp.write(f'\n')
|
||||||
|
@ -2038,6 +2038,7 @@ static void exprName(Compiler* compiler) {
|
|||||||
void exprOr(Compiler* compiler) {
|
void exprOr(Compiler* compiler) {
|
||||||
emitOpcode(compiler, OP_OR);
|
emitOpcode(compiler, OP_OR);
|
||||||
int orpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
int orpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||||
|
skipNewLines(compiler);
|
||||||
parsePrecedence(compiler, PREC_LOGICAL_OR);
|
parsePrecedence(compiler, PREC_LOGICAL_OR);
|
||||||
patchJump(compiler, orpatch);
|
patchJump(compiler, orpatch);
|
||||||
}
|
}
|
||||||
@ -2045,6 +2046,7 @@ void exprOr(Compiler* compiler) {
|
|||||||
void exprAnd(Compiler* compiler) {
|
void exprAnd(Compiler* compiler) {
|
||||||
emitOpcode(compiler, OP_AND);
|
emitOpcode(compiler, OP_AND);
|
||||||
int andpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
int andpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||||
|
skipNewLines(compiler);
|
||||||
parsePrecedence(compiler, PREC_LOGICAL_AND);
|
parsePrecedence(compiler, PREC_LOGICAL_AND);
|
||||||
patchJump(compiler, andpatch);
|
patchJump(compiler, andpatch);
|
||||||
}
|
}
|
||||||
|
@ -826,6 +826,14 @@ void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
|
|||||||
SET_SLOT(index, handle->value);
|
SET_SLOT(index, handle->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pkGetSlotHash(PKVM* vm, int index) {
|
||||||
|
CHECK_FIBER_EXISTS(vm);
|
||||||
|
VALIDATE_SLOT_INDEX(index);
|
||||||
|
Var value = SLOT(index);
|
||||||
|
ASSERT(!IS_OBJ(value) || isObjectHashable(AS_OBJ(value)->type), OOPS);
|
||||||
|
return varHashValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
bool pkSetAttribute(PKVM* vm, int instance, const char* name, int value) {
|
bool pkSetAttribute(PKVM* vm, int instance, const char* name, int value) {
|
||||||
CHECK_FIBER_EXISTS(vm);
|
CHECK_FIBER_EXISTS(vm);
|
||||||
CHECK_ARG_NULL(name);
|
CHECK_ARG_NULL(name);
|
||||||
|
@ -801,7 +801,7 @@ String* toString(PKVM* vm, const Var value);
|
|||||||
|
|
||||||
// Returns the representation version of the [value], similar to python's
|
// Returns the representation version of the [value], similar to python's
|
||||||
// __repr__() method.
|
// __repr__() method.
|
||||||
String * toRepr(PKVM * vm, const Var value);
|
String* toRepr(PKVM * vm, const Var value);
|
||||||
|
|
||||||
// Returns the truthy value of the var.
|
// Returns the truthy value of the var.
|
||||||
bool toBool(Var v);
|
bool toBool(Var v);
|
||||||
|
@ -426,6 +426,10 @@ PK_PUBLIC void pkSetSlotStringFmt(PKVM* vm, int index, const char* fmt, ...);
|
|||||||
// 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);
|
||||||
|
|
||||||
|
// Returns the hash of the [index] slot value. The value at the [index] must be
|
||||||
|
// hashable.
|
||||||
|
PK_PUBLIC uint32_t pkGetSlotHash(PKVM* vm, int index);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* POCKET FFI */
|
/* POCKET FFI */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -54,6 +54,7 @@ typedef void (*pkSetSlotNumber_t)(PKVM*, int, double);
|
|||||||
typedef void (*pkSetSlotString_t)(PKVM*, int, const char*);
|
typedef void (*pkSetSlotString_t)(PKVM*, int, const char*);
|
||||||
typedef void (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
typedef void (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
||||||
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
||||||
|
typedef uint32_t (*pkGetSlotHash_t)(PKVM*, int);
|
||||||
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
||||||
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
||||||
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
||||||
@ -113,6 +114,7 @@ typedef struct {
|
|||||||
pkSetSlotString_t pkSetSlotString_ptr;
|
pkSetSlotString_t pkSetSlotString_ptr;
|
||||||
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
||||||
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
||||||
|
pkGetSlotHash_t pkGetSlotHash_ptr;
|
||||||
pkPlaceSelf_t pkPlaceSelf_ptr;
|
pkPlaceSelf_t pkPlaceSelf_ptr;
|
||||||
pkGetClass_t pkGetClass_ptr;
|
pkGetClass_t pkGetClass_ptr;
|
||||||
pkNewInstance_t pkNewInstance_ptr;
|
pkNewInstance_t pkNewInstance_ptr;
|
||||||
@ -129,8 +131,9 @@ typedef struct {
|
|||||||
pkImportModule_t pkImportModule_ptr;
|
pkImportModule_t pkImportModule_ptr;
|
||||||
} PkNativeApi;
|
} PkNativeApi;
|
||||||
|
|
||||||
#define PK_API_INIT_FN_NAME "pkInitApi"
|
#define PK_API_INIT_FN_NAME "pkInitApi"
|
||||||
#define PK_EXPORT_FN_NAME "pkExportModule"
|
#define PK_EXPORT_FN_NAME "pkExportModule"
|
||||||
|
#define PK_CLEANUP_FN_NAME "pkCleanupModule"
|
||||||
|
|
||||||
typedef void (*pkInitApiFn)(PkNativeApi*);
|
typedef void (*pkInitApiFn)(PkNativeApi*);
|
||||||
typedef PkHandle* (*pkExportModuleFn)(PKVM*);
|
typedef PkHandle* (*pkExportModuleFn)(PKVM*);
|
||||||
@ -184,6 +187,7 @@ PkNativeApi pkMakeNativeAPI() {
|
|||||||
api.pkSetSlotString_ptr = pkSetSlotString;
|
api.pkSetSlotString_ptr = pkSetSlotString;
|
||||||
api.pkSetSlotStringLength_ptr = pkSetSlotStringLength;
|
api.pkSetSlotStringLength_ptr = pkSetSlotStringLength;
|
||||||
api.pkSetSlotHandle_ptr = pkSetSlotHandle;
|
api.pkSetSlotHandle_ptr = pkSetSlotHandle;
|
||||||
|
api.pkGetSlotHash_ptr = pkGetSlotHash;
|
||||||
api.pkPlaceSelf_ptr = pkPlaceSelf;
|
api.pkPlaceSelf_ptr = pkPlaceSelf;
|
||||||
api.pkGetClass_ptr = pkGetClass;
|
api.pkGetClass_ptr = pkGetClass;
|
||||||
api.pkNewInstance_ptr = pkNewInstance;
|
api.pkNewInstance_ptr = pkNewInstance;
|
||||||
|
@ -96,7 +96,7 @@ typedef struct {
|
|||||||
bool closed; // True if the file isn't closed yet.
|
bool closed; // True if the file isn't closed yet.
|
||||||
} File;
|
} File;
|
||||||
|
|
||||||
void* _newFile(PKVM* vm) {
|
void* _fileNew(PKVM* vm) {
|
||||||
File* file = pkRealloc(vm, NULL, sizeof(File));
|
File* file = pkRealloc(vm, NULL, sizeof(File));
|
||||||
ASSERT(file != NULL, "pkRealloc failed.");
|
ASSERT(file != NULL, "pkRealloc failed.");
|
||||||
file->closed = true;
|
file->closed = true;
|
||||||
@ -105,7 +105,7 @@ void* _newFile(PKVM* vm) {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deleteFile(PKVM* vm, void* ptr) {
|
void _fileDelete(PKVM* vm, void* ptr) {
|
||||||
File* file = (File*)ptr;
|
File* file = (File*)ptr;
|
||||||
if (!file->closed) {
|
if (!file->closed) {
|
||||||
ASSERT(file->fp != NULL, OOPS);
|
ASSERT(file->fp != NULL, OOPS);
|
||||||
@ -440,7 +440,7 @@ void registerModuleIO(PKVM* vm) {
|
|||||||
pkModuleAddFunction(vm, io, "write", _ioWrite, 2);
|
pkModuleAddFunction(vm, io, "write", _ioWrite, 2);
|
||||||
pkModuleAddFunction(vm, io, "flush", _ioFlush, 0);
|
pkModuleAddFunction(vm, io, "flush", _ioFlush, 0);
|
||||||
|
|
||||||
PkHandle* cls_file = pkNewClass(vm, "File", NULL, io, _newFile, _deleteFile);
|
PkHandle* cls_file = pkNewClass(vm, "File", NULL, io, _fileNew, _fileDelete);
|
||||||
pkClassAddMethod(vm, cls_file, "open", _fileOpen, -1);
|
pkClassAddMethod(vm, cls_file, "open", _fileOpen, -1);
|
||||||
pkClassAddMethod(vm, cls_file, "read", _fileRead, -1);
|
pkClassAddMethod(vm, cls_file, "read", _fileRead, -1);
|
||||||
pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1);
|
pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1);
|
||||||
|
@ -97,6 +97,9 @@ PkHandle* osImportDL(PKVM* vm, void* handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void osUnloadDL(PKVM* vm, void* handle) {
|
void osUnloadDL(PKVM* vm, void* handle) {
|
||||||
|
pkExportModuleFn cleanup_fn = \
|
||||||
|
(pkExportModuleFn)GetProcAddress((HMODULE) handle, PK_CLEANUP_FN_NAME);
|
||||||
|
if (cleanup_fn != NULL) cleanup_fn(vm);
|
||||||
FreeLibrary((HMODULE) handle);
|
FreeLibrary((HMODULE) handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,16 +8,44 @@
|
|||||||
|
|
||||||
#ifndef PK_AMALGAMATED
|
#ifndef PK_AMALGAMATED
|
||||||
#include "libs.h"
|
#include "libs.h"
|
||||||
|
#include "../core/value.h"
|
||||||
|
#include "../core/vm.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEF(_typesHashable,
|
||||||
|
"types.hashable(value:Var) -> Bool\n"
|
||||||
|
"Returns true if the [value] is hashable.") {
|
||||||
|
|
||||||
|
// Get argument 1 directly.
|
||||||
|
ASSERT(vm->fiber != NULL, OOPS);
|
||||||
|
ASSERT(1 < pkGetSlotsCount(vm), OOPS);
|
||||||
|
Var value = vm->fiber->ret[1];
|
||||||
|
|
||||||
|
if (!IS_OBJ(value)) pkSetSlotBool(vm, 0, true);
|
||||||
|
else pkSetSlotBool(vm, 0, isObjectHashable(AS_OBJ(value)->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF(_typesHash,
|
||||||
|
"types.hash(value:Var) -> Number\n"
|
||||||
|
"Returns the hash of the [value]") {
|
||||||
|
|
||||||
|
// Get argument 1 directly.
|
||||||
|
ASSERT(vm->fiber != NULL, OOPS);
|
||||||
|
ASSERT(1 < pkGetSlotsCount(vm), OOPS);
|
||||||
|
Var value = vm->fiber->ret[1];
|
||||||
|
|
||||||
|
if (IS_OBJ(value) && !isObjectHashable(AS_OBJ(value)->type)) {
|
||||||
|
pkSetRuntimeErrorFmt(vm, "Type '%s' is not hashable.", varTypeName(value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkSetSlotNumber(vm, 0, varHashValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* BYTE BUFFER */
|
/* BYTE BUFFER */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#ifndef PK_AMALGAMATED
|
|
||||||
#include "../core/value.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void* _bytebuffNew(PKVM* vm) {
|
void* _bytebuffNew(PKVM* vm) {
|
||||||
pkByteBuffer* self = pkRealloc(vm, NULL, sizeof(pkByteBuffer));
|
pkByteBuffer* self = pkRealloc(vm, NULL, sizeof(pkByteBuffer));
|
||||||
pkByteBufferInit(self);
|
pkByteBufferInit(self);
|
||||||
@ -263,6 +291,9 @@ void _vectorRepr(PKVM* vm) {
|
|||||||
void registerModuleTypes(PKVM* vm) {
|
void registerModuleTypes(PKVM* vm) {
|
||||||
PkHandle* types = pkNewModule(vm, "types");
|
PkHandle* types = pkNewModule(vm, "types");
|
||||||
|
|
||||||
|
pkModuleAddFunction(vm, types, "hashable", _typesHashable, 1);
|
||||||
|
pkModuleAddFunction(vm, types, "hash", _typesHash, 1);
|
||||||
|
|
||||||
PkHandle* cls_byte_buffer = pkNewClass(vm, "ByteBuffer", NULL, types,
|
PkHandle* cls_byte_buffer = pkNewClass(vm, "ByteBuffer", NULL, types,
|
||||||
_bytebuffNew, _bytebuffDelete);
|
_bytebuffNew, _bytebuffDelete);
|
||||||
|
|
||||||
|
@ -60,6 +60,13 @@ if a and b then assert(false) end
|
|||||||
if a or b then val = 42 else assert(false) end assert(val == 42)
|
if a or b then val = 42 else assert(false) end assert(val == 42)
|
||||||
if get_true() or false then val = 12 end assert(val == 12)
|
if get_true() or false then val = 12 end assert(val == 12)
|
||||||
|
|
||||||
|
if (get_true() or false) and ## New line after and.
|
||||||
|
((a or b) or (a and b))
|
||||||
|
assert(true) ## Reachable.
|
||||||
|
else
|
||||||
|
assert(false) ## Unreachable
|
||||||
|
end
|
||||||
|
|
||||||
## Newer logical or implementation.
|
## Newer logical or implementation.
|
||||||
## a or b === if (a) return a else return b
|
## a or b === if (a) return a else return b
|
||||||
## a and b === if (!a) return a else return b
|
## a and b === if (!a) return a else return b
|
||||||
|
@ -51,6 +51,7 @@ typedef void (*pkSetSlotNumber_t)(PKVM*, int, double);
|
|||||||
typedef void (*pkSetSlotString_t)(PKVM*, int, const char*);
|
typedef void (*pkSetSlotString_t)(PKVM*, int, const char*);
|
||||||
typedef void (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
typedef void (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
||||||
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
||||||
|
typedef uint32_t (*pkGetSlotHash_t)(PKVM*, int);
|
||||||
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
||||||
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
||||||
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
||||||
@ -110,6 +111,7 @@ typedef struct {
|
|||||||
pkSetSlotString_t pkSetSlotString_ptr;
|
pkSetSlotString_t pkSetSlotString_ptr;
|
||||||
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
||||||
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
||||||
|
pkGetSlotHash_t pkGetSlotHash_ptr;
|
||||||
pkPlaceSelf_t pkPlaceSelf_ptr;
|
pkPlaceSelf_t pkPlaceSelf_ptr;
|
||||||
pkGetClass_t pkGetClass_ptr;
|
pkGetClass_t pkGetClass_ptr;
|
||||||
pkNewInstance_t pkNewInstance_ptr;
|
pkNewInstance_t pkNewInstance_ptr;
|
||||||
@ -172,6 +174,7 @@ PK_EXPORT void pkInitApi(PkNativeApi* api) {
|
|||||||
pk_api.pkSetSlotString_ptr = api->pkSetSlotString_ptr;
|
pk_api.pkSetSlotString_ptr = api->pkSetSlotString_ptr;
|
||||||
pk_api.pkSetSlotStringLength_ptr = api->pkSetSlotStringLength_ptr;
|
pk_api.pkSetSlotStringLength_ptr = api->pkSetSlotStringLength_ptr;
|
||||||
pk_api.pkSetSlotHandle_ptr = api->pkSetSlotHandle_ptr;
|
pk_api.pkSetSlotHandle_ptr = api->pkSetSlotHandle_ptr;
|
||||||
|
pk_api.pkGetSlotHash_ptr = api->pkGetSlotHash_ptr;
|
||||||
pk_api.pkPlaceSelf_ptr = api->pkPlaceSelf_ptr;
|
pk_api.pkPlaceSelf_ptr = api->pkPlaceSelf_ptr;
|
||||||
pk_api.pkGetClass_ptr = api->pkGetClass_ptr;
|
pk_api.pkGetClass_ptr = api->pkGetClass_ptr;
|
||||||
pk_api.pkNewInstance_ptr = api->pkNewInstance_ptr;
|
pk_api.pkNewInstance_ptr = api->pkNewInstance_ptr;
|
||||||
@ -360,6 +363,10 @@ void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
|
|||||||
pk_api.pkSetSlotHandle_ptr(vm, index, handle);
|
pk_api.pkSetSlotHandle_ptr(vm, index, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t pkGetSlotHash(PKVM* vm, int index) {
|
||||||
|
return pk_api.pkGetSlotHash_ptr(vm, index);
|
||||||
|
}
|
||||||
|
|
||||||
void pkPlaceSelf(PKVM* vm, int index) {
|
void pkPlaceSelf(PKVM* vm, int index) {
|
||||||
pk_api.pkPlaceSelf_ptr(vm, index);
|
pk_api.pkPlaceSelf_ptr(vm, index);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user