types hash api implemented

and, or operators supports new line after the first
expression.
This commit is contained in:
Thakee Nathees 2022-06-01 12:40:00 +05:30
parent c48cc7ea01
commit 4f33aa7e25
11 changed files with 78 additions and 10 deletions

View File

@ -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')

View File

@ -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);
} }

View File

@ -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);

View File

@ -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);

View File

@ -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 */
/*****************************************************************************/ /*****************************************************************************/

View File

@ -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;

View File

@ -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);

View File

@ -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);
} }

View File

@ -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);

View File

@ -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

View File

@ -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);
} }