mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-03-04 13:15:55 +08:00
types hash api implemented
and, or operators supports new line after the first expression.
This commit is contained in:
parent
c48cc7ea01
commit
4f33aa7e25
@ -23,6 +23,7 @@ PK_API = "pk_api"
|
||||
PK_API_TYPE = "PkNativeApi"
|
||||
PK_API_INIT = 'pkInitApi'
|
||||
PK_EXPORT_MODULE = 'pkExportModule'
|
||||
PK_CLEANUP_MODULE = 'pkCleanupModule'
|
||||
|
||||
API_DEF = f'''\
|
||||
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_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 PkHandle* (*{PK_EXPORT_MODULE}Fn)(PKVM*);\n')
|
||||
fp.write(f'\n')
|
||||
|
@ -2038,6 +2038,7 @@ static void exprName(Compiler* compiler) {
|
||||
void exprOr(Compiler* compiler) {
|
||||
emitOpcode(compiler, OP_OR);
|
||||
int orpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||
skipNewLines(compiler);
|
||||
parsePrecedence(compiler, PREC_LOGICAL_OR);
|
||||
patchJump(compiler, orpatch);
|
||||
}
|
||||
@ -2045,6 +2046,7 @@ void exprOr(Compiler* compiler) {
|
||||
void exprAnd(Compiler* compiler) {
|
||||
emitOpcode(compiler, OP_AND);
|
||||
int andpatch = emitShort(compiler, 0xffff); //< Will be patched.
|
||||
skipNewLines(compiler);
|
||||
parsePrecedence(compiler, PREC_LOGICAL_AND);
|
||||
patchJump(compiler, andpatch);
|
||||
}
|
||||
|
@ -826,6 +826,14 @@ void pkSetSlotHandle(PKVM* vm, int index, PkHandle* handle) {
|
||||
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) {
|
||||
CHECK_FIBER_EXISTS(vm);
|
||||
CHECK_ARG_NULL(name);
|
||||
|
@ -426,6 +426,10 @@ PK_PUBLIC void pkSetSlotStringFmt(PKVM* vm, int index, const char* fmt, ...);
|
||||
// it's released by yourself.
|
||||
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 */
|
||||
/*****************************************************************************/
|
||||
|
@ -54,6 +54,7 @@ typedef void (*pkSetSlotNumber_t)(PKVM*, int, double);
|
||||
typedef void (*pkSetSlotString_t)(PKVM*, int, const char*);
|
||||
typedef void (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
||||
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
||||
typedef uint32_t (*pkGetSlotHash_t)(PKVM*, int);
|
||||
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
||||
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
||||
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
||||
@ -113,6 +114,7 @@ typedef struct {
|
||||
pkSetSlotString_t pkSetSlotString_ptr;
|
||||
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
||||
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
||||
pkGetSlotHash_t pkGetSlotHash_ptr;
|
||||
pkPlaceSelf_t pkPlaceSelf_ptr;
|
||||
pkGetClass_t pkGetClass_ptr;
|
||||
pkNewInstance_t pkNewInstance_ptr;
|
||||
@ -131,6 +133,7 @@ typedef struct {
|
||||
|
||||
#define PK_API_INIT_FN_NAME "pkInitApi"
|
||||
#define PK_EXPORT_FN_NAME "pkExportModule"
|
||||
#define PK_CLEANUP_FN_NAME "pkCleanupModule"
|
||||
|
||||
typedef void (*pkInitApiFn)(PkNativeApi*);
|
||||
typedef PkHandle* (*pkExportModuleFn)(PKVM*);
|
||||
@ -184,6 +187,7 @@ PkNativeApi pkMakeNativeAPI() {
|
||||
api.pkSetSlotString_ptr = pkSetSlotString;
|
||||
api.pkSetSlotStringLength_ptr = pkSetSlotStringLength;
|
||||
api.pkSetSlotHandle_ptr = pkSetSlotHandle;
|
||||
api.pkGetSlotHash_ptr = pkGetSlotHash;
|
||||
api.pkPlaceSelf_ptr = pkPlaceSelf;
|
||||
api.pkGetClass_ptr = pkGetClass;
|
||||
api.pkNewInstance_ptr = pkNewInstance;
|
||||
|
@ -96,7 +96,7 @@ typedef struct {
|
||||
bool closed; // True if the file isn't closed yet.
|
||||
} File;
|
||||
|
||||
void* _newFile(PKVM* vm) {
|
||||
void* _fileNew(PKVM* vm) {
|
||||
File* file = pkRealloc(vm, NULL, sizeof(File));
|
||||
ASSERT(file != NULL, "pkRealloc failed.");
|
||||
file->closed = true;
|
||||
@ -105,7 +105,7 @@ void* _newFile(PKVM* vm) {
|
||||
return file;
|
||||
}
|
||||
|
||||
void _deleteFile(PKVM* vm, void* ptr) {
|
||||
void _fileDelete(PKVM* vm, void* ptr) {
|
||||
File* file = (File*)ptr;
|
||||
if (!file->closed) {
|
||||
ASSERT(file->fp != NULL, OOPS);
|
||||
@ -440,7 +440,7 @@ void registerModuleIO(PKVM* vm) {
|
||||
pkModuleAddFunction(vm, io, "write", _ioWrite, 2);
|
||||
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, "read", _fileRead, -1);
|
||||
pkClassAddMethod(vm, cls_file, "write", _fileWrite, 1);
|
||||
|
@ -97,6 +97,9 @@ PkHandle* osImportDL(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);
|
||||
}
|
||||
|
||||
|
@ -8,16 +8,44 @@
|
||||
|
||||
#ifndef PK_AMALGAMATED
|
||||
#include "libs.h"
|
||||
#include "../core/value.h"
|
||||
#include "../core/vm.h"
|
||||
#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 */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef PK_AMALGAMATED
|
||||
#include "../core/value.h"
|
||||
#endif
|
||||
|
||||
void* _bytebuffNew(PKVM* vm) {
|
||||
pkByteBuffer* self = pkRealloc(vm, NULL, sizeof(pkByteBuffer));
|
||||
pkByteBufferInit(self);
|
||||
@ -263,6 +291,9 @@ void _vectorRepr(PKVM* vm) {
|
||||
void registerModuleTypes(PKVM* vm) {
|
||||
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,
|
||||
_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 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.
|
||||
## a or 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 (*pkSetSlotStringLength_t)(PKVM*, int, const char*, uint32_t);
|
||||
typedef void (*pkSetSlotHandle_t)(PKVM*, int, PkHandle*);
|
||||
typedef uint32_t (*pkGetSlotHash_t)(PKVM*, int);
|
||||
typedef void (*pkPlaceSelf_t)(PKVM*, int);
|
||||
typedef void (*pkGetClass_t)(PKVM*, int, int);
|
||||
typedef bool (*pkNewInstance_t)(PKVM*, int, int, int, int);
|
||||
@ -110,6 +111,7 @@ typedef struct {
|
||||
pkSetSlotString_t pkSetSlotString_ptr;
|
||||
pkSetSlotStringLength_t pkSetSlotStringLength_ptr;
|
||||
pkSetSlotHandle_t pkSetSlotHandle_ptr;
|
||||
pkGetSlotHash_t pkGetSlotHash_ptr;
|
||||
pkPlaceSelf_t pkPlaceSelf_ptr;
|
||||
pkGetClass_t pkGetClass_ptr;
|
||||
pkNewInstance_t pkNewInstance_ptr;
|
||||
@ -172,6 +174,7 @@ PK_EXPORT void pkInitApi(PkNativeApi* api) {
|
||||
pk_api.pkSetSlotString_ptr = api->pkSetSlotString_ptr;
|
||||
pk_api.pkSetSlotStringLength_ptr = api->pkSetSlotStringLength_ptr;
|
||||
pk_api.pkSetSlotHandle_ptr = api->pkSetSlotHandle_ptr;
|
||||
pk_api.pkGetSlotHash_ptr = api->pkGetSlotHash_ptr;
|
||||
pk_api.pkPlaceSelf_ptr = api->pkPlaceSelf_ptr;
|
||||
pk_api.pkGetClass_ptr = api->pkGetClass_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);
|
||||
}
|
||||
|
||||
uint32_t pkGetSlotHash(PKVM* vm, int index) {
|
||||
return pk_api.pkGetSlotHash_ptr(vm, index);
|
||||
}
|
||||
|
||||
void pkPlaceSelf(PKVM* vm, int index) {
|
||||
pk_api.pkPlaceSelf_ptr(vm, index);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user