From e5ddc178968b1f1babf70d77507f37936099b193 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Wed, 1 Nov 2023 22:56:03 +0000 Subject: [PATCH 001/148] Correct memory count --- src/optionals/http/http.c | 6 +++++- src/optionals/http/http.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/optionals/http/http.c b/src/optionals/http/http.c index e2255d65d..2930d106d 100644 --- a/src/optionals/http/http.c +++ b/src/optionals/http/http.c @@ -243,16 +243,20 @@ static void createResponse(DictuVM *vm, Response *response) { response->len = 0; response->res = NULL; + response->firstIteration = true; } static size_t writeResponse(char *ptr, size_t size, size_t nmemb, void *data) { Response *response = (Response *) data; size_t new_len = response->len + size * nmemb; - response->res = GROW_ARRAY(response->vm, response->res, char, response->len, new_len + 1); + response->res = GROW_ARRAY(response->vm, response->res, char, response->len + !response->firstIteration, new_len + 1); + response->firstIteration = false; + if (response->res == NULL) { printf("Unable to allocate memory\n"); exit(71); } + memcpy(response->res + response->len, ptr, size * nmemb); response->res[new_len] = '\0'; response->len = new_len; diff --git a/src/optionals/http/http.h b/src/optionals/http/http.h index fe13633df..57c860e96 100644 --- a/src/optionals/http/http.h +++ b/src/optionals/http/http.h @@ -14,6 +14,7 @@ typedef struct response { char *res; size_t len; long statusCode; + bool firstIteration; } Response; Value createHTTPModule(DictuVM *vm); From 1a99343e6be8bb26fc8f4972bb25bea2913ecef4 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 2 Nov 2023 21:40:04 +0000 Subject: [PATCH 002/148] My translate skills are obviously seriously laking --- README.md | 6 +----- docs/index.md | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index e16f71872..74e82307a 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,7 @@ *What is Dictu?* Dictu is a high-level dynamically typed, multi-paradigm, interpreted programming language. Dictu has a very familiar -C-style syntax along with taking inspiration from the family of languages surrounding it, such as Python and JavaScript. - -*What does Dictu mean?* - -Dictu means `simplistic` in Latin. +C-style syntax along with taking inspiration from the family of languages surrounding it, such as Python and JavaScript. ### Dictu documentation Documentation for Dictu can be found [here](https://dictu-lang.com/) diff --git a/docs/index.md b/docs/index.md index b2c1e7dd7..294828177 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,8 +29,6 @@ HTTP.get("https://api.coindesk.com/v1/bpi/currentprice.json").match( Dictu is a high-level dynamically typed, multi-paradigm, interpreted programming language. Dictu has a very familiar C-style syntax along with taking inspiration from the family of languages surrounding it, such as Python and JavaScript. -Dictu means simplistic in Latin. This is the aim of the language: to be as simplistic, organized, and logical as humanly possible. - {: .fs-6 .fw-300 } --- From 36f2fbb0e288bf012a21e42044d7abcd3283cbbe Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 09:54:50 -0700 Subject: [PATCH 003/148] add dev null Signed-off-by: Brian Downs --- docs/docs/standard-lib/io.md | 6 ++++++ examples/writeDevNull.du | 13 +++++++++++++ src/optionals/io.c | 5 +++++ tests/io/copyFile.du | 13 +++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 examples/writeDevNull.du diff --git a/docs/docs/standard-lib/io.md b/docs/docs/standard-lib/io.md index b0b59bd72..5d3071db1 100644 --- a/docs/docs/standard-lib/io.md +++ b/docs/docs/standard-lib/io.md @@ -24,6 +24,12 @@ To make use of the IO module an import is required. import IO; ``` +### Constants + +| Constant | Description | +| ---------- | ----------------------------------- | +| IO.devNull | Provides access to the null device. | + ### IO.print(...values) -> Nil Prints a given list of values to stdout. diff --git a/examples/writeDevNull.du b/examples/writeDevNull.du new file mode 100644 index 000000000..427787425 --- /dev/null +++ b/examples/writeDevNull.du @@ -0,0 +1,13 @@ +import IO; +import System; + + +{ // main + print(IO.devNull); + with(IO.devNull, 'w') { + const out = file.write("asdfasfdasdfasdf"); + print(out); + } + + System.exit(0); +} \ No newline at end of file diff --git a/src/optionals/io.c b/src/optionals/io.c index 877233b32..500744c0a 100644 --- a/src/optionals/io.c +++ b/src/optionals/io.c @@ -127,6 +127,11 @@ Value createIOModule(DictuVM *vm) { defineNativeProperty(vm, &module->values, "stdin", NUMBER_VAL(STDIN_FILENO)); defineNativeProperty(vm, &module->values, "stdout", NUMBER_VAL(STDOUT_FILENO)); defineNativeProperty(vm, &module->values, "stderr", NUMBER_VAL(STDERR_FILENO)); +#ifndef _WIN32 + defineNativeProperty(vm, &module->values, "devNull", OBJ_VAL(copyString(vm, "/dev/null", strlen("/dev/null")))); +#else + defineNativeProperty(vm, &module->values, "devNull", OBJ_VAL(copyString(vm, "\\\\.\\NUL", strlen("\\\\.\\NUL")))); +#endif /** * Define IO methods diff --git a/tests/io/copyFile.du b/tests/io/copyFile.du index 60d38836e..2048aa59e 100644 --- a/tests/io/copyFile.du +++ b/tests/io/copyFile.du @@ -48,6 +48,19 @@ class TestSystemCopyFile < UnitTest { this.assertNotNil(res); this.assertSuccess(res); } + + testCopyFileToDevNull() { + with(Path.join(this.tmpDir, srcFile), 'w') { + file.write("lots and lots of temp data!"); + } + + const srcFullPath = Path.join(this.tmpDir, srcFile); + + const res = IO.copyFile(srcFullPath, IO.devNull); + + this.assertNotNil(res); + this.assertSuccess(res); + } } TestSystemCopyFile().run(); \ No newline at end of file From a1598b02df990538d29d08c2edb659d3ee6cb280 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 09:55:54 -0700 Subject: [PATCH 004/148] add new line to example file Signed-off-by: Brian Downs --- examples/writeDevNull.du | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/writeDevNull.du b/examples/writeDevNull.du index 427787425..faeb64439 100644 --- a/examples/writeDevNull.du +++ b/examples/writeDevNull.du @@ -10,4 +10,4 @@ import System; } System.exit(0); -} \ No newline at end of file +} From e0d2e82a9da1d2a22e06aa4c805226d8e2853c48 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:14:24 -0700 Subject: [PATCH 005/148] initial impl of Process.kill Signed-off-by: Brian Downs --- docs/docs/standard-lib/process.md | 14 ++++ src/cli/main.c | 20 +++--- src/optionals/process.c | 106 ++++++++++++++++++++++++++++-- 3 files changed, 125 insertions(+), 15 deletions(-) diff --git a/docs/docs/standard-lib/process.md b/docs/docs/standard-lib/process.md index 378343fb0..3694c9332 100644 --- a/docs/docs/standard-lib/process.md +++ b/docs/docs/standard-lib/process.md @@ -50,3 +50,17 @@ If the external process writes to stdout and you wish to capture the output you Process.run(["ls", "-la"]).unwrap(); print(Process.run(["echo", "test"], true).unwrap()); // 'test' ``` + +### Process.kill(Number, Number -> Optional) -> Result\ + +kill receives a process ID number and an optional signal number and attempts to kill the process associated with the given pid. If no signal is provided, SIGKILL is used. + +```cs +const res = Process.kill(709871); +// 0 +``` + +```cs +const res = Process.kill(709871, Process.SIGTERM).unwrap(); +// 0 +``` diff --git a/src/cli/main.c b/src/cli/main.c index 8bdaf95da..e9e1fe179 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -13,8 +13,7 @@ #include "linenoise/linenoise.h" -static int matchStringLiteral(char* line, int i) -{ +static int matchStringLiteral(char* line, int i) { char quote = line[i]; if (quote != '\'' && quote != '"') { @@ -62,8 +61,7 @@ static bool matchBraces(char *line) { return braceLevel == 0; } -static void memcpyAndAppendNul(char* dst, char* src, int len) -{ +static void memcpyAndAppendNul(char* dst, char* src, int len) { memcpy(dst, src, len); dst[len] = '\0'; } @@ -157,9 +155,9 @@ static void runFile(DictuVM *vm, char *filename) { } static const char *const usage[] = { - "dictu [options] [[--] args]", - "dictu [options]", - NULL, + "dictu [options] [[--] args]", + "dictu [options]", + NULL, }; int main(int argc, char *argv[]) { @@ -167,10 +165,10 @@ int main(int argc, char *argv[]) { char *cmd = NULL; struct argparse_option options[] = { - OPT_HELP(), - OPT_BOOLEAN('v', "version", &version, "Display Dictu version"), - OPT_STRING('c', "cmd", &cmd, "Run program passed in as string"), - OPT_END(), + OPT_HELP(), + OPT_BOOLEAN('v', "version", &version, "Display Dictu version"), + OPT_STRING('c', "cmd", &cmd, "Run program passed in as string"), + OPT_END(), }; struct argparse argparse; diff --git a/src/optionals/process.c b/src/optionals/process.c index 85284603c..aff8c19d7 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -1,3 +1,5 @@ +#include + #include "process.h" #ifdef _WIN32 @@ -222,7 +224,7 @@ static Value executeReturnOutput(DictuVM* vm, ObjList* argList) { } #endif -static Value execNative(DictuVM* vm, int argCount, Value* args) { +static Value execProcess(DictuVM* vm, int argCount, Value* args) { if (argCount != 1) { runtimeError(vm, "exec() takes 1 argument (%d given).", argCount); return EMPTY_VAL; @@ -237,7 +239,7 @@ static Value execNative(DictuVM* vm, int argCount, Value* args) { return execute(vm, argList, false); } -static Value runNative(DictuVM* vm, int argCount, Value* args) { +static Value runProcess(DictuVM* vm, int argCount, Value* args) { if (argCount != 1 && argCount != 2) { runtimeError(vm, "run() takes 1 or 2 arguments (%d given)", argCount); return EMPTY_VAL; @@ -268,6 +270,34 @@ static Value runNative(DictuVM* vm, int argCount, Value* args) { return execute(vm, argList, true); } +static Value killProcess(DictuVM* vm, int argCount, Value* args) { + if (argCount > 2) { + runtimeError(vm, "kill() takes 1 or 2 arguments (%d given)", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[0])) { + runtimeError(vm, "First argument passed to kill() must be a number"); + return EMPTY_VAL; + } + + pid_t pid = (pid_t)AS_NUMBER(args[0]); + int signal = SIGKILL; + + if (argCount == 2) { + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "Second argument passed to kill() must be a number"); + return EMPTY_VAL; + } + + signal = AS_NUMBER(args[1]); + } + + int res = kill(pid, signal); + + return newResultSuccess(vm, AS_NUMBER(res)); +} + Value createProcessModule(DictuVM* vm) { ObjString* name = copyString(vm, "Process", 7); push(vm, OBJ_VAL(name)); @@ -277,12 +307,80 @@ Value createProcessModule(DictuVM* vm) { /** * Define process methods */ - defineNative(vm, &module->values, "exec", execNative); - defineNative(vm, &module->values, "run", runNative); + defineNative(vm, &module->values, "exec", execProcess); + defineNative(vm, &module->values, "run", runProcess); + defineNative(vm, &module->values, "kill", killProcess); /** * Define process properties */ + defineNativeProperty(vm, &module->values, "SIGINT", NUMBER_VAL(SIGINT)); + defineNativeProperty(vm, &module->values, "SIGILL", NUMBER_VAL(SIGILL)); + defineNativeProperty(vm, &module->values, "SIGFPE", NUMBER_VAL(SIGFPE)); + defineNativeProperty(vm, &module->values, "SIGKILL", NUMBER_VAL(SIGKILL)); + defineNativeProperty(vm, &module->values, "SIGSEGV", NUMBER_VAL(SIGSEGV)); + defineNativeProperty(vm, &module->values, "SIGTERM", NUMBER_VAL(SIGTERM)); + +#if defined(__Linux__) + defineNativeProperty(vm, &module->values, "SIGHUP", NUMBER_VAL(1)); + defineNativeProperty(vm, &module->values, "SIGQUIT", NUMBER_VAL(3)); + defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(6)); + defineNativeProperty(vm, &module->values, "SIGTRAP", NUMBER_VAL(5)); + defineNativeProperty(vm, &module->values, "SIGIOT", NUMBER_VAL(6)); + defineNativeProperty(vm, &module->values, "SIGBUS", NUMBER_VAL(7)); + defineNativeProperty(vm, &module->values, "SIGUSR1", NUMBER_VAL(10)); + defineNativeProperty(vm, &module->values, "SIGUSR2", NUMBER_VAL(12)); + defineNativeProperty(vm, &module->values, "SIGPIPE", NUMBER_VAL(13)); + defineNativeProperty(vm, &module->values, "SIGALRM", NUMBER_VAL(14)); + defineNativeProperty(vm, &module->values, "SIGSTKFLT", NUMBER_VAL(16)); + defineNativeProperty(vm, &module->values, "SIGCHLD", NUMBER_VAL(17)); + defineNativeProperty(vm, &module->values, "SIGCONT", NUMBER_VAL(18)); + defineNativeProperty(vm, &module->values, "SIGSTOP", NUMBER_VAL(19)); + defineNativeProperty(vm, &module->values, "SIGTSTP", NUMBER_VAL(20)); + defineNativeProperty(vm, &module->values, "SIGTTIN", NUMBER_VAL(21)); + defineNativeProperty(vm, &module->values, "SIGTTOU", NUMBER_VAL(22)); + defineNativeProperty(vm, &module->values, "SIGURG", NUMBER_VAL(23)); + defineNativeProperty(vm, &module->values, "SIGXCPU", NUMBER_VAL(24)); + defineNativeProperty(vm, &module->values, "SIGXFSZ", NUMBER_VAL(25)); + defineNativeProperty(vm, &module->values, "SIGVTALRM", NUMBER_VAL(26)); + defineNativeProperty(vm, &module->values, "SIGPROF", NUMBER_VAL(27)); + defineNativeProperty(vm, &module->values, "SIGWINCH", NUMBER_VAL(28)); + defineNativeProperty(vm, &module->values, "SIGIO", NUMBER_VAL(29)); + defineNativeProperty(vm, &module->values, "SIGPWR", NUMBER_VAL(30)); + defineNativeProperty(vm, &module->values, "SIGSYS", NUMBER_VAL(31)); + defineNativeProperty(vm, &module->values, "SIGUNUSED", NUMBER_VAL(31)); +#elif defined(__FreeBSD__) || defined(__APPLE__) + defineNativeProperty(vm, &module->values, "SIGHUP", NUMBER_VAL(1)); + defineNativeProperty(vm, &module->values, "SIGQUIT", NUMBER_VAL(3)); + defineNativeProperty(vm, &module->values, "SIGTRAP", NUMBER_VAL(5)); + defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(6)); + defineNativeProperty(vm, &module->values, "SIGEMT", NUMBER_VAL(7)); + defineNativeProperty(vm, &module->values, "SIGBUS", NUMBER_VAL(10)); + defineNativeProperty(vm, &module->values, "SIGSYS", NUMBER_VAL(12)); + defineNativeProperty(vm, &module->values, "SIGPIPE", NUMBER_VAL(13)); + defineNativeProperty(vm, &module->values, "SIGALRM", NUMBER_VAL(14)); + defineNativeProperty(vm, &module->values, "SIGURG", NUMBER_VAL(16)); + defineNativeProperty(vm, &module->values, "SIGSTOP", NUMBER_VAL(17)); + defineNativeProperty(vm, &module->values, "SIGTSTP", NUMBER_VAL(18)); + defineNativeProperty(vm, &module->values, "SIGCONT", NUMBER_VAL(19)); + defineNativeProperty(vm, &module->values, "SIGCHLD", NUMBER_VAL(20)); + defineNativeProperty(vm, &module->values, "SIGTTIN", NUMBER_VAL(21)); + defineNativeProperty(vm, &module->values, "SIGTTOU", NUMBER_VAL(22)); + defineNativeProperty(vm, &module->values, "SIGIO", NUMBER_VAL(23)); + defineNativeProperty(vm, &module->values, "SIGXCPU", NUMBER_VAL(24)); + defineNativeProperty(vm, &module->values, "SIGXFSZ", NUMBER_VAL(25)); + defineNativeProperty(vm, &module->values, "SIGVTALRM", NUMBER_VAL(26)); + defineNativeProperty(vm, &module->values, "SIGPROF", NUMBER_VAL(27)); + defineNativeProperty(vm, &module->values, "SIGWINCH", NUMBER_VAL(28)); + defineNativeProperty(vm, &module->values, "SIGINFO", NUMBER_VAL(29)); + defineNativeProperty(vm, &module->values, "SIGUSR1", NUMBER_VAL(30)); + defineNativeProperty(vm, &module->values, "SIGUSR2", NUMBER_VAL(31)); + defineNativeProperty(vm, &module->values, "SIGTHR", NUMBER_VAL(32)); + defineNativeProperty(vm, &module->values, "SIGLIBRT", NUMBER_VAL(33)); +#elif defined(__WIN32) + defineNativeProperty(vm, &module->values, "SIGEXIT", NUMBER_VAL(0)); + defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(22)); +#endif pop(vm); pop(vm); From 55b5a7ffd031230d9fcc17eea1007907bbbcbc18 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:19:57 -0700 Subject: [PATCH 006/148] fix macro Signed-off-by: Brian Downs --- src/optionals/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index aff8c19d7..d178a0e3e 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -377,7 +377,7 @@ Value createProcessModule(DictuVM* vm) { defineNativeProperty(vm, &module->values, "SIGUSR2", NUMBER_VAL(31)); defineNativeProperty(vm, &module->values, "SIGTHR", NUMBER_VAL(32)); defineNativeProperty(vm, &module->values, "SIGLIBRT", NUMBER_VAL(33)); -#elif defined(__WIN32) +#elif defined(WIN32) defineNativeProperty(vm, &module->values, "SIGEXIT", NUMBER_VAL(0)); defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(22)); #endif From 7c90c64096fcedd603b496b0dcb797d306917fcd Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:25:19 -0700 Subject: [PATCH 007/148] fix macro Signed-off-by: Brian Downs --- src/optionals/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index d178a0e3e..3a72d67af 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -377,7 +377,7 @@ Value createProcessModule(DictuVM* vm) { defineNativeProperty(vm, &module->values, "SIGUSR2", NUMBER_VAL(31)); defineNativeProperty(vm, &module->values, "SIGTHR", NUMBER_VAL(32)); defineNativeProperty(vm, &module->values, "SIGLIBRT", NUMBER_VAL(33)); -#elif defined(WIN32) +#elif _WIN32 defineNativeProperty(vm, &module->values, "SIGEXIT", NUMBER_VAL(0)); defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(22)); #endif From acb17952e8bec59e15060a1f86bed5852aa7e576 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:26:03 -0700 Subject: [PATCH 008/148] fix macro Signed-off-by: Brian Downs --- src/optionals/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index 3a72d67af..5e017e547 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -377,7 +377,7 @@ Value createProcessModule(DictuVM* vm) { defineNativeProperty(vm, &module->values, "SIGUSR2", NUMBER_VAL(31)); defineNativeProperty(vm, &module->values, "SIGTHR", NUMBER_VAL(32)); defineNativeProperty(vm, &module->values, "SIGLIBRT", NUMBER_VAL(33)); -#elif _WIN32 +#elif defined(_WIN32) defineNativeProperty(vm, &module->values, "SIGEXIT", NUMBER_VAL(0)); defineNativeProperty(vm, &module->values, "SIGABRT", NUMBER_VAL(22)); #endif From 8f6b4a15940080276c0b29daffca84f188edcf62 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:43:48 -0700 Subject: [PATCH 009/148] fix macro Signed-off-by: Brian Downs --- src/optionals/process.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index 5e017e547..8a41de909 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -314,12 +314,12 @@ Value createProcessModule(DictuVM* vm) { /** * Define process properties */ - defineNativeProperty(vm, &module->values, "SIGINT", NUMBER_VAL(SIGINT)); - defineNativeProperty(vm, &module->values, "SIGILL", NUMBER_VAL(SIGILL)); - defineNativeProperty(vm, &module->values, "SIGFPE", NUMBER_VAL(SIGFPE)); - defineNativeProperty(vm, &module->values, "SIGKILL", NUMBER_VAL(SIGKILL)); - defineNativeProperty(vm, &module->values, "SIGSEGV", NUMBER_VAL(SIGSEGV)); - defineNativeProperty(vm, &module->values, "SIGTERM", NUMBER_VAL(SIGTERM)); + defineNativeProperty(vm, &module->values, "SIGINT", NUMBER_VAL(2)); + defineNativeProperty(vm, &module->values, "SIGILL", NUMBER_VAL(4)); + defineNativeProperty(vm, &module->values, "SIGFPE", NUMBER_VAL(8)); + defineNativeProperty(vm, &module->values, "SIGKILL", NUMBER_VAL(9)); + defineNativeProperty(vm, &module->values, "SIGSEGV", NUMBER_VAL(11)); + defineNativeProperty(vm, &module->values, "SIGTERM", NUMBER_VAL(15)); #if defined(__Linux__) defineNativeProperty(vm, &module->values, "SIGHUP", NUMBER_VAL(1)); From 2ae3422ead021565234ef65a57d1f3258132bae6 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:47:02 -0700 Subject: [PATCH 010/148] add pid_t macro Signed-off-by: Brian Downs --- src/optionals/process.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/optionals/process.c b/src/optionals/process.c index 8a41de909..89cc04dd2 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -2,6 +2,10 @@ #include "process.h" +#ifdef _WIN32 +#define pid_t int +#endif + #ifdef _WIN32 static char* buildArgs(DictuVM *vm, ObjList* list, int *size) { // 3 for 1st arg escape + null terminator From 798c3712870b2e6193251b38af1c5979960e20a6 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 6 Nov 2023 20:52:40 -0700 Subject: [PATCH 011/148] explicit sigkill value Signed-off-by: Brian Downs --- src/optionals/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index 89cc04dd2..00c3dbede 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -286,7 +286,7 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { } pid_t pid = (pid_t)AS_NUMBER(args[0]); - int signal = SIGKILL; + int signal = 9; if (argCount == 2) { if (!IS_NUMBER(args[1])) { From 49fe0c2b04dce87bbb7f0af9dae9f338d9838aa9 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 7 Nov 2023 15:09:31 -0700 Subject: [PATCH 012/148] windows madness Signed-off-by: Brian Downs --- src/optionals/process.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index 00c3dbede..02b390bc2 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -1,4 +1,7 @@ #include +#ifdef _WIN32 +#include "windowsapi.h" +#endif #include "process.h" @@ -297,9 +300,17 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { signal = AS_NUMBER(args[1]); } - int res = kill(pid, signal); +#ifdef _WIN32 + HANDLE handle = OpenProcess(PROCESS_TERMINATE, TRUE, (int)pid); + if (handle != NULL) { + TerminateProcess(handle, 0); + CloseHandle(handle); + } +#else + kill(pid, signal); +#endif - return newResultSuccess(vm, AS_NUMBER(res)); + return newResultSuccess(vm, NIL_VAL); } Value createProcessModule(DictuVM* vm) { From 3354065e4adba83b90cbab04126b74e7ee889c59 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 7 Nov 2023 15:22:23 -0700 Subject: [PATCH 013/148] seperate impl for windows, update docs Signed-off-by: Brian Downs --- docs/docs/standard-lib/process.md | 2 ++ src/optionals/process.c | 32 +++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/docs/docs/standard-lib/process.md b/docs/docs/standard-lib/process.md index 3694c9332..2f6616b51 100644 --- a/docs/docs/standard-lib/process.md +++ b/docs/docs/standard-lib/process.md @@ -64,3 +64,5 @@ const res = Process.kill(709871); const res = Process.kill(709871, Process.SIGTERM).unwrap(); // 0 ``` + +**Note:** On Windows, `kill` only takes the PID as the argument. diff --git a/src/optionals/process.c b/src/optionals/process.c index 02b390bc2..6f50f0745 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -277,6 +277,30 @@ static Value runProcess(DictuVM* vm, int argCount, Value* args) { return execute(vm, argList, true); } +#ifdef _WIN32 +static Value killProcess(DictuVM* vm, int argCount, Value* args) { + if (argCount > 2) { + runtimeError(vm, "kill() takes 1 argument (%d given)", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[0])) { + runtimeError(vm, "Argument passed to kill() must be a number"); + return EMPTY_VAL; + } + + pid_t pid = (pid_t)AS_NUMBER(args[0]); + + HANDLE handle = OpenProcess(PROCESS_TERMINATE, TRUE, (int)pid); + if (handle != NULL) { + TerminateProcess(handle, 0); + CloseHandle(handle); + } + + return newResultSuccess(vm, NIL_VAL); +} +#endif + static Value killProcess(DictuVM* vm, int argCount, Value* args) { if (argCount > 2) { runtimeError(vm, "kill() takes 1 or 2 arguments (%d given)", argCount); @@ -300,15 +324,7 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { signal = AS_NUMBER(args[1]); } -#ifdef _WIN32 - HANDLE handle = OpenProcess(PROCESS_TERMINATE, TRUE, (int)pid); - if (handle != NULL) { - TerminateProcess(handle, 0); - CloseHandle(handle); - } -#else kill(pid, signal); -#endif return newResultSuccess(vm, NIL_VAL); } From 1124f18ab8c079460e33826c2c7144cbd4b7def4 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 7 Nov 2023 15:27:08 -0700 Subject: [PATCH 014/148] more preprocessor segmentation Signed-off-by: Brian Downs --- src/optionals/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/optionals/process.c b/src/optionals/process.c index 6f50f0745..ca63f8860 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -299,8 +299,7 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { return newResultSuccess(vm, NIL_VAL); } -#endif - +#else static Value killProcess(DictuVM* vm, int argCount, Value* args) { if (argCount > 2) { runtimeError(vm, "kill() takes 1 or 2 arguments (%d given)", argCount); @@ -328,6 +327,7 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { return newResultSuccess(vm, NIL_VAL); } +#endif Value createProcessModule(DictuVM* vm) { ObjString* name = copyString(vm, "Process", 7); From 66cee3ed1228c8250956b0ca5565e636423f047d Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Thu, 9 Nov 2023 15:40:22 -0700 Subject: [PATCH 015/148] add kill tests for process module Signed-off-by: Brian Downs --- docs/docs/standard-lib/process.md | 2 +- src/optionals/process.c | 4 ++- tests/process/exec.du | 2 +- tests/process/import.du | 2 +- tests/process/kill.du | 46 +++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 tests/process/kill.du diff --git a/docs/docs/standard-lib/process.md b/docs/docs/standard-lib/process.md index 2f6616b51..165f8b1c4 100644 --- a/docs/docs/standard-lib/process.md +++ b/docs/docs/standard-lib/process.md @@ -51,7 +51,7 @@ Process.run(["ls", "-la"]).unwrap(); print(Process.run(["echo", "test"], true).unwrap()); // 'test' ``` -### Process.kill(Number, Number -> Optional) -> Result\ +### Process.kill(Number, Number -> Optional) -> Result\ kill receives a process ID number and an optional signal number and attempts to kill the process associated with the given pid. If no signal is provided, SIGKILL is used. diff --git a/src/optionals/process.c b/src/optionals/process.c index ca63f8860..ec7de1f52 100644 --- a/src/optionals/process.c +++ b/src/optionals/process.c @@ -323,7 +323,9 @@ static Value killProcess(DictuVM* vm, int argCount, Value* args) { signal = AS_NUMBER(args[1]); } - kill(pid, signal); + if (kill(pid, signal) == -1) { + ERROR_RESULT; + } return newResultSuccess(vm, NIL_VAL); } diff --git a/tests/process/exec.du b/tests/process/exec.du index 853162bd8..835c0805f 100644 --- a/tests/process/exec.du +++ b/tests/process/exec.du @@ -25,4 +25,4 @@ class TestProcessExec < UnitTest { } } -TestProcessExec().run(); \ No newline at end of file +TestProcessExec().run(); diff --git a/tests/process/import.du b/tests/process/import.du index 894e9ea7f..d81d9fe1b 100644 --- a/tests/process/import.du +++ b/tests/process/import.du @@ -5,4 +5,4 @@ */ import "exec.du"; -import "run.du"; \ No newline at end of file +import "run.du"; diff --git a/tests/process/kill.du b/tests/process/kill.du new file mode 100644 index 000000000..2328522cb --- /dev/null +++ b/tests/process/kill.du @@ -0,0 +1,46 @@ +/** + * kill.du + * + * Testing the Process.kill() function + * + * kill() receives a PID as a Number and optional signal, as a Number (on *NIX) to be passed to the process. + */ +from UnitTest import UnitTest; + +import IO; +import Process; +import System; + +class TestProcessKill < UnitTest { + testProcessKillError() { + const res = Process.kill(9999999999999999).unwrapError(); + this.assertEquals(res, "No such process"); + } + + testProcessKillNoSignal() { + Process.exec(["sleep", "100"]); + + const out = Process.run(["pgrep", "sleep"], true).unwrap(); + const pids = out.split("\n"); + + if (pids.len() > 1) { + for (var i = 0; i < pids.len(); i += 1) { + var pid = pids[i].replace("\n", ""); + pid = pid.toNumber().unwrap(); + const res = Process.kill(pid, 0); + this.assertSuccess(res); + this.assertNil(res.unwrap()); + } + } else { + var pid = pids[0].replace("\n", ""); + pid = pid.toNumber().unwrap(); + const res = Process.kill(pid, 0); + this.assertSuccess(res); + this.assertNil(res.unwrap()); + } + } +} + +if (System.platform != "windows") { + TestProcessKill().run(); +} From d9101f3da96947d6c57aad31fe6fe117e932e3d1 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Thu, 9 Nov 2023 16:09:10 -0700 Subject: [PATCH 016/148] add kill.du to tests Signed-off-by: Brian Downs --- tests/process/import.du | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/process/import.du b/tests/process/import.du index d81d9fe1b..158164f64 100644 --- a/tests/process/import.du +++ b/tests/process/import.du @@ -5,4 +5,5 @@ */ import "exec.du"; +import "kill.du"; import "run.du"; From a94e3404b6875972199a40c14d5419a1c2efaa3d Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 11 Nov 2023 15:06:59 -0700 Subject: [PATCH 017/148] use appropriate macro Signed-off-by: Brian Downs --- src/optionals/http/http.c | 16 ++++++++-------- src/optionals/io.c | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/optionals/http/http.c b/src/optionals/http/http.c index 2930d106d..8bd6a15bc 100644 --- a/src/optionals/http/http.c +++ b/src/optionals/http/http.c @@ -941,7 +941,7 @@ static Value httpClientSetHeaders(DictuVM *vm, int argCount, Value *args) { headerChunk = NULL; for (int h = 0; h < headers->values.count; h++) { - headerChunk = curl_slist_append(headerChunk, AS_STRING(headers->values.values[h])->chars); + headerChunk = curl_slist_append(headerChunk, AS_CSTRING(headers->values.values[h])); } curl_easy_setopt(httpClient->curl, CURLOPT_HTTPHEADER, headerChunk); @@ -962,7 +962,7 @@ static Value httpClientSetKeyFile(DictuVM *vm, int argCount, Value *args) { HttpClient *httpClient = AS_HTTP_CLIENT(args[0]); - curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_STRING(args[1])->chars); + curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_CSTRING(args[1])); return NIL_VAL; } @@ -980,7 +980,7 @@ static Value httpClientSetCertFile(DictuVM *vm, int argCount, Value *args) { HttpClient *httpClient = AS_HTTP_CLIENT(args[0]); - curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_STRING(args[1])->chars); + curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_CSTRING(args[1])); return NIL_VAL; } @@ -998,7 +998,7 @@ static Value httpClientSetKeyPass(DictuVM *vm, int argCount, Value *args) { HttpClient *httpClient = AS_HTTP_CLIENT(args[0]); - curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_STRING(args[1])->chars); + curl_easy_setopt(httpClient->curl, CURLOPT_SSLKEY, AS_CSTRING(args[1])); return NIL_VAL; } @@ -1281,7 +1281,7 @@ Value newHttpClient(DictuVM *vm, ObjDict *opts) { ObjList *headers = AS_LIST(entry->value); for (int h = 0; h < headers->values.count; h++) { - headerChunk = curl_slist_append(headerChunk, AS_STRING(headers->values.values[h])->chars); + headerChunk = curl_slist_append(headerChunk, AS_CSTRING(headers->values.values[h])); } curl_easy_setopt(httpClient->curl, CURLOPT_HTTPHEADER, headerChunk); @@ -1323,7 +1323,7 @@ Value newHttpClient(DictuVM *vm, ObjDict *opts) { return EMPTY_VAL; } - char *keyFile = AS_STRING(entry->value)->chars; + char *keyFile = AS_CSTRING(entry->value); if (keyFile[0] == '\0') { continue; } @@ -1339,7 +1339,7 @@ Value newHttpClient(DictuVM *vm, ObjDict *opts) { return EMPTY_VAL; } - char *certFile = AS_STRING(entry->value)->chars; + char *certFile = AS_CSTRING(entry->value); if (certFile[0] == '\0') { continue; } @@ -1355,7 +1355,7 @@ Value newHttpClient(DictuVM *vm, ObjDict *opts) { return EMPTY_VAL; } - char *keyPasswd = AS_STRING(entry->value)->chars; + char *keyPasswd = AS_CSTRING(entry->value); if (keyPasswd[0] == '\0') { continue; } diff --git a/src/optionals/io.c b/src/optionals/io.c index 500744c0a..1602c7d49 100644 --- a/src/optionals/io.c +++ b/src/optionals/io.c @@ -50,8 +50,8 @@ static Value copyFileIO(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - char *srcFile = AS_STRING(args[0])->chars; - char *dstFile = AS_STRING(args[1])->chars; + char *srcFile = AS_CSTRING(args[0]); + char *dstFile = AS_CSTRING(args[1]); FILE *sf = fopen(srcFile, "r"); if (sf == NULL) { @@ -89,8 +89,8 @@ static Value copyFileIO(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - char *src = AS_STRING(args[0])->chars; - char *dst = AS_STRING(args[1])->chars; + char *src = AS_CSTRING(args[0]); + char *dst = AS_CSTRING(args[1]); int in = 0; int out = 0; From c62b3b737b069e528da82f8b60f2273cbfb831c3 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 11 Nov 2023 15:18:39 -0700 Subject: [PATCH 018/148] trigger ci Signed-off-by: Brian Downs --- src/optionals/hashlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/hashlib.c b/src/optionals/hashlib.c index 87177bfa6..ba8af5e79 100644 --- a/src/optionals/hashlib.c +++ b/src/optionals/hashlib.c @@ -167,4 +167,4 @@ Value createHashlibModule(DictuVM *vm) { pop(vm); return OBJ_VAL(module); -} \ No newline at end of file +} From 2d24ef7709b2a508bf12d48ffbbdf37eadb79e8a Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 19 Nov 2023 20:22:38 -0700 Subject: [PATCH 019/148] add options request Signed-off-by: Brian Downs --- docs/docs/standard-lib/http.md | 19 ++++ examples/httpOptions.du | 27 +++++ src/optionals/http/http.c | 186 +++++++++++++++++++++++++++++++++ src/optionals/optionals.h | 1 - 4 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 examples/httpOptions.du diff --git a/docs/docs/standard-lib/http.md b/docs/docs/standard-lib/http.md index 8af4a530b..f45826f6c 100644 --- a/docs/docs/standard-lib/http.md +++ b/docs/docs/standard-lib/http.md @@ -74,6 +74,19 @@ HTTP.head("https://httpbin.org/get", ["Content-Type: application/json"], 1); {"content": "", "headers": ["...", "..."], "statusCode": 200} ``` +### HTTP.options(String, list: headers -> Optional, Number: timeout -> Optional) -> Result\ + +Sends a HTTP OPTIONS request to a given URL. Timeout is given in seconds. +Returns a Result and unwraps to a Response upon success. + +```cs +HTTP.head("https://httpbin.org/options"); +HTTP.head("https://httpbin.org/options", ["Content-Type: application/json"]); +HTTP.head("https://httpbin.org/options", ["Content-Type: application/json"], 1); + +{"content": "", "headers": ["...", "..."], "statusCode": 404} +``` + ### HTTP.newClient(Dict) -> HttpClient Creates a new HTTP client with a given set of options. @@ -136,6 +149,12 @@ httpClient.head("https://httpbin.org/get"); {"content": "", "headers": ["...", "..."], "statusCode": 200} ``` +```cs +httpClient.options("https://httpbin.org/options"); + +{"content": "", "headers": ["...", "..."], "statusCode": 404} +``` + ### Response All HTTP requests return a Result that unwraps a Response object on success, or nil on error. diff --git a/examples/httpOptions.du b/examples/httpOptions.du new file mode 100644 index 000000000..f0e7775c6 --- /dev/null +++ b/examples/httpOptions.du @@ -0,0 +1,27 @@ +import HTTP; +import System; + +{ + const opts = { + "timeout": 20, + "headers": [ + "Content-Type: application/json", + "Accept: application/json", + "User-Agent: Dictu" + ], + "insecure": false, + "keyFile": "", + "certFile": "", + "keyPasswd": "" + }; + const httpClient = HTTP.newClient(opts); + + const res1 = httpClient.options("https://httpbin.org/options").unwrap(); + print(res1.headers); + + const res2 HTTP.options("https://httpbin.org/options").unwrap(); + print(res2.headers); + + + System.exit(0); +} \ No newline at end of file diff --git a/src/optionals/http/http.c b/src/optionals/http/http.c index 8bd6a15bc..fe7963eec 100644 --- a/src/optionals/http/http.c +++ b/src/optionals/http/http.c @@ -828,6 +828,99 @@ static Value head(DictuVM *vm, int argCount, Value *args) { return newResultError(vm, errorString); } +static Value options(DictuVM *vm, int argCount, Value *args) { + if (argCount < 0 || argCount > 3) { + runtimeError(vm, "options() takes between 1 and 3 arguments (%d given).", argCount); + return EMPTY_VAL; + } + + long timeout = DEFAULT_REQUEST_TIMEOUT; + ObjList *headers = NULL; + + if (argCount == 3) { + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "Timeout passed to options() must be a number."); + return EMPTY_VAL; + } + + timeout = AS_NUMBER(args[2]); + argCount--; + } + + if (argCount == 2) { + if (!IS_LIST(args[1])) { + runtimeError(vm, "Headers passed to options() must be a list."); + return EMPTY_VAL; + } + + headers = AS_LIST(args[1]); + } + + if (!IS_STRING(args[0])) { + runtimeError(vm, "URL passed to options() must be a string."); + return EMPTY_VAL; + } + + CURL *curl; + CURLcode curlResponse; + + curl_global_init(CURL_GLOBAL_DEFAULT); + curl = curl_easy_init(); + + if (curl) { + Response response; + createResponse(vm, &response); + char *url = AS_CSTRING(args[0]); + + struct curl_slist *list = NULL; + + if (headers) { + if (!setRequestHeaders(vm, list, curl, headers)) { + curl_slist_free_all(list); + return EMPTY_VAL; + } + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "OPTIONS"); + curl_easy_setopt(curl, CURLOPT_REQUEST_TARGET, "*"); + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip"); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, writeHeaders); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + + /* Perform the request, res will get the return code */ + curlResponse = curl_easy_perform(curl); + + if (headers) { + curl_slist_free_all(list); + } + + /* Check for errors */ + if (curlResponse != CURLE_OK) { + /* always cleanup */ + curl_easy_cleanup(curl); + curl_global_cleanup(); + pop(vm); + + char *errorString = (char *) curl_easy_strerror(curlResponse); + return newResultError(vm, errorString); + } + + return newResultSuccess(vm, OBJ_VAL(endRequest(vm, curl, response, true))); + } + + /* always cleanup */ + curl_easy_cleanup(curl); + curl_global_cleanup(); + pop(vm); + + char *errorString = (char *) curl_easy_strerror(CURLE_FAILED_INIT); + return newResultError(vm, errorString); +} + typedef struct { CURL *curl; } HttpClient; @@ -1231,6 +1324,97 @@ static Value httpClientHead(DictuVM *vm, int argCount, Value *args) { return newResultError(vm, errorString); } +static Value httpClientOptions(DictuVM *vm, int argCount, Value *args) { + if (argCount < 0 || argCount > 3) { + runtimeError(vm, "options() takes between 1 and 3 arguments (%d given).", argCount); + return EMPTY_VAL; + } + + long timeout = DEFAULT_REQUEST_TIMEOUT; + ObjList *headers = NULL; + + HttpClient *httpClient = AS_HTTP_CLIENT(args[0]); + + if (argCount == 4) { + if (!IS_NUMBER(args[3])) { + runtimeError(vm, "Timeout passed to options() must be a number."); + return EMPTY_VAL; + } + + timeout = AS_NUMBER(args[3]); + argCount--; + } + + if (argCount == 3) { + if (!IS_LIST(args[2])) { + runtimeError(vm, "Headers passed to options() must be a list."); + return EMPTY_VAL; + } + + headers = AS_LIST(args[2]); + } + + if (!IS_STRING(args[1])) { + runtimeError(vm, "URL passed to options() must be a string."); + return EMPTY_VAL; + } + + CURLcode curlResponse; + + if (httpClient) { + Response response; + createResponse(vm, &response); + char *url = AS_CSTRING(args[1]); + + struct curl_slist *list = NULL; + + if (headers) { + if (!setRequestHeaders(vm, list, httpClient->curl, headers)) { + curl_slist_free_all(list); + return EMPTY_VAL; + } + } + + curl_easy_setopt(httpClient->curl, CURLOPT_URL, url); + curl_easy_setopt(httpClient->curl, CURLOPT_NOBODY, 1L); + curl_easy_setopt(httpClient->curl, CURLOPT_TIMEOUT, timeout); + curl_easy_setopt(httpClient->curl, CURLOPT_CUSTOMREQUEST, "OPTIONS"); + curl_easy_setopt(httpClient->curl, CURLOPT_REQUEST_TARGET, "*"); + curl_easy_setopt(httpClient->curl, CURLOPT_ACCEPT_ENCODING, "gzip"); + curl_easy_setopt(httpClient->curl, CURLOPT_HEADERFUNCTION, writeHeaders); + curl_easy_setopt(httpClient->curl, CURLOPT_HEADERDATA, &response); + curl_easy_setopt(httpClient->curl, CURLOPT_FOLLOWLOCATION, 1L); + + /* Perform the request, res will get the return code */ + curlResponse = curl_easy_perform(httpClient->curl); + + if (headers) { + curl_slist_free_all(list); + } + + /* Check for errors */ + if (curlResponse != CURLE_OK) { + /* always cleanup */ + curl_easy_cleanup(httpClient->curl); + curl_global_cleanup(); + pop(vm); + + char *errorString = (char *) curl_easy_strerror(curlResponse); + return newResultError(vm, errorString); + } + + return newResultSuccess(vm, OBJ_VAL(endRequest(vm, httpClient->curl, response, true))); + } + + /* always cleanup */ + curl_easy_cleanup(httpClient->curl); + curl_global_cleanup(); + pop(vm); + + char *errorString = (char *) curl_easy_strerror(CURLE_FAILED_INIT); + return newResultError(vm, errorString); +} + Value newHttpClient(DictuVM *vm, ObjDict *opts) { ObjAbstract *abstract = newAbstract(vm, freeHttpClient, httpClientToString); push(vm, OBJ_VAL(abstract)); @@ -1374,6 +1558,7 @@ Value newHttpClient(DictuVM *vm, ObjDict *opts) { defineNative(vm, &abstract->values, "post", httpClientPost); defineNative(vm, &abstract->values, "put", httpClientPut); defineNative(vm, &abstract->values, "head", httpClientHead); + defineNative(vm, &abstract->values, "options", httpClientOptions); defineNative(vm, &abstract->values, "setTimeout", httpClientSetTimeout); defineNative(vm, &abstract->values, "setHeaders", httpClientSetHeaders); defineNative(vm, &abstract->values, "setInsecure", httpClientSetInsecure); @@ -1647,6 +1832,7 @@ Value createHTTPModule(DictuVM *vm) { defineNative(vm, &module->values, "post", post); defineNative(vm, &module->values, "put", put); defineNative(vm, &module->values, "head", head); + defineNative(vm, &module->values, "options", options); defineNative(vm, &module->values, "newClient", newClient); diff --git a/src/optionals/optionals.h b/src/optionals/optionals.h index e1649a001..f39f11c04 100644 --- a/src/optionals/optionals.h +++ b/src/optionals/optionals.h @@ -12,7 +12,6 @@ #include "log.h" #include "http/http.h" #include "path.h" -#include "c.h" #include "datetime.h" #include "socket.h" #include "net.h" From 485a106cdaf9f0e88e85e51b6e10256402d033f5 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 19 Nov 2023 20:26:42 -0700 Subject: [PATCH 020/148] update examples Signed-off-by: Brian Downs --- examples/httpClient.du | 7 +++++++ examples/httpOptions.du | 27 --------------------------- 2 files changed, 7 insertions(+), 27 deletions(-) delete mode 100644 examples/httpOptions.du diff --git a/examples/httpClient.du b/examples/httpClient.du index 8cd6b232c..e6f7705ca 100644 --- a/examples/httpClient.du +++ b/examples/httpClient.du @@ -43,6 +43,13 @@ import System; print("Status Code: {}".format(res.unwrap().statusCode)); print(res.unwrap().json().unwrap()); + res = httpClient.options("https://httpbin.org/options", {}); + if (not res.success()) { + print(res.unwrapError()); + System.exit(1); + } + print("Headers: {}".format(res.unwrap().headers)); + System.exit(0); } diff --git a/examples/httpOptions.du b/examples/httpOptions.du deleted file mode 100644 index f0e7775c6..000000000 --- a/examples/httpOptions.du +++ /dev/null @@ -1,27 +0,0 @@ -import HTTP; -import System; - -{ - const opts = { - "timeout": 20, - "headers": [ - "Content-Type: application/json", - "Accept: application/json", - "User-Agent: Dictu" - ], - "insecure": false, - "keyFile": "", - "certFile": "", - "keyPasswd": "" - }; - const httpClient = HTTP.newClient(opts); - - const res1 = httpClient.options("https://httpbin.org/options").unwrap(); - print(res1.headers); - - const res2 HTTP.options("https://httpbin.org/options").unwrap(); - print(res2.headers); - - - System.exit(0); -} \ No newline at end of file From 5034226f4dc12c3ee9f5d3d94c3e7d9c00152ee6 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Wed, 22 Nov 2023 10:33:28 -0700 Subject: [PATCH 021/148] removed c module setup, left used code Signed-off-by: Brian Downs --- src/optionals/c.c | 259 -------------------------------------- src/optionals/c.h | 2 - src/optionals/optionals.c | 1 - 3 files changed, 262 deletions(-) diff --git a/src/optionals/c.c b/src/optionals/c.c index 1e3ecfe25..d752654bb 100644 --- a/src/optionals/c.c +++ b/src/optionals/c.c @@ -19,262 +19,3 @@ void getStrerror(char *buf, int error) { strerror_r(error, buf, MAX_ERROR_LEN); #endif } - -Value createCModule(DictuVM *vm) { - ObjString *name = copyString(vm, "C", 1); - push(vm, OBJ_VAL(name)); - ObjModule *module = newModule(vm, name); - push(vm, OBJ_VAL(module)); - - /** - * Define C properties - */ - defineNativeProperty(vm, &module->values, "EPERM", NUMBER_VAL(EPERM)); - defineNativeProperty(vm, &module->values, "ENOENT", NUMBER_VAL(ENOENT)); - defineNativeProperty(vm, &module->values, "ESRCH", NUMBER_VAL(ESRCH)); - defineNativeProperty(vm, &module->values, "EINTR", NUMBER_VAL(EINTR)); - defineNativeProperty(vm, &module->values, "EIO", NUMBER_VAL(EIO)); - defineNativeProperty(vm, &module->values, "ENXIO", NUMBER_VAL(ENXIO)); - defineNativeProperty(vm, &module->values, "E2BIG", NUMBER_VAL(E2BIG)); - defineNativeProperty(vm, &module->values, "ENOEXEC",NUMBER_VAL(ENOEXEC)); - defineNativeProperty(vm, &module->values, "EAGAIN", NUMBER_VAL(EAGAIN)); - defineNativeProperty(vm, &module->values, "ENOMEM", NUMBER_VAL(ENOMEM)); - defineNativeProperty(vm, &module->values, "EACCES", NUMBER_VAL(EACCES)); - defineNativeProperty(vm, &module->values, "EFAULT", NUMBER_VAL(EFAULT)); -#ifdef ENOTBLK - defineNativeProperty(vm, &module->values, "ENOTBLK", NUMBER_VAL(ENOTBLK)); -#endif - defineNativeProperty(vm, &module->values, "EBUSY", NUMBER_VAL(EBUSY)); - defineNativeProperty(vm, &module->values, "EEXIST", NUMBER_VAL(EEXIST)); - defineNativeProperty(vm, &module->values, "EXDEV", NUMBER_VAL(EXDEV)); - defineNativeProperty(vm, &module->values, "ENODEV", NUMBER_VAL(ENODEV)); - defineNativeProperty(vm, &module->values, "ENOTDIR",NUMBER_VAL(ENOTDIR)); - defineNativeProperty(vm, &module->values, "EISDIR", NUMBER_VAL(EISDIR)); - defineNativeProperty(vm, &module->values, "EINVAL", NUMBER_VAL(EINVAL)); - defineNativeProperty(vm, &module->values, "ENFILE", NUMBER_VAL(ENFILE)); - defineNativeProperty(vm, &module->values, "EMFILE", NUMBER_VAL(EMFILE)); - defineNativeProperty(vm, &module->values, "ENOTTY", NUMBER_VAL(ENOTTY)); - defineNativeProperty(vm, &module->values, "ETXTBSY",NUMBER_VAL(ETXTBSY)); - defineNativeProperty(vm, &module->values, "EFBIG", NUMBER_VAL(EFBIG)); - defineNativeProperty(vm, &module->values, "ENOSPC", NUMBER_VAL(ENOSPC)); - defineNativeProperty(vm, &module->values, "ESPIPE", NUMBER_VAL(ESPIPE)); - defineNativeProperty(vm, &module->values, "EROFS", NUMBER_VAL(EROFS)); - defineNativeProperty(vm, &module->values, "EMLINK", NUMBER_VAL(EMLINK)); - defineNativeProperty(vm, &module->values, "EPIPE", NUMBER_VAL(EPIPE)); - defineNativeProperty(vm, &module->values, "EDOM", NUMBER_VAL(EDOM)); - defineNativeProperty(vm, &module->values, "ERANGE", NUMBER_VAL(ERANGE)); - defineNativeProperty(vm, &module->values, "EDEADLK",NUMBER_VAL(EDEADLK)); - defineNativeProperty(vm, &module->values, "ENAMETOOLONG", NUMBER_VAL(ENAMETOOLONG)); - defineNativeProperty(vm, &module->values, "ENOLCK", NUMBER_VAL(ENOLCK)); - defineNativeProperty(vm, &module->values, "ENOSYS", NUMBER_VAL(ENOSYS)); - defineNativeProperty(vm, &module->values, "ENOTEMPTY", NUMBER_VAL(ENOTEMPTY)); - defineNativeProperty(vm, &module->values, "ELOOP", NUMBER_VAL(ELOOP)); - defineNativeProperty(vm, &module->values, "EWOULDBLOCK", NUMBER_VAL(EWOULDBLOCK)); - defineNativeProperty(vm, &module->values, "ENOMSG", NUMBER_VAL(ENOMSG)); - defineNativeProperty(vm, &module->values, "EIDRM", NUMBER_VAL(EIDRM)); -#ifdef ECHRNG - defineNativeProperty(vm, &module->values, "ECHRNG", NUMBER_VAL(ECHRNG)); -#endif -#ifdef EL2NSYNC - defineNativeProperty(vm, &module->values, "EL2NSYNC", NUMBER_VAL(EL2NSYNC)); -#endif -#ifdef EL3HLT - defineNativeProperty(vm, &module->values, "EL3HLT", NUMBER_VAL(EL3HLT)); -#endif -#ifdef EL3RST - defineNativeProperty(vm, &module->values, "EL3RST", NUMBER_VAL(EL3RST)); -#endif -#ifdef ELNRNG - defineNativeProperty(vm, &module->values, "ELNRNG", NUMBER_VAL(ELNRNG)); -#endif -#ifdef EUNATCH - defineNativeProperty(vm, &module->values, "EUNATCH", NUMBER_VAL(EUNATCH)); -#endif -#ifdef ENOCSI - defineNativeProperty(vm, &module->values, "ENOCSI", NUMBER_VAL(ENOCSI)); -#endif -#ifdef EL2HLT - defineNativeProperty(vm, &module->values, "EL2HLT", NUMBER_VAL(EL2HLT)); -#endif -#ifdef EBADE - defineNativeProperty(vm, &module->values, "EBADE", NUMBER_VAL(EBADE)); -#endif -#ifdef EBADR - defineNativeProperty(vm, &module->values, "EBADR", NUMBER_VAL(EBADR)); -#endif -#ifdef EXFULL - defineNativeProperty(vm, &module->values, "EXFULL", NUMBER_VAL(EXFULL)); -#endif -#ifdef ENOANO - defineNativeProperty(vm, &module->values, "ENOANO", NUMBER_VAL(ENOANO)); -#endif -#ifdef EBADRQC - defineNativeProperty(vm, &module->values, "EBADRQC", NUMBER_VAL(EBADRQC)); -#endif -#ifdef EBADSLT - defineNativeProperty(vm, &module->values, "EBADSLT", NUMBER_VAL(EBADSLT)); -#endif -#ifdef EDEADLOCK - defineNativeProperty(vm, &module->values, "EDEADLOCK", NUMBER_VAL(EDEADLOCK)); -#endif -#ifdef EBFONT - defineNativeProperty(vm, &module->values, "EBFONT", NUMBER_VAL(EBFONT)); -#endif - defineNativeProperty(vm, &module->values, "ENOSTR", NUMBER_VAL(ENOSTR)); - defineNativeProperty(vm, &module->values, "ENODATA", NUMBER_VAL(ENODATA)); - defineNativeProperty(vm, &module->values, "ETIME", NUMBER_VAL(ETIME)); - defineNativeProperty(vm, &module->values, "ENOSR", NUMBER_VAL(ENOSR)); -#ifdef ENONET - defineNativeProperty(vm, &module->values, "ENONET", NUMBER_VAL(ENONET)); -#endif -#ifdef ENOPKG - defineNativeProperty(vm, &module->values, "ENOPKG", NUMBER_VAL(ENOPKG)); -#endif -#ifdef EREMOTE - defineNativeProperty(vm, &module->values, "EREMOTE", NUMBER_VAL(EREMOTE)); -#endif - defineNativeProperty(vm, &module->values, "ENOLINK", NUMBER_VAL(ENOLINK)); -#ifdef EADV - defineNativeProperty(vm, &module->values, "EADV", NUMBER_VAL(EADV)); -#endif -#ifdef ESRMNT - defineNativeProperty(vm, &module->values, "ESRMNT", NUMBER_VAL(ESRMNT)); -#endif -#ifdef ECOMM - defineNativeProperty(vm, &module->values, "ECOMM", NUMBER_VAL(ECOMM)); -#endif - defineNativeProperty(vm, &module->values, "EPROTO", NUMBER_VAL(EPROTO)); -#ifdef EMULTIHOP - defineNativeProperty(vm, &module->values, "EMULTIHOP", NUMBER_VAL(EMULTIHOP)); -#endif -#ifdef EDOTDOT - defineNativeProperty(vm, &module->values, "EDOTDOT", NUMBER_VAL(EDOTDOT)); -#endif - defineNativeProperty(vm, &module->values, "EBADMSG", NUMBER_VAL(EBADMSG)); - defineNativeProperty(vm, &module->values, "EOVERFLOW", NUMBER_VAL(EOVERFLOW)); -#ifdef ENOTUNIQ - defineNativeProperty(vm, &module->values, "ENOTUNIQ", NUMBER_VAL(ENOTUNIQ)); -#endif -#ifdef EBADFD - defineNativeProperty(vm, &module->values, "EBADFD", NUMBER_VAL(EBADFD)); -#endif -#ifdef EREMCHG - defineNativeProperty(vm, &module->values, "EREMCHG", NUMBER_VAL(EREMCHG)); -#endif -#ifdef ELIBACC - defineNativeProperty(vm, &module->values, "ELIBACC", NUMBER_VAL(ELIBACC)); -#endif -#ifdef ELIBBAD - defineNativeProperty(vm, &module->values, "ELIBBAD", NUMBER_VAL(ELIBBAD)); -#endif -#ifdef ELIBSCN - defineNativeProperty(vm, &module->values, "ELIBSCN", NUMBER_VAL(ELIBSCN)); -#endif -#ifdef ELIBMAX - defineNativeProperty(vm, &module->values, "ELIBMAX", NUMBER_VAL(ELIBMAX)); -#endif -#ifdef ELIBEXEC - defineNativeProperty(vm, &module->values, "ELIBEXEC", NUMBER_VAL(ELIBEXEC)); -#endif - defineNativeProperty(vm, &module->values, "EILSEQ", NUMBER_VAL(EILSEQ)); -#ifdef ERESTART - defineNativeProperty(vm, &module->values, "ERESTART", NUMBER_VAL(ERESTART)); -#endif -#ifdef ESTRPIPE - defineNativeProperty(vm, &module->values, "ESTRPIPE", NUMBER_VAL(ESTRPIPE)); -#endif -#ifdef EUSERS - defineNativeProperty(vm, &module->values, "EUSERS", NUMBER_VAL(EUSERS)); -#endif - defineNativeProperty(vm, &module->values, "ENOTSOCK", NUMBER_VAL(ENOTSOCK)); - defineNativeProperty(vm, &module->values, "EDESTADDRREQ", NUMBER_VAL(EDESTADDRREQ)); - defineNativeProperty(vm, &module->values, "EMSGSIZE", NUMBER_VAL(EMSGSIZE)); - defineNativeProperty(vm, &module->values, "EPROTOTYPE", NUMBER_VAL(EPROTOTYPE)); - defineNativeProperty(vm, &module->values, "ENOPROTOOPT", NUMBER_VAL(ENOPROTOOPT)); - defineNativeProperty(vm, &module->values, "EPROTONOSUPPORT", NUMBER_VAL(EPROTONOSUPPORT)); -#ifdef ESOCKTNOSUPPORT - defineNativeProperty(vm, &module->values, "ESOCKTNOSUPPORT", NUMBER_VAL(ESOCKTNOSUPPORT)); -#endif - defineNativeProperty(vm, &module->values, "EOPNOTSUPP", NUMBER_VAL(EOPNOTSUPP)); -#ifdef EPFNOSUPPORT - defineNativeProperty(vm, &module->values, "EPFNOSUPPORT", NUMBER_VAL(EPFNOSUPPORT)); -#endif - defineNativeProperty(vm, &module->values, "EAFNOSUPPORT", NUMBER_VAL(EAFNOSUPPORT)); - defineNativeProperty(vm, &module->values, "EADDRINUSE", NUMBER_VAL(EADDRINUSE)); - defineNativeProperty(vm, &module->values, "EADDRNOTAVAIL", NUMBER_VAL(EADDRNOTAVAIL)); - defineNativeProperty(vm, &module->values, "ENETDOWN", NUMBER_VAL(ENETDOWN)); - defineNativeProperty(vm, &module->values, "ENETUNREACH", NUMBER_VAL(ENETUNREACH)); - defineNativeProperty(vm, &module->values, "ENETRESET", NUMBER_VAL(ENETRESET)); - defineNativeProperty(vm, &module->values, "ECONNABORTED", NUMBER_VAL(ECONNABORTED)); - defineNativeProperty(vm, &module->values, "ECONNRESET", NUMBER_VAL(ECONNRESET)); - defineNativeProperty(vm, &module->values, "ENOBUFS", NUMBER_VAL(ENOBUFS)); - defineNativeProperty(vm, &module->values, "EISCONN", NUMBER_VAL(EISCONN)); - defineNativeProperty(vm, &module->values, "ENOTCONN", NUMBER_VAL(ENOTCONN)); -#ifdef ESHUTDOWN - defineNativeProperty(vm, &module->values, "ESHUTDOWN", NUMBER_VAL(ESHUTDOWN)); -#endif -#ifdef ETOOMANYREFS - defineNativeProperty(vm, &module->values, "ETOOMANYREFS", NUMBER_VAL(ETOOMANYREFS)); -#endif - defineNativeProperty(vm, &module->values, "ETIMEDOUT", NUMBER_VAL(ETIMEDOUT)); - defineNativeProperty(vm, &module->values, "ECONNREFUSED", NUMBER_VAL(ECONNREFUSED)); -#ifdef EHOSTDOWN - defineNativeProperty(vm, &module->values, "EHOSTDOWN", NUMBER_VAL(EHOSTDOWN)); -#endif - defineNativeProperty(vm, &module->values, "EHOSTUNREACH", NUMBER_VAL(EHOSTUNREACH)); - defineNativeProperty(vm, &module->values, "EALREADY", NUMBER_VAL(EALREADY)); - defineNativeProperty(vm, &module->values, "EINPROGRESS", NUMBER_VAL(EINPROGRESS)); -#ifdef ESTALE - defineNativeProperty(vm, &module->values, "ESTALE", NUMBER_VAL(ESTALE)); -#endif -#ifdef EUCLEAN - defineNativeProperty(vm, &module->values, "EUCLEAN", NUMBER_VAL(EUCLEAN)); -#endif -#ifdef ENOTNAM - defineNativeProperty(vm, &module->values, "ENOTNAM", NUMBER_VAL(ENOTNAM)); -#endif -#ifdef ENAVAIL - defineNativeProperty(vm, &module->values, "ENAVAIL", NUMBER_VAL(ENAVAIL)); -#endif -#ifdef EISNAM - defineNativeProperty(vm, &module->values, "EISNAM", NUMBER_VAL(EISNAM)); -#endif -#ifdef EREMOTEIO - defineNativeProperty(vm, &module->values, "EREMOTEIO", NUMBER_VAL(EREMOTEIO)); -#endif -#ifdef EDQUOT - defineNativeProperty(vm, &module->values, "EDQUOT", NUMBER_VAL(EDQUOT)); -#endif -#ifdef ENOMEDIUM - defineNativeProperty(vm, &module->values, "ENOMEDIUM", NUMBER_VAL(ENOMEDIUM)); -#endif -#ifdef EMEDIUMTYPE - defineNativeProperty(vm, &module->values, "EMEDIUMTYPE", NUMBER_VAL(EMEDIUMTYPE)); -#endif - defineNativeProperty(vm, &module->values, "ECANCELED", NUMBER_VAL(ECANCELED)); -#ifdef ENOKEY - defineNativeProperty(vm, &module->values, "ENOKEY", NUMBER_VAL(ENOKEY)); -#endif -#ifdef EKEYEXPIRED - defineNativeProperty(vm, &module->values, "EKEYEXPIRED", NUMBER_VAL(EKEYEXPIRED)); -#endif -#ifdef EKEYREVOKED - defineNativeProperty(vm, &module->values, "EKEYREVOKED", NUMBER_VAL(EKEYREVOKED)); -#endif -#ifdef EKEYREJECTED - defineNativeProperty(vm, &module->values, "EKEYREJECTED", NUMBER_VAL(EKEYREJECTED)); -#endif - defineNativeProperty(vm, &module->values, "EOWNERDEAD", NUMBER_VAL(EOWNERDEAD)); - defineNativeProperty(vm, &module->values, "ENOTRECOVERABLE", NUMBER_VAL(ENOTRECOVERABLE)); -#ifdef ERFKILL - defineNativeProperty(vm, &module->values, "ERFKILL", NUMBER_VAL(ERFKILL)); -#endif -#ifdef EHWPOISON - defineNativeProperty(vm, &module->values, "EHWPOISON", NUMBER_VAL(EHWPOISON)); -#endif - - pop(vm); - pop(vm); - - return OBJ_VAL(module); -} diff --git a/src/optionals/c.h b/src/optionals/c.h index 14ea5d0bd..3fc9f6a0d 100644 --- a/src/optionals/c.h +++ b/src/optionals/c.h @@ -39,8 +39,6 @@ #include "../vm/vm.h" #include "../vm/memory.h" -Value createCModule(DictuVM *vm); - void getStrerror(char *buf, int error); #endif //dictu_c_h diff --git a/src/optionals/optionals.c b/src/optionals/optionals.c index 35ca31765..d76a5e3ab 100644 --- a/src/optionals/optionals.c +++ b/src/optionals/optionals.c @@ -1,7 +1,6 @@ #include "optionals.h" BuiltinModules modules[] = { - {"C", &createCModule, false}, {"Argparse", &createArgParseModule, false}, {"Math", &createMathsModule, false}, {"Env", &createEnvModule, true}, From 6687a21e5ce22518e1e09627f876bb067471d583 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Fri, 1 Dec 2023 13:10:32 +0000 Subject: [PATCH 022/148] Fix an issue with internal table type --- src/vm/table.c | 58 +++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/vm/table.c b/src/vm/table.c index 554d97ca4..e3f2b330a 100644 --- a/src/vm/table.c +++ b/src/vm/table.c @@ -10,22 +10,22 @@ void initTable(Table *table) { table->count = 0; - table->capacityMask = -1; + table->capacityMask = 0; table->entries = NULL; } void freeTable(DictuVM *vm, Table *table) { - FREE_ARRAY(vm, Entry, table->entries, table->capacityMask + 1); + FREE_ARRAY(vm, Entry, table->entries, table->capacityMask); initTable(table); } static Entry *findEntry(Entry *entries, int capacityMask, ObjString *key) { - uint32_t index = key->hash & capacityMask; - Entry *tombstone = NULL; + uint32_t index = key->hash & (capacityMask - 1); + Entry* tombstone = NULL; for (;;) { - Entry *entry = &entries[index]; + Entry* entry = &entries[index]; if (entry->key == NULL) { if (IS_NIL(entry->value)) { @@ -40,7 +40,7 @@ static Entry *findEntry(Entry *entries, int capacityMask, return entry; } - index = (index + 1) & capacityMask; + index = (index + 1) & (capacityMask - 1); } } @@ -55,34 +55,33 @@ bool tableGet(Table *table, ObjString *key, Value *value) { } static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) { - Entry *entries = ALLOCATE(vm, Entry, capacityMask + 1); - for (int i = 0; i <= capacityMask; i++) { + Entry* entries = ALLOCATE(vm, Entry, capacityMask); + for (int i = 0; i < capacityMask; i++) { entries[i].key = NULL; entries[i].value = NIL_VAL; } table->count = 0; - for (int i = 0; i <= table->capacityMask; i++) { - Entry *entry = &table->entries[i]; + for (int i = 0; i < table->capacityMask; i++) { + Entry* entry = &table->entries[i]; if (entry->key == NULL) continue; - Entry *dest = findEntry(entries, capacityMask, entry->key); + Entry* dest = findEntry(entries, capacityMask, entry->key); dest->key = entry->key; dest->value = entry->value; table->count++; } - FREE_ARRAY(vm, Entry, table->entries, table->capacityMask + 1); + FREE_ARRAY(vm, Entry, table->entries, table->capacityMask); table->entries = entries; table->capacityMask = capacityMask; } bool tableSet(DictuVM *vm, Table *table, ObjString *key, Value value) { - if (table->count + 1 > (table->capacityMask + 1) * TABLE_MAX_LOAD) { - // Figure out the new table size. - int capacityMask = GROW_CAPACITY(table->capacityMask + 1) - 1; - adjustCapacity(vm, table, capacityMask); + if (table->count + 1 > table->capacityMask * TABLE_MAX_LOAD) { + int capacity = GROW_CAPACITY(table->capacityMask); + adjustCapacity(vm, table, capacity); } Entry *entry = findEntry(table->entries, table->capacityMask, key); @@ -99,20 +98,19 @@ bool tableDelete(DictuVM *vm, Table *table, ObjString *key) { UNUSED(vm); if (table->count == 0) return false; - Entry *entry = findEntry(table->entries, table->capacityMask, key); + // Find the entry. + Entry* entry = findEntry(table->entries, table->capacityMask, key); if (entry->key == NULL) return false; // Place a tombstone in the entry. - table->count--; entry->key = NULL; entry->value = BOOL_VAL(true); - return true; } void tableAddAll(DictuVM *vm, Table *from, Table *to) { - for (int i = 0; i <= from->capacityMask; i++) { - Entry *entry = &from->entries[i]; + for (int i = 0; i < from->capacityMask; i++) { + Entry* entry = &from->entries[i]; if (entry->key != NULL) { tableSet(vm, to, entry->key, entry->value); } @@ -127,13 +125,12 @@ ObjString *tableFindString(Table *table, const char *chars, int length, // Figure out where to insert it in the table. Use open addressing and // basic linear probing. - - uint32_t index = hash & table->capacityMask; + uint32_t index = hash & (table->capacityMask - 1); for (;;) { - Entry *entry = &table->entries[index]; - + Entry* entry = &table->entries[index]; if (entry->key == NULL) { + // Stop if we find an empty non-tombstone entry. if (IS_NIL(entry->value)) return NULL; } else if (entry->key->length == length && entry->key->hash == hash && @@ -142,14 +139,13 @@ ObjString *tableFindString(Table *table, const char *chars, int length, return entry->key; } - // Try the next slot. - index = (index + 1) & table->capacityMask; + index = (index + 1) & (table->capacityMask - 1); } } -void tableRemoveWhite(DictuVM *vm, Table *table) { - for (int i = 0; i <= table->capacityMask; i++) { - Entry *entry = &table->entries[i]; +void tableRemoveWhite(DictuVM *vm, Table* table) { + for (int i = 0; i < table->capacityMask; i++) { + Entry* entry = &table->entries[i]; if (entry->key != NULL && !entry->key->obj.isDark) { tableDelete(vm, table, entry->key); } @@ -157,7 +153,7 @@ void tableRemoveWhite(DictuVM *vm, Table *table) { } void grayTable(DictuVM *vm, Table *table) { - for (int i = 0; i <= table->capacityMask; i++) { + for (int i = 0; i < table->capacityMask; i++) { Entry *entry = &table->entries[i]; grayObject(vm, (Obj *) entry->key); grayValue(vm, entry->value); From 14196fd7c2d80ae288a40b1b1254b36766e375c9 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Fri, 1 Dec 2023 13:16:51 +0000 Subject: [PATCH 023/148] Correct use of capacity --- src/optionals/unittest/unittest.c | 2 +- src/vm/datatypes/class.c | 2 +- src/vm/datatypes/copy.c | 4 +-- src/vm/datatypes/enums.c | 2 +- src/vm/datatypes/instance.c | 10 +++---- src/vm/object.c | 6 ++-- src/vm/table.c | 48 +++++++++++++++---------------- src/vm/table.h | 2 +- src/vm/vm.c | 2 +- 9 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/optionals/unittest/unittest.c b/src/optionals/unittest/unittest.c index 23268c63b..31dd627e0 100644 --- a/src/optionals/unittest/unittest.c +++ b/src/optionals/unittest/unittest.c @@ -31,7 +31,7 @@ static Value mockNative(DictuVM *vm, int argCount, Value *args) { pop(vm); push(vm, OBJ_VAL(mockedClass)); - for (int i = 0; i <= klass->publicMethods.capacityMask; ++i) { + for (int i = 0; i < klass->publicMethods.capacity; ++i) { if (klass->publicMethods.entries[i].key == NULL) { continue; } diff --git a/src/vm/datatypes/class.c b/src/vm/datatypes/class.c index b783c46b2..939295da1 100644 --- a/src/vm/datatypes/class.c +++ b/src/vm/datatypes/class.c @@ -38,7 +38,7 @@ static Value methods(DictuVM *vm, int argCount, Value *args) { ObjList *list = newList(vm); push(vm, OBJ_VAL(list)); - for (int i = 0; i <= klass->publicMethods.capacityMask; ++i) { + for (int i = 0; i < klass->publicMethods.capacity; ++i) { if (klass->publicMethods.entries[i].key == NULL) { continue; } diff --git a/src/vm/datatypes/copy.c b/src/vm/datatypes/copy.c index 55c21b2d1..c1862da5b 100644 --- a/src/vm/datatypes/copy.c +++ b/src/vm/datatypes/copy.c @@ -70,7 +70,7 @@ ObjInstance *copyInstance(DictuVM* vm, ObjInstance *oldInstance, bool shallow) { if (shallow) { tableAddAll(vm, &oldInstance->publicAttributes, &instance->publicAttributes); } else { - for (int i = 0; i <= oldInstance->publicAttributes.capacityMask; i++) { + for (int i = 0; i < oldInstance->publicAttributes.capacity; i++) { Entry *entry = &oldInstance->publicAttributes.entries[i]; if (entry->key != NULL) { Value val = entry->value; @@ -90,7 +90,7 @@ ObjInstance *copyInstance(DictuVM* vm, ObjInstance *oldInstance, bool shallow) { } } - for (int i = 0; i <= oldInstance->privateAttributes.capacityMask; i++) { + for (int i = 0; i < oldInstance->privateAttributes.capacity; i++) { Entry *entry = &oldInstance->privateAttributes.entries[i]; if (entry->key != NULL) { Value val = entry->value; diff --git a/src/vm/datatypes/enums.c b/src/vm/datatypes/enums.c index 7a5c170c3..2d3ac7ac7 100644 --- a/src/vm/datatypes/enums.c +++ b/src/vm/datatypes/enums.c @@ -10,7 +10,7 @@ static Value values(DictuVM *vm, int argCount, Value *args) { ObjDict *dict = newDict(vm); push(vm, OBJ_VAL(dict)); - for (int i = 0; i < objEnum->values.capacityMask + 1; ++i) { + for (int i = 0; i < objEnum->values.capacity; ++i) { if (objEnum->values.entries[i].key == NULL) { continue; } diff --git a/src/vm/datatypes/instance.c b/src/vm/datatypes/instance.c index 0952169e7..8d497de35 100644 --- a/src/vm/datatypes/instance.c +++ b/src/vm/datatypes/instance.c @@ -132,7 +132,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) { // Walk the inheritance chain while (klass != NULL) { - for (int i = 0; i < klass->variables.capacityMask + 1; i++) { + for (int i = 0; i < klass->variables.capacity; i++) { if (klass->variables.entries[i].key == NULL) { continue; } @@ -144,7 +144,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) { writeValueArray(vm, &fields->values, OBJ_VAL(klass->variables.entries[i].key)); } - for (int i = 0; i < klass->constants.capacityMask + 1; i++) { + for (int i = 0; i < klass->constants.capacity; i++) { if (klass->constants.entries[i].key == NULL) { continue; } @@ -170,7 +170,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) { ObjList *attributes = newList(vm); push(vm, OBJ_VAL(attributes)); - for (int i = 0; i < instance->publicAttributes.capacityMask + 1; i++) { + for (int i = 0; i < instance->publicAttributes.capacity; i++) { if (instance->publicAttributes.entries[i].key == NULL) { continue; } @@ -193,7 +193,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) { ObjList *methods = newList(vm); push(vm, OBJ_VAL(methods)); - for (int i = 0; i <= instance->klass->publicMethods.capacityMask; ++i) { + for (int i = 0; i < instance->klass->publicMethods.capacity; ++i) { if (instance->klass->publicMethods.entries[i].key == NULL) { continue; } @@ -295,7 +295,7 @@ static Value methods(DictuVM *vm, int argCount, Value *args) { ObjList *list = newList(vm); push(vm, OBJ_VAL(list)); - for (int i = 0; i <= instance->klass->publicMethods.capacityMask; ++i) { + for (int i = 0; i < instance->klass->publicMethods.capacity; ++i) { if (instance->klass->publicMethods.entries[i].key == NULL) { continue; } diff --git a/src/vm/object.c b/src/vm/object.c index 9257f605e..ac677abd7 100644 --- a/src/vm/object.c +++ b/src/vm/object.c @@ -550,21 +550,21 @@ ObjDict *classToDict(DictuVM *vm, Value value) { push(vm, OBJ_VAL(methodsList)); while (klass != NULL) { - for (int i = 0; i < klass->variables.capacityMask + 1; i++) { + for (int i = 0; i < klass->variables.capacity; i++) { if (klass->variables.entries[i].key == NULL) { continue; } dictSet(vm, variablesDict, OBJ_VAL(klass->variables.entries[i].key), klass->variables.entries[i].value); } - for (int i = 0; i < klass->constants.capacityMask + 1; i++) { + for (int i = 0; i < klass->constants.capacity; i++) { if (klass->constants.entries[i].key == NULL) { continue; } dictSet(vm, constantsDict, OBJ_VAL(klass->constants.entries[i].key), klass->constants.entries[i].value); } - for (int i = 0; i < klass->publicMethods.capacityMask + 1; i++) { + for (int i = 0; i < klass->publicMethods.capacity; i++) { if (klass->publicMethods.entries[i].key == NULL) { continue; } diff --git a/src/vm/table.c b/src/vm/table.c index e3f2b330a..e1c0e9d26 100644 --- a/src/vm/table.c +++ b/src/vm/table.c @@ -10,22 +10,22 @@ void initTable(Table *table) { table->count = 0; - table->capacityMask = 0; + table->capacity = 0; table->entries = NULL; } void freeTable(DictuVM *vm, Table *table) { - FREE_ARRAY(vm, Entry, table->entries, table->capacityMask); + FREE_ARRAY(vm, Entry, table->entries, table->capacity); initTable(table); } static Entry *findEntry(Entry *entries, int capacityMask, ObjString *key) { uint32_t index = key->hash & (capacityMask - 1); - Entry* tombstone = NULL; + Entry *tombstone = NULL; for (;;) { - Entry* entry = &entries[index]; + Entry *entry = &entries[index]; if (entry->key == NULL) { if (IS_NIL(entry->value)) { @@ -47,7 +47,7 @@ static Entry *findEntry(Entry *entries, int capacityMask, bool tableGet(Table *table, ObjString *key, Value *value) { if (table->count == 0) return false; - Entry *entry = findEntry(table->entries, table->capacityMask, key); + Entry *entry = findEntry(table->entries, table->capacity, key); if (entry->key == NULL) return false; *value = entry->value; @@ -55,7 +55,7 @@ bool tableGet(Table *table, ObjString *key, Value *value) { } static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) { - Entry* entries = ALLOCATE(vm, Entry, capacityMask); + Entry *entries = ALLOCATE(vm, Entry, capacityMask); for (int i = 0; i < capacityMask; i++) { entries[i].key = NULL; entries[i].value = NIL_VAL; @@ -63,28 +63,28 @@ static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) { table->count = 0; - for (int i = 0; i < table->capacityMask; i++) { - Entry* entry = &table->entries[i]; + for (int i = 0; i < table->capacity; i++) { + Entry *entry = &table->entries[i]; if (entry->key == NULL) continue; - Entry* dest = findEntry(entries, capacityMask, entry->key); + Entry *dest = findEntry(entries, capacityMask, entry->key); dest->key = entry->key; dest->value = entry->value; table->count++; } - FREE_ARRAY(vm, Entry, table->entries, table->capacityMask); + FREE_ARRAY(vm, Entry, table->entries, table->capacity); table->entries = entries; - table->capacityMask = capacityMask; + table->capacity = capacityMask; } bool tableSet(DictuVM *vm, Table *table, ObjString *key, Value value) { - if (table->count + 1 > table->capacityMask * TABLE_MAX_LOAD) { - int capacity = GROW_CAPACITY(table->capacityMask); + if (table->count + 1 > table->capacity * TABLE_MAX_LOAD) { + int capacity = GROW_CAPACITY(table->capacity); adjustCapacity(vm, table, capacity); } - Entry *entry = findEntry(table->entries, table->capacityMask, key); + Entry *entry = findEntry(table->entries, table->capacity, key); bool isNewKey = entry->key == NULL; entry->key = key; entry->value = value; @@ -99,7 +99,7 @@ bool tableDelete(DictuVM *vm, Table *table, ObjString *key) { if (table->count == 0) return false; // Find the entry. - Entry* entry = findEntry(table->entries, table->capacityMask, key); + Entry *entry = findEntry(table->entries, table->capacity, key); if (entry->key == NULL) return false; // Place a tombstone in the entry. @@ -109,8 +109,8 @@ bool tableDelete(DictuVM *vm, Table *table, ObjString *key) { } void tableAddAll(DictuVM *vm, Table *from, Table *to) { - for (int i = 0; i < from->capacityMask; i++) { - Entry* entry = &from->entries[i]; + for (int i = 0; i < from->capacity; i++) { + Entry *entry = &from->entries[i]; if (entry->key != NULL) { tableSet(vm, to, entry->key, entry->value); } @@ -125,10 +125,10 @@ ObjString *tableFindString(Table *table, const char *chars, int length, // Figure out where to insert it in the table. Use open addressing and // basic linear probing. - uint32_t index = hash & (table->capacityMask - 1); + uint32_t index = hash & (table->capacity - 1); for (;;) { - Entry* entry = &table->entries[index]; + Entry *entry = &table->entries[index]; if (entry->key == NULL) { // Stop if we find an empty non-tombstone entry. if (IS_NIL(entry->value)) return NULL; @@ -139,13 +139,13 @@ ObjString *tableFindString(Table *table, const char *chars, int length, return entry->key; } - index = (index + 1) & (table->capacityMask - 1); + index = (index + 1) & (table->capacity - 1); } } -void tableRemoveWhite(DictuVM *vm, Table* table) { - for (int i = 0; i < table->capacityMask; i++) { - Entry* entry = &table->entries[i]; +void tableRemoveWhite(DictuVM *vm, Table *table) { + for (int i = 0; i < table->capacity; i++) { + Entry *entry = &table->entries[i]; if (entry->key != NULL && !entry->key->obj.isDark) { tableDelete(vm, table, entry->key); } @@ -153,7 +153,7 @@ void tableRemoveWhite(DictuVM *vm, Table* table) { } void grayTable(DictuVM *vm, Table *table) { - for (int i = 0; i < table->capacityMask; i++) { + for (int i = 0; i < table->capacity; i++) { Entry *entry = &table->entries[i]; grayObject(vm, (Obj *) entry->key); grayValue(vm, entry->value); diff --git a/src/vm/table.h b/src/vm/table.h index a4e9cbffb..d42e577ff 100644 --- a/src/vm/table.h +++ b/src/vm/table.h @@ -14,7 +14,7 @@ typedef struct { typedef struct { int count; - int capacityMask; + int capacity; Entry *entries; } Table; diff --git a/src/vm/vm.c b/src/vm/vm.c index 8819d190b..3e6e8306b 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -2276,7 +2276,7 @@ static DictuInterpretResult run(DictuVM *vm) { ObjClass *klass = AS_CLASS(peek(vm, 0)); // If super class is abstract, ensure we have defined all abstract methods - for (int i = 0; i < klass->abstractMethods.capacityMask + 1; i++) { + for (int i = 0; i < klass->abstractMethods.capacity; i++) { if (klass->abstractMethods.entries[i].key == NULL) { continue; } From 8a9bf68fdef694a1daaae6312c2322e663b27a8d Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 3 Dec 2023 12:34:18 -0700 Subject: [PATCH 024/148] resolve typo and use single macro Signed-off-by: Brian Downs --- src/vm/vm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index 3e6e8306b..2892136d9 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -51,6 +51,8 @@ static void resetStack(DictuVM *vm) { unpack = false; \ } +#define INSTANCE_HAS_NO_ATTR_ERR RUNTIME_ERROR("'%s' instance has no attribute: '%s'.", instance->klass->name->chars, name->chars) + void runtimeError(DictuVM *vm, const char *format, ...) { for (int i = vm->frameCount - 1; i >= 0; i--) { CallFrame *frame = &vm->frames[i]; @@ -1139,7 +1141,7 @@ static DictuInterpretResult run(DictuVM *vm) { RUNTIME_ERROR("Cannot access private attribute '%s' on '%s' instance.", name->chars, instance->klass->name->chars); } - RUNTIME_ERROR("'%s' instance has no attribute: '%s'.", instance->klass->name->chars, name->chars); + INSTANCE_HAS_NO_ATTR_ERR; } case OBJ_MODULE: { @@ -1259,7 +1261,7 @@ static DictuInterpretResult run(DictuVM *vm) { klass = klass->superclass; } - RUNTIME_ERROR("'%s' instance has no attribute1: '%s'.", instance->klass->name->chars, name->chars); + INSTANCE_HAS_NO_ATTR_ERR; } else if (IS_CLASS(peek(vm, 0))) { ObjClass *klass = AS_CLASS(peek(vm, 0)); // Used to keep a reference to the class for the runtime error below @@ -1369,7 +1371,7 @@ static DictuInterpretResult run(DictuVM *vm) { klass = klass->superclass; } - RUNTIME_ERROR("'%s' instance has no attribute3: '%s'.", instance->klass->name->chars, name->chars); + INSTANCE_HAS_NO_ATTR_ERR; } CASE_CODE(SET_ATTRIBUTE): { From b8a50d9e68257ddd0f20e4a67c6910cbccda5a07 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Sun, 3 Dec 2023 20:16:59 +0000 Subject: [PATCH 025/148] Fix issue where string was getting popped before created --- src/vm/vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index 2892136d9..e15ea5baf 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1873,9 +1873,10 @@ static DictuInterpretResult run(DictuVM *vm) { index = string->length + index; if (index >= 0 && index < string->length) { + ObjString *newString = copyString(vm, &string->chars[index], 1); pop(vm); pop(vm); - push(vm, OBJ_VAL(copyString(vm, &string->chars[index], 1))); + push(vm, OBJ_VAL(newString)); DISPATCH(); } From b893dc4f0bf9de35b27202cdfc30db5b62b24bf1 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 8 Dec 2023 15:04:33 -0700 Subject: [PATCH 026/148] initial support for dictu path and relocate history Signed-off-by: Brian Downs --- src/cli/main.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/cli/main.c b/src/cli/main.c index e9e1fe179..32cee29f9 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -1,6 +1,14 @@ +#ifdef __linux__ +#include +#else +#include +#endif #include #include #include +#include +#include +#include #define UNUSED(__x__) (void) __x__ @@ -13,6 +21,9 @@ #include "linenoise/linenoise.h" +#define DICTU_HOME "/.dictu" +#define DICTU_HIST "/history.txt" + static int matchStringLiteral(char* line, int i) { char quote = line[i]; @@ -66,10 +77,36 @@ static void memcpyAndAppendNul(char* dst, char* src, int len) { dst[len] = '\0'; } +// getDictuPath sets up the path to be used for saving history +// amongst other things. The returned string needs to be freed +// by the caller. +char *getDictuPath() { + char *dictuPath = calloc(PATH_MAX, sizeof(char) * PATH_MAX); + char *tmp; + + if ((tmp = getenv("DICTU_PATH")) != NULL ) { + strncpy(dictuPath, tmp, strlen(tmp)); + } else { + const char *home = getenv("HOME"); + strncpy(dictuPath, home, strlen(home)); + strncat(dictuPath, DICTU_HOME, strlen(DICTU_HOME)); + } + + return dictuPath; +} + static void repl(DictuVM *vm) { printf(DICTU_STRING_VERSION); char *line; - linenoiseHistoryLoad("history.txt"); + + char *dictuPath = getDictuPath(); + // create ${HOME}/.dictu. Silently fail if + // already exists. + mkdir(dictuPath, 0700); + + strncat(dictuPath, DICTU_HIST, strlen(DICTU_HIST)); + + linenoiseHistoryLoad(dictuPath); while((line = linenoise(">>> ")) != NULL) { int statementLength = strlen(line); @@ -77,7 +114,7 @@ static void repl(DictuVM *vm) { memcpyAndAppendNul(statement, line, statementLength); linenoiseHistoryAdd(line); - linenoiseHistorySave("history.txt"); + linenoiseHistorySave(dictuPath); while (!matchBraces(statement)) { free(line); @@ -101,12 +138,13 @@ static void repl(DictuVM *vm) { statementLength += lineLength; linenoiseHistoryAdd(line); - linenoiseHistorySave("history.txt"); + linenoiseHistorySave(dictuPath); } dictuInterpret(vm, "repl", statement); free(line); + free(dictuPath); free(statement); } } From 9d8ae53c1e3c8b24fd75aee2b43bb270d3abe889 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 8 Dec 2023 16:06:01 -0700 Subject: [PATCH 027/148] account for windows Signed-off-by: Brian Downs --- src/cli/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/main.c b/src/cli/main.c index 32cee29f9..b50a3feb6 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -1,6 +1,6 @@ -#ifdef __linux__ +#if defined(__linux__) || defined(_WIN32) #include -#else +#elif defined(__APPLE__) || defined(__FreeBSD__) #include #endif #include From 76bc192fb963aed8ecc554d5d10b58bc15c09b86 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 8 Dec 2023 16:11:58 -0700 Subject: [PATCH 028/148] windows api include Signed-off-by: Brian Downs --- src/cli/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cli/main.c b/src/cli/main.c index b50a3feb6..1e69bef49 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -8,7 +8,11 @@ #include #include #include +#ifdef _WIN32 +#include "../optionals/windowsapi.h" +#else #include +#endif #define UNUSED(__x__) (void) __x__ From 66c51f2c1eafd5d2aa0e5e44e8085cff86838876 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 8 Dec 2023 16:18:57 -0700 Subject: [PATCH 029/148] attempting to get sneaky Signed-off-by: Brian Downs --- src/cli/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cli/main.c b/src/cli/main.c index 1e69bef49..0920d0f9e 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -10,6 +10,7 @@ #include #ifdef _WIN32 #include "../optionals/windowsapi.h" +#define PATH_MAX MAX_PATH #else #include #endif From 1fab11216a8e965e1f8fc7551e1b75e84af1cb1a Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 10 Dec 2023 15:32:52 -0700 Subject: [PATCH 030/148] handle mkdir error Signed-off-by: Brian Downs --- src/cli/main.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cli/main.c b/src/cli/main.c index 0920d0f9e..8feb4559b 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -1,3 +1,4 @@ +#include #if defined(__linux__) || defined(_WIN32) #include #elif defined(__APPLE__) || defined(__FreeBSD__) @@ -89,8 +90,8 @@ char *getDictuPath() { char *dictuPath = calloc(PATH_MAX, sizeof(char) * PATH_MAX); char *tmp; - if ((tmp = getenv("DICTU_PATH")) != NULL ) { - strncpy(dictuPath, tmp, strlen(tmp)); + if ((tmp = getenv("DICTU_PATH")) != NULL) { + strncat(dictuPath, tmp, strlen(tmp)); } else { const char *home = getenv("HOME"); strncpy(dictuPath, home, strlen(home)); @@ -105,9 +106,12 @@ static void repl(DictuVM *vm) { char *line; char *dictuPath = getDictuPath(); - // create ${HOME}/.dictu. Silently fail if - // already exists. - mkdir(dictuPath, 0700); + + if (mkdir(dictuPath, 0700) == -1) { + fprintf(stderr, "Cannot create directory %s - %s\n", dictuPath, strerror(errno)); + free(dictuPath); + exit(75); + } strncat(dictuPath, DICTU_HIST, strlen(DICTU_HIST)); From 3df79e3b18772a0b29df1f19b8b6e004f6d502e9 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Fri, 15 Dec 2023 21:32:03 -0700 Subject: [PATCH 031/148] add ability for dictu to load user modules Signed-off-by: Brian Downs --- src/vm/vm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index e15ea5baf..4866dd9f6 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1645,7 +1645,12 @@ static DictuInterpretResult run(DictuVM *vm) { char path[PATH_MAX]; if (!resolvePath(frame->closure->function->module->path->chars, fileName->chars, path)) { - RUNTIME_ERROR("Could not open file \"%s\".", fileName->chars); + // if not found, try to load from the user's modules + memset(path, 0, PATH_MAX); + char *home_dir = getenv("HOME"); + strcat(path, home_dir); + strcat(path, "/.dictu/modules/"); + strcat(path, fileName->chars); } ObjString *pathObj = copyString(vm, path, strlen(path)); From 602c0d11276bfce235fd7d413b70a8ba807db957 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 16 Dec 2023 21:01:51 -0700 Subject: [PATCH 032/148] account for history existing Signed-off-by: Brian Downs --- src/cli/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cli/main.c b/src/cli/main.c index 8feb4559b..371f2e6ad 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -107,7 +107,8 @@ static void repl(DictuVM *vm) { char *dictuPath = getDictuPath(); - if (mkdir(dictuPath, 0700) == -1) { + const int res = mkdir(dictuPath, 0700); + if (errno != EEXIST) { fprintf(stderr, "Cannot create directory %s - %s\n", dictuPath, strerror(errno)); free(dictuPath); exit(75); From 28880ad96b1467c6834226ee336e827296f5a647 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 16 Dec 2023 21:04:47 -0700 Subject: [PATCH 033/148] simplify Signed-off-by: Brian Downs --- src/cli/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cli/main.c b/src/cli/main.c index 371f2e6ad..cfb74ab99 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -107,8 +107,7 @@ static void repl(DictuVM *vm) { char *dictuPath = getDictuPath(); - const int res = mkdir(dictuPath, 0700); - if (errno != EEXIST) { + if (mkdir(dictuPath, 0700) == -1 && errno != EEXIST) { fprintf(stderr, "Cannot create directory %s - %s\n", dictuPath, strerror(errno)); free(dictuPath); exit(75); From a163c30fc8650df70fe40f5ba7adf9544382c66f Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 18 Dec 2023 11:00:40 -0700 Subject: [PATCH 034/148] update to use relevative path Signed-off-by: Brian Downs --- dmi.db | Bin 0 -> 20480 bytes src/cli/main.c | 2 +- src/vm/vm.c | 23 ++++++++++++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 dmi.db diff --git a/dmi.db b/dmi.db new file mode 100644 index 0000000000000000000000000000000000000000..4ac664aa16d6d44e6394bb4a0563ed549e7e2a07 GIT binary patch literal 20480 zcmeI#K~EY%6u|LaK{?TS<6uml^@5S~;-!ffR~QYEU2z$bk{-y`9g~fK3g{jC1^a!x z^nnk?iO`5Up(q&uV&(t%s%}*F(2DsYjm$?S_?VJC1c{clyhg4Z>zcQrB}UXBG06+%u*UX^t8C` zj@-ke8(h1UVQwk4mBm?h72SC-`QaBzJ3Icb;w#f-t=%xK@b$5=bjEyA%Bj0|gH-=B zbE7%Sg4UB8j #include #include #include #include -#include +#ifdef _WIN32 +#include "windowsapi.h" +#else +#include +#endif #include "common.h" #include "compiler.h" @@ -27,6 +32,10 @@ #include "natives.h" #include "../optionals/optionals.h" +#ifdef _WIN32 +#define getcwd(BUFFER, MAXLEN) _getcwd(BUFFER, MAXLEN) +#endif + static void resetStack(DictuVM *vm) { vm->stackTop = vm->stack; vm->frameCount = 0; @@ -1645,11 +1654,15 @@ static DictuInterpretResult run(DictuVM *vm) { char path[PATH_MAX]; if (!resolvePath(frame->closure->function->module->path->chars, fileName->chars, path)) { - // if not found, try to load from the user's modules + // if import is not found, try to load from the project's modules directory + memset(path, 0, PATH_MAX); - char *home_dir = getenv("HOME"); - strcat(path, home_dir); - strcat(path, "/.dictu/modules/"); + + if (getcwd(path, sizeof(path)) == NULL) { + RUNTIME_ERROR("Could not determine current working directiory."); + } + + strcat(path, "/dictu_modules/"); strcat(path, fileName->chars); } From 5fc1949893378e166f1c70a1ee5d0ed294fe6b65 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 18 Dec 2023 11:09:29 -0700 Subject: [PATCH 035/148] update path to win api Signed-off-by: Brian Downs --- src/vm/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index bbd65f9c9..fbb1b8911 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -4,7 +4,7 @@ #include #include #ifdef _WIN32 -#include "windowsapi.h" +#include "../optionals/windowsapi.h" #else #include #endif From 47f5212cf949224cf14e70498f8081e240475cee Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 18 Dec 2023 15:04:19 -0700 Subject: [PATCH 036/148] pr comment remediation Signed-off-by: Brian Downs --- src/vm/vm.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index fbb1b8911..0fef582a1 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -3,11 +3,6 @@ #include #include #include -#ifdef _WIN32 -#include "../optionals/windowsapi.h" -#else -#include -#endif #include "common.h" #include "compiler.h" @@ -32,10 +27,6 @@ #include "natives.h" #include "../optionals/optionals.h" -#ifdef _WIN32 -#define getcwd(BUFFER, MAXLEN) _getcwd(BUFFER, MAXLEN) -#endif - static void resetStack(DictuVM *vm) { vm->stackTop = vm->stack; vm->frameCount = 0; @@ -1656,14 +1647,9 @@ static DictuInterpretResult run(DictuVM *vm) { if (!resolvePath(frame->closure->function->module->path->chars, fileName->chars, path)) { // if import is not found, try to load from the project's modules directory - memset(path, 0, PATH_MAX); - - if (getcwd(path, sizeof(path)) == NULL) { - RUNTIME_ERROR("Could not determine current working directiory."); + if (!resolvePath("dictu_modules", fileName->chars, path)) { + RUNTIME_ERROR("Could not open file \"%s\".", fileName->chars); } - - strcat(path, "/dictu_modules/"); - strcat(path, fileName->chars); } ObjString *pathObj = copyString(vm, path, strlen(path)); From ecebc5449ffacae9f53d375a4a98df6fe580579d Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 18 Dec 2023 15:10:27 -0700 Subject: [PATCH 037/148] retrigger ci Signed-off-by: Brian Downs --- src/vm/vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/vm.c b/src/vm/vm.c index 0fef582a1..cef7c3c35 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1645,7 +1645,7 @@ static DictuInterpretResult run(DictuVM *vm) { char path[PATH_MAX]; if (!resolvePath(frame->closure->function->module->path->chars, fileName->chars, path)) { - // if import is not found, try to load from the project's modules directory + // if stdlib import is not found, try to load from the project's modules directory if (!resolvePath("dictu_modules", fileName->chars, path)) { RUNTIME_ERROR("Could not open file \"%s\".", fileName->chars); From 87a5d131d9c4114203997be681dd54651b3f69d7 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 19 Dec 2023 16:23:21 -0700 Subject: [PATCH 038/148] add rename, tests, and docs Signed-off-by: Brian Downs --- docs/docs/standard-lib/system.md | 14 ++++++++++++++ src/optionals/system.c | 22 ++++++++++++++++++++++ tests/system/import.du | 1 + tests/system/rename.du | 28 ++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 tests/system/rename.du diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index b1e54e8bc..560e00993 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -252,6 +252,20 @@ Set the ownership of a file or directory with the given path, uid, and gid. Note: This is not available on Windows systems. +### System.rename(String, String) + +Rename the given file. + +```cs +System.rename("old_file", "new_file"); +``` + +### System.chown(String, Number, Number) + +Set the ownership of a file or directory with the given path, uid, and gid. + +Note: This is not available on Windows systems. + ```cs System.chown("/path/to/file", 0, 0); ``` diff --git a/src/optionals/system.c b/src/optionals/system.c index da7ed6e60..68cbdbf93 100644 --- a/src/optionals/system.c +++ b/src/optionals/system.c @@ -490,6 +490,27 @@ static Value chmodNative(DictuVM *vm, int argCount, Value *args) { return newResultSuccess(vm, NIL_VAL); } +static Value renameNative(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "rename() takes 2 arguments (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_STRING(args[0]) || !IS_STRING(args[1])) { + runtimeError(vm, "rename() arguments must be strings."); + return EMPTY_VAL; + } + + char *old = AS_CSTRING(args[0]); + char *new = AS_CSTRING(args[1]); + + if (rename(old, new) != 0) { + return newResultError(vm, "failed to reaneme file"); + } + + return newResultSuccess(vm, NIL_VAL); +} + void initArgv(DictuVM *vm, Table *table, int argc, char **argv) { ObjList *list = newList(vm); push(vm, OBJ_VAL(list)); @@ -590,6 +611,7 @@ Value createSystemModule(DictuVM *vm) { defineNative(vm, &module->values, "sleep", sleepNative); defineNative(vm, &module->values, "exit", exitNative); defineNative(vm, &module->values, "chmod", chmodNative); + defineNative(vm, &module->values, "rename", renameNative); /** * Define System properties diff --git a/tests/system/import.du b/tests/system/import.du index 218f88fb5..e00da45fb 100644 --- a/tests/system/import.du +++ b/tests/system/import.du @@ -16,6 +16,7 @@ import "process.du"; import "mkdir.du"; import "constants.du"; import "chmod.du"; +import "rename.du"; import "chown.du"; import "uname.du"; import "mkdirTemp.du"; diff --git a/tests/system/rename.du b/tests/system/rename.du new file mode 100644 index 000000000..6e6ee24f4 --- /dev/null +++ b/tests/system/rename.du @@ -0,0 +1,28 @@ +/** + * rename.du + * + * Testing the System.rename() function + * + * rename() renames a file from the system + */ +from UnitTest import UnitTest; + +import System; + +class TestSystemRename < UnitTest { + setUp() { + with ("old_file", "w") { + file.write("test"); + } + } + + tearDown() { + System.remove("new_file"); + } + + testSystemRename() { + this.assertTruthy(System.rename("old_file", "new_file").success()); + } +} + +TestSystemRename().run(); From d453c672b10be6a59a2a5e3874387b5adc099226 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Wed, 20 Dec 2023 18:03:09 +0000 Subject: [PATCH 039/148] Update system.md --- docs/docs/standard-lib/system.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index 560e00993..acdaef63a 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -238,7 +238,7 @@ Shell $ echo $?; // 10 ``` -### System.chmod(String, String) +### System.chmod(String, String) -> Result\ Set the permissions on a file or directory. @@ -246,13 +246,13 @@ Set the permissions on a file or directory. System.chmod("/usr/local/share", "755"); ``` -### System.chown(String, Number, Number) +### System.chown(String, Number, Number) -> Result\ Set the ownership of a file or directory with the given path, uid, and gid. Note: This is not available on Windows systems. -### System.rename(String, String) +### System.rename(String, String) -> Result\ Rename the given file. @@ -260,7 +260,7 @@ Rename the given file. System.rename("old_file", "new_file"); ``` -### System.chown(String, Number, Number) +### System.chown(String, Number, Number) -> Result\ Set the ownership of a file or directory with the given path, uid, and gid. From 2d6f9c2566659636d306aca858b63390e31ed249 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Wed, 20 Dec 2023 18:28:15 +0000 Subject: [PATCH 040/148] Update system.c --- src/optionals/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/system.c b/src/optionals/system.c index 68cbdbf93..da8d35fef 100644 --- a/src/optionals/system.c +++ b/src/optionals/system.c @@ -98,7 +98,7 @@ static Value chownNative(DictuVM *vm, int argCount, Value *args) { ERROR_RESULT; } - return newResultSuccess(vm, EMPTY_VAL); + return newResultSuccess(vm, NIL_VAL); } static Value unameNative(DictuVM *vm, int argCount, Value *args) { From e404d03662112854c7f74ca0a22a312238bc0e64 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 21 Dec 2023 11:23:16 +0000 Subject: [PATCH 041/148] Dont free path after first execution --- src/cli/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cli/main.c b/src/cli/main.c index cfb74ab99..857005f22 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -153,9 +153,10 @@ static void repl(DictuVM *vm) { dictuInterpret(vm, "repl", statement); free(line); - free(dictuPath); free(statement); } + + free(dictuPath); } static char *readFile(const char *path) { From 7606e562d7032928d3e86bb19f637398f6872a24 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 1 Jan 2024 16:50:21 -0700 Subject: [PATCH 042/148] add lastIndexOf string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 9 ++++++++ src/vm/datatypes/strings.c | 44 ++++++++++++++++++++++++++++++++++++ tests/strings/import.du | 1 + tests/strings/lastIndexOf.du | 17 ++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 tests/strings/lastIndexOf.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 5dfb75c84..596d9c023 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -199,6 +199,15 @@ Returns true if a string contains another string. To find the index of a given substring, use the `.find()` method. This method takes an optional second parameter which can be used to skip the first `n` number of appearances of the substring. This method returns `-1` if the substring could not be found. Otherwise, it returns the index of the string. +```cs +"woolly woolly mammoth".lastIndexOf("woolly"); // 7 +"mammoth".lastIndexOf("woolly"); // -1 +``` + +### string.lastIndexOf(String) -> Number + +Returns the last index of the given string. If the substring doesn't exist, -1 is returned. + ```cs "Hello, how are you?".find("how"); // 7 "hello something hello".find("hello", 2); // 16 (Skipped first occurrence) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 296084e03..6d3aca745 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -275,6 +275,49 @@ static Value findString(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(position); } +static Value lastIndexOfString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "lastInxedOf() takes 1 argument (%d given)", argCount); + return EMPTY_VAL; + } + + char *str = AS_CSTRING(args[0]); + const char *p = str; + char *ss = AS_CSTRING(args[1]); + int found = !*ss; + + if (!found) { + while (*p) { + ++p; + } + + const char *q = ss; + while (*q) { + ++q; + } + + while (!found && !(p-str < q-ss)) { + const char *s = p; + const char *t = q; + + while (t != ss && *(s-1) == *(t-1)) { + --s; + --t; + } + + found = t == ss; + + if (found) { + p = s; + } else { + --p; + } + } + } + + return NUMBER_VAL(found ? p-str : -1); +} + static Value replaceString(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { runtimeError(vm, "replace() takes 2 arguments (%d given)", argCount); @@ -562,6 +605,7 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "split", splitString); defineNative(vm, &vm->stringMethods, "contains", containsString); defineNative(vm, &vm->stringMethods, "find", findString); + defineNative(vm, &vm->stringMethods, "lastIndexOf", lastIndexOfString); defineNative(vm, &vm->stringMethods, "replace", replaceString); defineNative(vm, &vm->stringMethods, "lower", lowerString); defineNative(vm, &vm->stringMethods, "upper", upperString); diff --git a/tests/strings/import.du b/tests/strings/import.du index 151d47456..fb1a9cfa6 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -12,6 +12,7 @@ import "concat.du"; import "startsWith.du"; import "endsWith.du"; import "find.du"; +import "lastIndexOf.du"; import "contains.du"; import "strip.du"; import "format.du"; diff --git a/tests/strings/lastIndexOf.du b/tests/strings/lastIndexOf.du new file mode 100644 index 000000000..bed5ecf68 --- /dev/null +++ b/tests/strings/lastIndexOf.du @@ -0,0 +1,17 @@ +/** + * lastIndexOf.du + * + * Testing the str.lastIndexOf() method + * + * .lastIndexOf() returns the last index of the given string + */ +from UnitTest import UnitTest; + +class TestStringLastIndexOf < UnitTest { + testStringLower() { + this.assertEquals("woolly woolly mammoth".lastIndexOf("woolly"), 7); + this.assertEquals("mammoth".lastIndexOf("woolly"), -1); + } +} + +TestStringLastIndexOf().run(); \ No newline at end of file From e1ae3bcb328601f84a04ba287b3f7c506987fa1c Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 1 Jan 2024 16:52:33 -0700 Subject: [PATCH 043/148] make vars const Signed-off-by: Brian Downs --- src/vm/datatypes/strings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 6d3aca745..cabbea1c2 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -281,9 +281,9 @@ static Value lastIndexOfString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - char *str = AS_CSTRING(args[0]); + const char *str = AS_CSTRING(args[0]); + const char *ss = AS_CSTRING(args[1]); const char *p = str; - char *ss = AS_CSTRING(args[1]); int found = !*ss; if (!found) { From 956499938f6831f1c425ffb598483ebd995010fc Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 2 Jan 2024 10:29:04 -0700 Subject: [PATCH 044/148] pr remediations Signed-off-by: Brian Downs --- docs/docs/strings.md | 2 +- src/vm/datatypes/strings.c | 4 ++-- tests/strings/{lastIndexOf.du => findLast.du} | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename tests/strings/{lastIndexOf.du => findLast.du} (65%) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 596d9c023..62dfbbf9e 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -204,7 +204,7 @@ To find the index of a given substring, use the `.find()` method. This method ta "mammoth".lastIndexOf("woolly"); // -1 ``` -### string.lastIndexOf(String) -> Number +### string.findLast(String) -> Number Returns the last index of the given string. If the substring doesn't exist, -1 is returned. diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index cabbea1c2..360ae3ea2 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -275,7 +275,7 @@ static Value findString(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(position); } -static Value lastIndexOfString(DictuVM *vm, int argCount, Value *args) { +static Value findLastString(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { runtimeError(vm, "lastInxedOf() takes 1 argument (%d given)", argCount); return EMPTY_VAL; @@ -605,7 +605,7 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "split", splitString); defineNative(vm, &vm->stringMethods, "contains", containsString); defineNative(vm, &vm->stringMethods, "find", findString); - defineNative(vm, &vm->stringMethods, "lastIndexOf", lastIndexOfString); + defineNative(vm, &vm->stringMethods, "findLast", findLastString); defineNative(vm, &vm->stringMethods, "replace", replaceString); defineNative(vm, &vm->stringMethods, "lower", lowerString); defineNative(vm, &vm->stringMethods, "upper", upperString); diff --git a/tests/strings/lastIndexOf.du b/tests/strings/findLast.du similarity index 65% rename from tests/strings/lastIndexOf.du rename to tests/strings/findLast.du index bed5ecf68..56b7a2026 100644 --- a/tests/strings/lastIndexOf.du +++ b/tests/strings/findLast.du @@ -9,8 +9,8 @@ from UnitTest import UnitTest; class TestStringLastIndexOf < UnitTest { testStringLower() { - this.assertEquals("woolly woolly mammoth".lastIndexOf("woolly"), 7); - this.assertEquals("mammoth".lastIndexOf("woolly"), -1); + this.assertEquals("woolly woolly mammoth".findLast("woolly"), 7); + this.assertEquals("mammoth".findLast("woolly"), -1); } } From 7344f187eab808c680c5a902052e24134e2c47ce Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 2 Jan 2024 10:35:27 -0700 Subject: [PATCH 045/148] update tests Signed-off-by: Brian Downs --- tests/strings/import.du | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/strings/import.du b/tests/strings/import.du index fb1a9cfa6..624c70e2a 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -12,7 +12,7 @@ import "concat.du"; import "startsWith.du"; import "endsWith.du"; import "find.du"; -import "lastIndexOf.du"; +import "findLast.du"; import "contains.du"; import "strip.du"; import "format.du"; From eb526edfa0314db471705b5afdc34466988bb98a Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 2 Jan 2024 15:47:11 -0700 Subject: [PATCH 046/148] update function name Signed-off-by: Brian Downs --- docs/docs/strings.md | 4 ++-- tests/strings/findLast.du | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 62dfbbf9e..3b79e1af5 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -200,8 +200,8 @@ Returns true if a string contains another string. To find the index of a given substring, use the `.find()` method. This method takes an optional second parameter which can be used to skip the first `n` number of appearances of the substring. This method returns `-1` if the substring could not be found. Otherwise, it returns the index of the string. ```cs -"woolly woolly mammoth".lastIndexOf("woolly"); // 7 -"mammoth".lastIndexOf("woolly"); // -1 +"woolly woolly mammoth".findLast("woolly"); // 7 +"mammoth".findLast("woolly"); // -1 ``` ### string.findLast(String) -> Number diff --git a/tests/strings/findLast.du b/tests/strings/findLast.du index 56b7a2026..1f7d04ea1 100644 --- a/tests/strings/findLast.du +++ b/tests/strings/findLast.du @@ -1,9 +1,9 @@ /** - * lastIndexOf.du + * findLast.du * - * Testing the str.lastIndexOf() method + * Testing the str.findLast() method * - * .lastIndexOf() returns the last index of the given string + * .findLast() returns the last index of the given string */ from UnitTest import UnitTest; From 256ca6f2834d2fc5b293c319e2f41532996a82b2 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 2 Jan 2024 15:48:59 -0700 Subject: [PATCH 047/148] fix docs mix up Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 3b79e1af5..bc4520af3 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -200,8 +200,9 @@ Returns true if a string contains another string. To find the index of a given substring, use the `.find()` method. This method takes an optional second parameter which can be used to skip the first `n` number of appearances of the substring. This method returns `-1` if the substring could not be found. Otherwise, it returns the index of the string. ```cs -"woolly woolly mammoth".findLast("woolly"); // 7 -"mammoth".findLast("woolly"); // -1 +"Hello, how are you?".find("how"); // 7 +"hello something hello".find("hello", 2); // 16 (Skipped first occurrence) +"House".find("Lost Keys"); // -1 (Not found) ``` ### string.findLast(String) -> Number @@ -209,9 +210,8 @@ To find the index of a given substring, use the `.find()` method. This method ta Returns the last index of the given string. If the substring doesn't exist, -1 is returned. ```cs -"Hello, how are you?".find("how"); // 7 -"hello something hello".find("hello", 2); // 16 (Skipped first occurrence) -"House".find("Lost Keys"); // -1 (Not found) +"woolly woolly mammoth".findLast("woolly"); // 7 +"mammoth".findLast("woolly"); // -1 ``` ### string.leftStrip() -> String From dd93796911d28206ac022ce527ce342bc9071dd0 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Tue, 2 Jan 2024 23:05:50 +0000 Subject: [PATCH 048/148] Update src/vm/datatypes/strings.c --- src/vm/datatypes/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 360ae3ea2..297ca0103 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -277,7 +277,7 @@ static Value findString(DictuVM *vm, int argCount, Value *args) { static Value findLastString(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "lastInxedOf() takes 1 argument (%d given)", argCount); + runtimeError(vm, "findLast() takes 1 argument (%d given)", argCount); return EMPTY_VAL; } From db3e2320e4d7085f0841bc94afaacf08ec6ed435 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 12:43:49 -0700 Subject: [PATCH 049/148] add isUpper string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 ++++++++++ src/vm/datatypes/strings.c | 24 ++++++++++++++++++++++++ tests/strings/isUpper.du | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 tests/strings/isUpper.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index bc4520af3..5b8eebcc9 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -276,4 +276,14 @@ Returns a new string with the original string repeated the given number of times ```cs "ba"+"na".repeat(2); // banana "la".repeat(2) + " land"; // lala land +``` + +### string.isUpper() -> Boolean + +Returns a boolean indicating that the given string is an upper case letter. + +```cs +"D".isUpper(); // true +"d".isUpper() // false +"Dog".isUpper() // false ``` \ No newline at end of file diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 297ca0103..18edf6c0d 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -598,6 +598,29 @@ static Value repeatString(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(takeString(vm, temp, tempLen - 1)); } +static Value isUpperString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "isUpper() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + bool ret = false; + + if (strlen(string) > 1) { + return ret; + } + + char s = string[0]; + + if (s >= 'A' && s <= 'Z') { + ret = true; + } + + return ret; +} + void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "len", lenString); defineNative(vm, &vm->stringMethods, "toNumber", toNumberString); @@ -618,5 +641,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "toBool", boolNative); // Defined in util defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); + defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); } diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du new file mode 100644 index 000000000..74bc673c1 --- /dev/null +++ b/tests/strings/isUpper.du @@ -0,0 +1,18 @@ +/** + * isUpper.du + * + * Testing the str.isUpper() method + * + * .isUpper() returns a boolean indicating that the given string is + * an upper case letter. + */ +from UnitTest import UnitTest; + +class TestStringIsUpper < UnitTest { + testStringIsUpper() { + this.assertTruthy("D".isUpper()); + this.assertFalsey("Maple".isUpper()); + } +} + +TestStringIsUpper().run(); \ No newline at end of file From c08c4a9756aad352fc1bca24662554e37b92749b Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 12:56:24 -0700 Subject: [PATCH 050/148] add toLower string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 ++++++++++ src/vm/datatypes/strings.c | 26 +++++++++++++++++++++++--- tests/strings/import.du | 2 ++ tests/strings/isLower.du | 19 +++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/strings/isLower.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 5b8eebcc9..cddff2ac2 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -286,4 +286,14 @@ Returns a boolean indicating that the given string is an upper case letter. "D".isUpper(); // true "d".isUpper() // false "Dog".isUpper() // false +``` + +### string.isLower() -> Boolean + +Returns a boolean indicating that the given string is an lower case letter. + +```cs +"D".isLower(); // false +"d".isLower() // true +"Dog".isLower() // false ``` \ No newline at end of file diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 18edf6c0d..f24538418 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -612,13 +612,32 @@ static Value isUpperString(DictuVM *vm, int argCount, Value *args) { return ret; } - char s = string[0]; + if (string[0] >= 'A' && string[0] <= 'Z') { + ret = true; + } + + return BOOL_VAL(ret); +} + +static Value isLowerString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "isLower() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + bool ret = false; + + if (strlen(string) > 1) { + return ret; + } - if (s >= 'A' && s <= 'Z') { + if (string[0] >= 'a' && string[0] <= 'z') { ret = true; } - return ret; + return BOOL_VAL(ret); } void declareStringMethods(DictuVM *vm) { @@ -642,5 +661,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); + defineNative(vm, &vm->stringMethods, "isLower", isLowerString); } diff --git a/tests/strings/import.du b/tests/strings/import.du index 624c70e2a..045fc19a8 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -26,3 +26,5 @@ import "toBool.du"; import "escapeCodes.du"; import "repeat.du"; import "title.du"; +import "isUpper.du"; +import "isLower.du"; diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du new file mode 100644 index 000000000..a3dc335a4 --- /dev/null +++ b/tests/strings/isLower.du @@ -0,0 +1,19 @@ +/** + * isLower.du + * + * Testing the str.isLower() method + * + * .isLower() returns a boolean indicating that the given string is + * an lower case letter. + */ +from UnitTest import UnitTest; + +class TestStringIsLower < UnitTest { + testStringIsLower() { + this.assertTruthy("d".isLower()); + this.assertFalsey("D".isLower()); + this.assertFalsey("Maple".isLower()); + } +} + +TestStringIsLower().run(); \ No newline at end of file From 0b96d02baeb91e878b6b7753bdf043a9bf4bf2e6 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 13:00:39 -0700 Subject: [PATCH 051/148] add newline chars Signed-off-by: Brian Downs --- tests/strings/isLower.du | 2 +- tests/strings/isUpper.du | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du index a3dc335a4..d48afe8c4 100644 --- a/tests/strings/isLower.du +++ b/tests/strings/isLower.du @@ -16,4 +16,4 @@ class TestStringIsLower < UnitTest { } } -TestStringIsLower().run(); \ No newline at end of file +TestStringIsLower().run(); diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du index 74bc673c1..ab7c45c21 100644 --- a/tests/strings/isUpper.du +++ b/tests/strings/isUpper.du @@ -15,4 +15,4 @@ class TestStringIsUpper < UnitTest { } } -TestStringIsUpper().run(); \ No newline at end of file +TestStringIsUpper().run(); From 2d751741b6d2ebcbbe530680704a16191b5fd64a Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 7 Jan 2024 18:39:26 -0700 Subject: [PATCH 052/148] added wordCount method Signed-off-by: Brian Downs --- docs/docs/strings.md | 13 ++++++++++++- src/vm/datatypes/strings.c | 27 +++++++++++++++++++++++++++ tests/strings/import.du | 1 + tests/strings/wordCount.du | 19 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/strings/wordCount.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index cddff2ac2..9b4ada2d3 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -296,4 +296,15 @@ Returns a boolean indicating that the given string is an lower case letter. "D".isLower(); // false "d".isLower() // true "Dog".isLower() // false -``` \ No newline at end of file +``` + +### string.wordCount() -> Number + +Returns the number of words in the given string. + +```cs +"".wordCount(); // 0 +"This".wordCount(); // 1 +"This is a sentence".wordCount(); // 4 +"This is an even longer sentence".wordCount(); // 6 +``` diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index f24538418..e3bafaee2 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -545,6 +545,32 @@ static Value countString(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(count); } +static Value wordCountString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "count() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + int count = 0; + int len = strlen(string); + bool in = false; + + for (int i = 0; i < len; i++) { + if (isspace(string[i])) { + in = false; + } else if(isalpha(string[i])) { + if(!in) { + in = true; + count++; + } + } + } + + return NUMBER_VAL(count); +} + static Value titleString(DictuVM *vm, int argCount, Value *args) { if (argCount != 0) { runtimeError(vm, "title() takes no arguments (%d given)", argCount); @@ -657,6 +683,7 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "rightStrip", rightStripString); defineNative(vm, &vm->stringMethods, "strip", stripString); defineNative(vm, &vm->stringMethods, "count", countString); + defineNative(vm, &vm->stringMethods, "wordCount", wordCountString); defineNative(vm, &vm->stringMethods, "toBool", boolNative); // Defined in util defineNative(vm, &vm->stringMethods, "title", titleString); defineNative(vm, &vm->stringMethods, "repeat", repeatString); diff --git a/tests/strings/import.du b/tests/strings/import.du index 045fc19a8..709f74fed 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -28,3 +28,4 @@ import "repeat.du"; import "title.du"; import "isUpper.du"; import "isLower.du"; +import "wordCount.du"; diff --git a/tests/strings/wordCount.du b/tests/strings/wordCount.du new file mode 100644 index 000000000..6f93cfde1 --- /dev/null +++ b/tests/strings/wordCount.du @@ -0,0 +1,19 @@ +/** + * wordCount.du + * + * Testing the str.wordCount() method + * + * .wordCount() returns the number of words in the given string. + */ +from UnitTest import UnitTest; + +class TestStringWordCount < UnitTest { + testStringWordCount() { + this.assertEquals("".wordCount(), 0); + this.assertEquals("This".wordCount(), 1); + this.assertEquals("This is a sentence".wordCount(), 4); + this.assertEquals("This is an even longer sentence".wordCount(), 6); + } +} + +TestStringWordCount().run(); From 56bfce0e5d3fe0806c2019511fe52ebcb7bded18 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 9 Jan 2024 14:19:40 -0700 Subject: [PATCH 053/148] refactor implementations Signed-off-by: Brian Downs --- docs/docs/strings.md | 6 ++++-- src/vm/datatypes/strings.c | 34 ++++++++++++++++++---------------- tests/strings/isLower.du | 2 ++ tests/strings/isUpper.du | 2 ++ 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 9b4ada2d3..8b8e6cf9e 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -285,22 +285,24 @@ Returns a boolean indicating that the given string is an upper case letter. ```cs "D".isUpper(); // true "d".isUpper() // false +"G00D!".isUpper() // true "Dog".isUpper() // false ``` ### string.isLower() -> Boolean -Returns a boolean indicating that the given string is an lower case letter. +Returns a boolean indicating that the given string is an lower case letter. Empty strings are considered false. ```cs "D".isLower(); // false "d".isLower() // true +"g00d!".isLower() // true "Dog".isLower() // false ``` ### string.wordCount() -> Number -Returns the number of words in the given string. +Returns the number of words in the given string. Empty strings are considered false. ```cs "".wordCount(); // 0 diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index e3bafaee2..929acdba6 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -631,18 +631,19 @@ static Value isUpperString(DictuVM *vm, int argCount, Value *args) { } char *string = AS_CSTRING(args[0]); + int len = strlen(string); - bool ret = false; - - if (strlen(string) > 1) { - return ret; + if (len == 0) { + return BOOL_VAL(false); } - if (string[0] >= 'A' && string[0] <= 'Z') { - ret = true; + for (int i = 0; i < len; i++) { + if (!isupper(string[i]) && isalpha(string[i])) { + return BOOL_VAL(false); + } } - - return BOOL_VAL(ret); + + return BOOL_VAL(true); } static Value isLowerString(DictuVM *vm, int argCount, Value *args) { @@ -652,18 +653,19 @@ static Value isLowerString(DictuVM *vm, int argCount, Value *args) { } char *string = AS_CSTRING(args[0]); + int len = strlen(string); - bool ret = false; - - if (strlen(string) > 1) { - return ret; + if (len == 0) { + return BOOL_VAL(false); } - if (string[0] >= 'a' && string[0] <= 'z') { - ret = true; + for (int i = 0; i < len; i++) { + if (!islower(string[i]) && isalpha(string[i])) { + return BOOL_VAL(false); + } } - - return BOOL_VAL(ret); + + return BOOL_VAL(true); } void declareStringMethods(DictuVM *vm) { diff --git a/tests/strings/isLower.du b/tests/strings/isLower.du index d48afe8c4..5b94fd345 100644 --- a/tests/strings/isLower.du +++ b/tests/strings/isLower.du @@ -11,6 +11,8 @@ from UnitTest import UnitTest; class TestStringIsLower < UnitTest { testStringIsLower() { this.assertTruthy("d".isLower()); + this.assertTruthy("dog".isLower()); + this.assertTruthy("g00d!".isLower()); this.assertFalsey("D".isLower()); this.assertFalsey("Maple".isLower()); } diff --git a/tests/strings/isUpper.du b/tests/strings/isUpper.du index ab7c45c21..f7d3294cb 100644 --- a/tests/strings/isUpper.du +++ b/tests/strings/isUpper.du @@ -11,6 +11,8 @@ from UnitTest import UnitTest; class TestStringIsUpper < UnitTest { testStringIsUpper() { this.assertTruthy("D".isUpper()); + this.assertTruthy("DOG".isUpper()); + this.assertTruthy("G00D!".isUpper()); this.assertFalsey("Maple".isUpper()); } } From eeef98c87d26fbd1a68d6b1c78d23437c91f921e Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 16 Jan 2024 19:45:14 +0100 Subject: [PATCH 054/148] fix: correctly return tombstone when theres no free element The dict findDictEntry function did not correctly handle the case when, a dict had no "free" slot but had tombstones, it would loop forever. This fixes that by conditionally returning a tombstone when all other indexes where processed. Fixes: https://github.com/dictu-lang/Dictu/issues/726 --- src/vm/value.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vm/value.c b/src/vm/value.c index 6e86bf1c5..1dafc6e59 100644 --- a/src/vm/value.c +++ b/src/vm/value.c @@ -77,6 +77,7 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, Value key) { uint32_t index = hashValue(key) & capacityMask; DictItem *tombstone = NULL; + uint32_t count = 0; for (;;) { DictItem *entry = &entries[index]; @@ -88,6 +89,8 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, } else { // We found a tombstone. if (tombstone == NULL) tombstone = entry; + if (count >= (uint32_t)capacityMask) + return tombstone; } } else if (valuesEqual(key, entry->key)) { // We found the key. @@ -97,6 +100,7 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, // printf("%d - ", index); index = (index + 1) & capacityMask; // printf("%d - mask: %d\n", index, capacityMask); + count++; } } From db8b8c6919a475f75827149246e34199a81e603c Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 16 Jan 2024 19:50:07 +0100 Subject: [PATCH 055/148] feat: set.values() Adds a method to set to return a list of all values within the set. --- docs/docs/collections/sets.md | 9 +++++++++ src/vm/datatypes/sets.c | 20 ++++++++++++++++++++ tests/sets/values.du | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 tests/sets/values.du diff --git a/docs/docs/collections/sets.md b/docs/docs/collections/sets.md index 46d3967d2..ee593b54a 100644 --- a/docs/docs/collections/sets.md +++ b/docs/docs/collections/sets.md @@ -73,6 +73,15 @@ var mySet = set(); mySet.add("Dictu!"); ``` +### set.values() -> List + +Returns a list of all of the values in the set. + +```cs +var mySet = set("foo", "bar", 123); +const values = mySet.values(); // ["foo", "bar", 123] +``` + ### set.contains(value) -> Boolean To check if a set contains a value use `.contains()` diff --git a/src/vm/datatypes/sets.c b/src/vm/datatypes/sets.c index f898a21f4..c87be14a0 100644 --- a/src/vm/datatypes/sets.c +++ b/src/vm/datatypes/sets.c @@ -14,6 +14,25 @@ static Value toStringSet(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(string); } +static Value valuesSet(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "keys() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + ObjSet *set = AS_SET(args[0]); + ObjList *list = newList(vm); + push(vm, OBJ_VAL(list)); + + for (int i = 0; i <= set->capacityMask; ++i) { + SetItem *item = &set->entries[i]; + if (IS_EMPTY(item->value) || item->deleted) + continue; + writeValueArray(vm, &list->values, item->value); + } + pop(vm); + return OBJ_VAL(list); +} + static Value lenSet(DictuVM *vm, int argCount, Value *args) { if (argCount != 0) { runtimeError(vm, "len() takes no arguments (%d given)", argCount); @@ -96,6 +115,7 @@ static Value containsAllSet(DictuVM *vm, int argCount, Value *args) { void declareSetMethods(DictuVM *vm) { defineNative(vm, &vm->setMethods, "toString", toStringSet); defineNative(vm, &vm->setMethods, "len", lenSet); + defineNative(vm, &vm->setMethods, "values", valuesSet); defineNative(vm, &vm->setMethods, "add", addSetItem); defineNative(vm, &vm->setMethods, "remove", removeSetItem); defineNative(vm, &vm->setMethods, "contains", containsSetItem); diff --git a/tests/sets/values.du b/tests/sets/values.du new file mode 100644 index 000000000..d81f77ee0 --- /dev/null +++ b/tests/sets/values.du @@ -0,0 +1,33 @@ +/** + * values.du + * + * Testing the set.values() method + * + * .values() returns a list of all values in the set + */ +from UnitTest import UnitTest; + +class TestSetValues < UnitTest { + testSetValues() { + const s = set(); + s.add("dictu"); + var values = s.values(); + this.assertEquals(values.len(), 1); + this.assertEquals(values[0] == "dictu", true); + + s.add("!"); + values = s.values(); + this.assertTruthy(values.contains("dictu")); + this.assertTruthy(values.contains("!")); + + + s.add(22); + values = s.values(); + this.assertTruthy(values.contains("dictu")); + this.assertTruthy(values.contains("!")); + this.assertTruthy(values.contains(22)); + + } +} + +TestSetValues().run(); \ No newline at end of file From c702e52f430e3447583dccc66c33c6f9bee71771 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 16 Jan 2024 19:52:57 +0100 Subject: [PATCH 056/148] fix: update error string --- src/vm/datatypes/sets.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/datatypes/sets.c b/src/vm/datatypes/sets.c index c87be14a0..0b3a3f084 100644 --- a/src/vm/datatypes/sets.c +++ b/src/vm/datatypes/sets.c @@ -16,7 +16,7 @@ static Value toStringSet(DictuVM *vm, int argCount, Value *args) { static Value valuesSet(DictuVM *vm, int argCount, Value *args) { if (argCount != 0) { - runtimeError(vm, "keys() takes no arguments (%d given)", argCount); + runtimeError(vm, "values() takes no arguments (%d given)", argCount); return EMPTY_VAL; } ObjSet *set = AS_SET(args[0]); From a1dc4921dad43900bff198986a18b6446144d5ff Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 17 Jan 2024 01:27:40 +0100 Subject: [PATCH 057/148] fix: add file to imports --- tests/sets/import.du | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sets/import.du b/tests/sets/import.du index 523e86d5f..d936e64ed 100644 --- a/tests/sets/import.du +++ b/tests/sets/import.du @@ -14,3 +14,4 @@ import "len.du"; import "toString.du"; import "toBool.du"; import "containsAll.du"; +import "values.du"; \ No newline at end of file From 649f0f7c44303835ce5523c11e3a16c386cdfa40 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Wed, 17 Jan 2024 20:28:13 +0000 Subject: [PATCH 058/148] Update values.du --- tests/sets/values.du | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sets/values.du b/tests/sets/values.du index d81f77ee0..a8e771b71 100644 --- a/tests/sets/values.du +++ b/tests/sets/values.du @@ -13,7 +13,7 @@ class TestSetValues < UnitTest { s.add("dictu"); var values = s.values(); this.assertEquals(values.len(), 1); - this.assertEquals(values[0] == "dictu", true); + this.assertEquals(values[0], "dictu"); s.add("!"); values = s.values(); @@ -30,4 +30,4 @@ class TestSetValues < UnitTest { } } -TestSetValues().run(); \ No newline at end of file +TestSetValues().run(); From 547d2df6f70746f67b2ce613a06d7197d731e325 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Fri, 19 Jan 2024 20:18:33 +0100 Subject: [PATCH 059/148] refactor: change pr to new approach --- src/vm/datatypes/dicts/dicts.c | 2 +- src/vm/object.c | 1 + src/vm/object.h | 1 + src/vm/value.c | 15 +++++++-------- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vm/datatypes/dicts/dicts.c b/src/vm/datatypes/dicts/dicts.c index 9fdc93df7..623c0aea0 100644 --- a/src/vm/datatypes/dicts/dicts.c +++ b/src/vm/datatypes/dicts/dicts.c @@ -31,7 +31,7 @@ static Value lenDict(DictuVM *vm, int argCount, Value *args) { } ObjDict *dict = AS_DICT(args[0]); - return NUMBER_VAL(dict->count); + return NUMBER_VAL(dict->activeCount); } static Value keysDict(DictuVM *vm, int argCount, Value *args) { diff --git a/src/vm/object.c b/src/vm/object.c index ac677abd7..68cda4ce3 100644 --- a/src/vm/object.c +++ b/src/vm/object.c @@ -167,6 +167,7 @@ ObjList *newList(DictuVM *vm) { ObjDict *newDict(DictuVM *vm) { ObjDict *dict = ALLOCATE_OBJ(vm, ObjDict, OBJ_DICT); dict->count = 0; + dict->activeCount = 0; dict->capacityMask = -1; dict->entries = NULL; return dict; diff --git a/src/vm/object.h b/src/vm/object.h index f316747fa..e86ee1372 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -146,6 +146,7 @@ typedef struct { struct sObjDict { Obj obj; int count; + int activeCount; int capacityMask; DictItem *entries; }; diff --git a/src/vm/value.c b/src/vm/value.c index 1dafc6e59..d06e696b1 100644 --- a/src/vm/value.c +++ b/src/vm/value.c @@ -77,7 +77,6 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, Value key) { uint32_t index = hashValue(key) & capacityMask; DictItem *tombstone = NULL; - uint32_t count = 0; for (;;) { DictItem *entry = &entries[index]; @@ -89,8 +88,6 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, } else { // We found a tombstone. if (tombstone == NULL) tombstone = entry; - if (count >= (uint32_t)capacityMask) - return tombstone; } } else if (valuesEqual(key, entry->key)) { // We found the key. @@ -100,7 +97,6 @@ static DictItem *findDictEntry(DictItem *entries, int capacityMask, // printf("%d - ", index); index = (index + 1) & capacityMask; // printf("%d - mask: %d\n", index, capacityMask); - count++; } } @@ -151,7 +147,10 @@ bool dictSet(DictuVM *vm, ObjDict *dict, Value key, Value value) { entry->key = key; entry->value = value; - if (isNewKey) dict->count++; + if (isNewKey) { + dict->activeCount++; + dict->count++; + } return isNewKey; } @@ -163,7 +162,7 @@ bool dictDelete(DictuVM *vm, ObjDict *dict, Value key) { if (IS_EMPTY(entry->key)) return false; // Place a tombstone in the entry. - dict->count--; + dict->activeCount--; entry->key = EMPTY_VAL; entry->value = BOOL_VAL(true); @@ -433,12 +432,12 @@ static bool dictComparison(Value a, Value b) { ObjDict *dictB = AS_DICT(b); // Different lengths, not the same - if (dict->count != dictB->count) + if (dict->activeCount != dictB->activeCount) return false; // Lengths are the same, and dict 1 has 0 length // therefore both are empty - if (dict->count == 0) + if (dict->activeCount == 0) return true; for (int i = 0; i <= dict->capacityMask; ++i) { From dc0f78ab56a72f4d06dd3811dc427bb110e82618 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 20 Jan 2024 03:04:36 +0100 Subject: [PATCH 060/148] feat: add list.sortFunc Adds a function to list implemented in dictu which uses quickSort to allow custom sorting which is suuuper useful for a lot of problems. I would have preferred to implement this is C too but there doesn't seam to be a straight forward way to pass callbacks into c. Using a hybrid approach would have been hacky too, but of course this approach does duplicate the sorting logic. --- docs/docs/collections/lists.md | 14 +++++++++++++ src/vm/datatypes/lists/list-source.h | 30 ++++++++++++++++++++++++++++ src/vm/datatypes/lists/list.du | 30 ++++++++++++++++++++++++++++ tests/lists/import.du | 1 + tests/lists/sortFunc.du | 24 ++++++++++++++++++++++ 5 files changed, 99 insertions(+) create mode 100644 tests/lists/sortFunc.du diff --git a/docs/docs/collections/lists.md b/docs/docs/collections/lists.md index ad58449cc..a385e247e 100644 --- a/docs/docs/collections/lists.md +++ b/docs/docs/collections/lists.md @@ -234,6 +234,20 @@ list1.sort(); print(list1); // [-1, 1, 2, 3, 4, 5, 10] ``` +#### list.sortFunc(Func) + +Sorts a list with a Custom Callback + +```cs +var list1 = [[1, "Dictu"], [-1, "SomeValue"], [5, "!"], [4, "Awesome"], [2, "is"]]; + +print(list1); // [[1, "Dictu"], [-1, "SomeValue"], [5, "!"], [4, "Awesome"], [2, "is"]]; +list1.sortFunc(def(a,b) => a[0] - b[0]); + +print(list1); // [[-1, "SomeValue"], [1, "Dictu"], [2, "is"], [4, "Awesome"], [5, "!"]] + +``` + ```cs var list1 = ["zebra", "cat", "dino", "pig"]; diff --git a/src/vm/datatypes/lists/list-source.h b/src/vm/datatypes/lists/list-source.h index 32a071812..9189d06a7 100644 --- a/src/vm/datatypes/lists/list-source.h +++ b/src/vm/datatypes/lists/list-source.h @@ -14,6 +14,36 @@ " return temp;\n" \ "}\n" \ "\n" \ +"def sortFunc(list, func) {\n" \ +" if(list.len() < 2) {\n" \ +" return;\n" \ +" }\n" \ +" const partition = def (arr, start, end) => {\n" \ +" const pivot = arr[end];\n" \ +" var i = start - 1;\n" \ +" for(var t = start; t <= end-1; t+= 1) {\n" \ +" if(func(pivot, arr[t]) > 0) {\n" \ +" i+= 1;\n" \ +" const temp = arr[i];\n" \ +" arr[i] = arr[t];\n" \ +" arr[t] = temp;\n" \ +" }\n" \ +" }\n" \ +" const temp = arr[i+1];\n" \ +" arr[i+1] = arr[end];\n" \ +" arr[end] = temp;\n" \ +" return i + 1;\n" \ +" };\n" \ +" const quickSort = def(arr, start, end) => {\n" \ +" if(start < end) {\n" \ +" const p = partition(arr, start, end);\n" \ +" quickSort(arr, start, p - 1);\n" \ +" quickSort(arr, p + 1, end);\n" \ +" }\n" \ +" };\n" \ +" quickSort(list, 0, list.len()-1);\n" \ +"}\n" \ +"\n" \ "def filter(list, func=def(x) => x) {\n" \ " const temp = [];\n" \ "\n" \ diff --git a/src/vm/datatypes/lists/list.du b/src/vm/datatypes/lists/list.du index a5e8ec8b3..218bec488 100644 --- a/src/vm/datatypes/lists/list.du +++ b/src/vm/datatypes/lists/list.du @@ -14,6 +14,36 @@ def map(list, func) { return temp; } +def sortFunc(list, func) { + if(list.len() < 2) { + return; + } + const partition = def (arr, start, end) => { + const pivot = arr[end]; + var i = start - 1; + for(var t = start; t <= end-1; t+= 1) { + if(func(pivot, arr[t]) > 0) { + i+= 1; + const temp = arr[i]; + arr[i] = arr[t]; + arr[t] = temp; + } + } + const temp = arr[i+1]; + arr[i+1] = arr[end]; + arr[end] = temp; + return i + 1; + }; + const quickSort = def(arr, start, end) => { + if(start < end) { + const p = partition(arr, start, end); + quickSort(arr, start, p - 1); + quickSort(arr, p + 1, end); + } + }; + quickSort(list, 0, list.len()-1); +} + def filter(list, func=def(x) => x) { const temp = []; diff --git a/tests/lists/import.du b/tests/lists/import.du index bd51de8e6..1640beb6f 100644 --- a/tests/lists/import.du +++ b/tests/lists/import.du @@ -23,6 +23,7 @@ import "remove.du"; import "reverse.du"; import "slicing.du"; import "sort.du"; +import "sortFunc.du"; import "splice.du"; import "subscript.du"; import "toBool.du"; diff --git a/tests/lists/sortFunc.du b/tests/lists/sortFunc.du new file mode 100644 index 000000000..d05d381c3 --- /dev/null +++ b/tests/lists/sortFunc.du @@ -0,0 +1,24 @@ +/** + * sortFunc.du + * + * Testing list sorting with custom callback + */ +from UnitTest import UnitTest; +class A { + init(var name, var n) {} +} + +class TestListSortFunc < UnitTest { + testListSortCallback() { + var list1 = [[1, "Dictu"], [-1, "SomeValue"], [5, "!"], [4, "Awesome"], [2, "is"]]; + list1.sortFunc(def(a,b) => a[0] - b[0]); + this.assertEquals(list1, [[-1, "SomeValue"], [1, "Dictu"], [2, "is"], [4, "Awesome"], [5, "!"]]); + } + testListSortCallbackClass() { + var list = [A("T", 10), A("U", 15), A("C", 5), A("D", 1), A("I", 3)]; + list.sortFunc(def(a,b) => a.n - b.n); + this.assertEquals(list.map(def (entry) => entry.n), [1, 3, 5, 10, 15]); + this.assertEquals(list.map(def (entry) => entry.name), ["D", "I", "C", "T", "U"]); + } +} +TestListSortFunc().run(); \ No newline at end of file From 85e6da0ebde6ec40e7d894a845bf855a3035c1aa Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 20 Jan 2024 23:12:58 +0100 Subject: [PATCH 061/148] ffi: wip --- src/optionals/ffi/ffi.c | 138 ++++++++++++++++++++++++++++++++++++++ src/optionals/ffi/ffi.h | 12 ++++ src/optionals/optionals.c | 2 + src/optionals/optionals.h | 1 + 4 files changed, 153 insertions(+) create mode 100644 src/optionals/ffi/ffi.c create mode 100644 src/optionals/ffi/ffi.h diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c new file mode 100644 index 000000000..2debfeb3e --- /dev/null +++ b/src/optionals/ffi/ffi.c @@ -0,0 +1,138 @@ +#include "ffi.h" +#include + + +typedef struct { + void* library; + char* path; + int size; + char** names; +} FFIInstance; + +typedef struct _vm_external vm_external; + +typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); + +#define AS_FFI_INSTANCE(v) ((FFIInstance*)AS_ABSTRACT(v)->data) + + +void freeFFI(DictuVM *vm, ObjAbstract *abstract) { + FFIInstance *instance = (FFIInstance*)abstract->data; + free(instance->path); + if(instance->size > 0){ + for(int i = 0; i < instance->size; i++){ + if(instance->names[i] != NULL) + free(instance->names[i]); + } + free(instance->names); + } + dlclose(instance->library); + FREE(vm, FFIInstance, abstract->data); +} + +char *ffiToString(ObjAbstract *abstract) { + UNUSED(abstract); + + char *ffiString = malloc(sizeof(char) * 11+3); + snprintf(ffiString, 11+3, ""); + return ffiString; +} + +void grayFFI(DictuVM *vm, ObjAbstract *abstract) { + (void)vm; + FFIInstance *ffi = (FFIInstance*)abstract->data; + + if (ffi == NULL) return; + +} +static Value ffiInstanceInvoke(DictuVM *vm, int argCount, Value *args) { + if(argCount < 1){ + runtimeError(vm, "invoke() takes at least one argument (%d given)", argCount-1); + return EMPTY_VAL; + } + FFIInstance* instance = AS_FFI_INSTANCE(args[0]); + ObjString* symbol = AS_STRING(args[1]); + bool found = false; + for(int i = 0; i < instance->size; i++) { + if(instance->names[i]) { + if(strcmp(instance->names[i], symbol->chars) == 0){ + found = true; + break; + } + } + } + if(!found){ + runtimeError(vm, "symbol not found: %s", symbol->chars); + return EMPTY_VAL; + } + function_definition_t* ptr = dlsym(instance->library, symbol->chars); + Value res = EMPTY_VAL; + if(argCount == 1) + res = ptr(vm, 0, NULL); + else + res = ptr(vm, argCount-1, args+2); + return res; +} + +static Value load(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "load() takes 2 arguments (%d given)", argCount); + return EMPTY_VAL; + } + ObjString* path = AS_STRING(args[0]); + void *library = dlopen(path->chars, RTLD_LAZY); + if(!library) { + runtimeError(vm, "Couldn't load shared object: %s", path->chars); + return EMPTY_VAL; + } + ObjList* symbols = AS_LIST(args[1]); + ObjAbstract *abstract = newAbstract(vm, freeFFI, ffiToString); + push(vm, OBJ_VAL(abstract)); + FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); + instance->path = malloc(path->length+1); + instance->path[path->length] = '\0'; + memcpy(instance->path, path->chars, path->length); + + instance->library = library; + instance->size = symbols->values.count; + if(instance->size > 0) { + instance->names = malloc(sizeof(char*) * instance->size); + for(int i = 0; i< symbols->values.count; i+= 1){ + Value v = symbols->values.values[i]; + if(!IS_STRING(v)) { + instance->names[i] = NULL; + } else { + ObjString* sym = AS_STRING(v); + if(dlsym(instance->library, sym->chars) == NULL){ + runtimeError(vm, "Couldn't load symbol: %s", sym->chars); + return EMPTY_VAL; + } + instance->names[i] = malloc(sym->length+1); + instance->names[i][sym->length] = '\0'; + memcpy(instance->names[i], sym->chars, sym->length); + } + } + } else { + instance->names = NULL; + } + + defineNative(vm, &abstract->values, "invoke", ffiInstanceInvoke); + + abstract->data = instance; + abstract->grayFunc = grayFFI; + pop(vm); + + return OBJ_VAL(abstract); +} + +Value createFFIModule(DictuVM *vm) { + ObjString *name = copyString(vm, "FFI", 3); + push(vm, OBJ_VAL(name)); + ObjModule *module = newModule(vm, name); + push(vm, OBJ_VAL(module)); + defineNative(vm, &module->values, "load", load); + pop(vm); + pop(vm); + + return OBJ_VAL(module); +} \ No newline at end of file diff --git a/src/optionals/ffi/ffi.h b/src/optionals/ffi/ffi.h new file mode 100644 index 000000000..a615abeb7 --- /dev/null +++ b/src/optionals/ffi/ffi.h @@ -0,0 +1,12 @@ +#ifndef dictu_ffi_module_h +#define dictu_ffi_module_h + +#include + +#include "../optionals.h" +#include "../../vm/vm.h" + + +Value createFFIModule(DictuVM *vm); + +#endif //dictu_ffi_module_h diff --git a/src/optionals/optionals.c b/src/optionals/optionals.c index d76a5e3ab..95ad538d6 100644 --- a/src/optionals/optionals.c +++ b/src/optionals/optionals.c @@ -1,4 +1,5 @@ #include "optionals.h" +#include "ffi/ffi.h" BuiltinModules modules[] = { {"Argparse", &createArgParseModule, false}, @@ -30,6 +31,7 @@ BuiltinModules modules[] = { {"HTTP", &createHTTPModule, true}, #endif {"BigInt", &createBigIntModule, false}, + {"FFI", &createFFIModule, false}, {NULL, NULL, false} }; diff --git a/src/optionals/optionals.h b/src/optionals/optionals.h index f39f11c04..74afcf3ef 100644 --- a/src/optionals/optionals.h +++ b/src/optionals/optionals.h @@ -28,6 +28,7 @@ #include "bigint.h" #include "object/object.h" #include "unittest/unittest.h" +#include "ffi/ffi.h" typedef Value (*BuiltinModule)(DictuVM *vm); From fe760783e1db6a9f6d79064fa5a338b0cbc5ba3d Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sun, 21 Jan 2024 03:28:47 +0100 Subject: [PATCH 062/148] feat: add suffix property --- src/optionals/ffi/ffi.c | 3 +++ src/optionals/ffi/ffi.h | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 2debfeb3e..62683afda 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -131,6 +131,9 @@ Value createFFIModule(DictuVM *vm) { ObjModule *module = newModule(vm, name); push(vm, OBJ_VAL(module)); defineNative(vm, &module->values, "load", load); + + defineNativeProperty(vm, &module->values, "suffix", OBJ_VAL( + copyString(vm, LIB_EXTENSION, LIB_EXTENSION_STRLEN))); pop(vm); pop(vm); diff --git a/src/optionals/ffi/ffi.h b/src/optionals/ffi/ffi.h index a615abeb7..ba0824cde 100644 --- a/src/optionals/ffi/ffi.h +++ b/src/optionals/ffi/ffi.h @@ -6,6 +6,17 @@ #include "../optionals.h" #include "../../vm/vm.h" +#ifdef _WIN32 +#define LIB_EXTENSION ".dll" +#define LIB_EXTENSION_STRLEN 4 +#elif __APPLE__ +#define LIB_EXTENSION ".dylib" +#define LIB_EXTENSION_STRLEN 6 +#else +#define LIB_EXTENSION ".so" +#define LIB_EXTENSION_STRLEN 3 +#endif + Value createFFIModule(DictuVM *vm); From aa7b9cefaa14ffb68cb48e1236e5a7e950214a6c Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 13 Jan 2024 19:08:16 -0700 Subject: [PATCH 063/148] add collapseSpaces method to string type Signed-off-by: Brian Downs --- docs/docs/strings.md | 8 ++++++++ src/vm/datatypes/strings.c | 20 ++++++++++++++++++++ tests/strings/collapseSpaces.du | 19 +++++++++++++++++++ tests/strings/concat.du | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/strings/collapseSpaces.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 8b8e6cf9e..ba8d4c3f8 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -310,3 +310,11 @@ Returns the number of words in the given string. Empty strings are considered fa "This is a sentence".wordCount(); // 4 "This is an even longer sentence".wordCount(); // 6 ``` + +### string.collapseSpaces() -> Number + +Returns a string with extraneous whitespace removed. + +```cs +"This is a huge string of a lot of spaces.".collapseSpaces(); // "This is a huge string of a lot of spaces." +``` diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 929acdba6..c730a7007 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -668,6 +668,25 @@ static Value isLowerString(DictuVM *vm, int argCount, Value *args) { return BOOL_VAL(true); } +static Value collapseSpacesString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "collapseSpaces() takes no arguments (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + + int i, j; + for (i = j = 0; string[i]; ++i) { + if(!isspace(string[i]) || (i > 0 && !isspace(string[i-1]))) { + string[j++] = string[i]; + } + } + string[j+1] = '\0'; + + return OBJ_VAL(copyString(vm, string, strlen(string) - 1)); +} + void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "len", lenString); defineNative(vm, &vm->stringMethods, "toNumber", toNumberString); @@ -691,5 +710,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "repeat", repeatString); defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); defineNative(vm, &vm->stringMethods, "isLower", isLowerString); + defineNative(vm, &vm->stringMethods, "collapseSpaces", collapseSpacesString); } diff --git a/tests/strings/collapseSpaces.du b/tests/strings/collapseSpaces.du new file mode 100644 index 000000000..d3e2893a8 --- /dev/null +++ b/tests/strings/collapseSpaces.du @@ -0,0 +1,19 @@ +/** + * collapseSpaces.du + * + * Testing the str.collapseSpaces() method + * + * .collapseSpaces() returns a string with extraneous spaces removed. + */ +from UnitTest import UnitTest; + +class TestStringCollapseSpaces < UnitTest { + testStringCollapseSpaces() { + const testString = "This is a huge string of a lot of spaces."; + const expected = "This is a huge string of a lot of spaces."; + const res = testString.collapseSpaces(); + this.assertEquals(res, expected); + } +} + +TestStringCollapseSpaces().run(); \ No newline at end of file diff --git a/tests/strings/concat.du b/tests/strings/concat.du index c25a5f765..9518698ca 100644 --- a/tests/strings/concat.du +++ b/tests/strings/concat.du @@ -17,4 +17,4 @@ class TestStringConcat < UnitTest { } } -TestStringConcat().run(); \ No newline at end of file +TestStringConcat().run(); From 2e2b6aaaa8a1a3ca1ef136bd1a3029301ac49bc4 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 13 Jan 2024 20:23:06 -0700 Subject: [PATCH 064/148] add wrap string method Signed-off-by: Brian Downs --- docs/docs/strings.md | 10 +++++++++- src/vm/datatypes/strings.c | 27 +++++++++++++++++++++++++++ tests/strings/import.du | 2 ++ tests/strings/wrap.du | 21 +++++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/strings/wrap.du diff --git a/docs/docs/strings.md b/docs/docs/strings.md index ba8d4c3f8..159915724 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -311,10 +311,18 @@ Returns the number of words in the given string. Empty strings are considered fa "This is an even longer sentence".wordCount(); // 6 ``` -### string.collapseSpaces() -> Number +### string.collapseSpaces() -> String Returns a string with extraneous whitespace removed. ```cs "This is a huge string of a lot of spaces.".collapseSpaces(); // "This is a huge string of a lot of spaces." ``` + +### string.wrap() -> String + +Returns a new string with new lines inserted at the given length. + +```cs +"This is a really really long string that will need to be broken up for whatever reason the caller has determined. Not out business as to why, but we can provide the functionality for them to do so.".wrap(80); +``` diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index c730a7007..7c7f17f4d 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -687,6 +687,32 @@ static Value collapseSpacesString(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(copyString(vm, string, strlen(string) - 1)); } +static Value wrapString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "wrap() takes 1 argument (%d given)", argCount); + return EMPTY_VAL; + } + + char *string = AS_CSTRING(args[0]); + int len = AS_NUMBER(args[1]); + + int last_space = 0; + int counter = 0; + + for (int current = 0; string[current] != '\0'; current++, counter++) { + if (isspace(string[current])) { + last_space = current; + } + + if (counter >= len) { + string[last_space] = '\n'; + counter = 0; + } + } + + return OBJ_VAL(copyString(vm, string, strlen(string) - 1)); +} + void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "len", lenString); defineNative(vm, &vm->stringMethods, "toNumber", toNumberString); @@ -711,5 +737,6 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "isUpper", isUpperString); defineNative(vm, &vm->stringMethods, "isLower", isLowerString); defineNative(vm, &vm->stringMethods, "collapseSpaces", collapseSpacesString); + defineNative(vm, &vm->stringMethods, "wrap", wrapString); } diff --git a/tests/strings/import.du b/tests/strings/import.du index 709f74fed..766fc8ecd 100644 --- a/tests/strings/import.du +++ b/tests/strings/import.du @@ -29,3 +29,5 @@ import "title.du"; import "isUpper.du"; import "isLower.du"; import "wordCount.du"; +import "collapseSpaces.du"; +import "wrap.du"; diff --git a/tests/strings/wrap.du b/tests/strings/wrap.du new file mode 100644 index 000000000..442b04652 --- /dev/null +++ b/tests/strings/wrap.du @@ -0,0 +1,21 @@ +/** + * wrap.du + * + * Testing the str.wrap() method + * + * .wrap() returns a new string with new lines inserted at the given length. + */ +from UnitTest import UnitTest; + +class TestStringWrap < UnitTest { + const maxLen = 80; + + testStringWrap() { + const testString = "This is a really really long string that will need to be broken up for whatever reason the caller has determined. Not out business as to why, but we can provide the functionality for them to do so."; + const res = testString.wrap(this.maxLen); + const idx = res.find("\n"); + this.assertTruthy(res.find("\n") <= this.maxLen); + } +} + +TestStringWrap().run(); From e3b29bd39f4ccc87a27d4c1f2476f09a1b087282 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 13 Jan 2024 20:46:37 -0700 Subject: [PATCH 065/148] newlines Signed-off-by: Brian Downs --- src/vm/datatypes/sets.c | 1 - src/vm/datatypes/strings.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/vm/datatypes/sets.c b/src/vm/datatypes/sets.c index 0b3a3f084..f8907688c 100644 --- a/src/vm/datatypes/sets.c +++ b/src/vm/datatypes/sets.c @@ -122,4 +122,3 @@ void declareSetMethods(DictuVM *vm) { defineNative(vm, &vm->setMethods, "containsAll", containsAllSet); defineNative(vm, &vm->setMethods, "toBool", boolNative); // Defined in util } - diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 7c7f17f4d..d656505d7 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -738,5 +738,4 @@ void declareStringMethods(DictuVM *vm) { defineNative(vm, &vm->stringMethods, "isLower", isLowerString); defineNative(vm, &vm->stringMethods, "collapseSpaces", collapseSpacesString); defineNative(vm, &vm->stringMethods, "wrap", wrapString); - } From b08a365c343374a3b170d50a0191074dfbca77c1 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 13 Jan 2024 20:50:36 -0700 Subject: [PATCH 066/148] update code style Signed-off-by: Brian Downs --- src/vm/datatypes/strings.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index d656505d7..555192494 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -696,17 +696,17 @@ static Value wrapString(DictuVM *vm, int argCount, Value *args) { char *string = AS_CSTRING(args[0]); int len = AS_NUMBER(args[1]); - int last_space = 0; - int counter = 0; + int last = 0; + int count = 0; - for (int current = 0; string[current] != '\0'; current++, counter++) { - if (isspace(string[current])) { - last_space = current; + for (int cur = 0; string[cur] != '\0'; cur++, count++) { + if (isspace(string[cur])) { + last = cur; } - if (counter >= len) { - string[last_space] = '\n'; - counter = 0; + if (count >= len) { + string[last] = '\n'; + count = 0; } } From 809b187dc7be064aeb06dd888a03fdaf1bfc8ce4 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 13 Jan 2024 20:58:27 -0700 Subject: [PATCH 067/148] add new line Signed-off-by: Brian Downs --- tests/strings/collapseSpaces.du | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/strings/collapseSpaces.du b/tests/strings/collapseSpaces.du index d3e2893a8..c448c4441 100644 --- a/tests/strings/collapseSpaces.du +++ b/tests/strings/collapseSpaces.du @@ -16,4 +16,4 @@ class TestStringCollapseSpaces < UnitTest { } } -TestStringCollapseSpaces().run(); \ No newline at end of file +TestStringCollapseSpaces().run(); From 76d28e93c7420f95c10de76bf87c82a106cd6be4 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 20 Jan 2024 20:15:04 -0700 Subject: [PATCH 068/148] redo implementations Signed-off-by: Brian Downs --- src/vm/datatypes/strings.c | 31 +++++++++++++++++++------------ tests/strings/collapseSpaces.du | 1 + 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 555192494..0202ec04f 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -674,17 +674,20 @@ static Value collapseSpacesString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - char *string = AS_CSTRING(args[0]); + ObjString *string = AS_STRING(args[0]); + char *temp = ALLOCATE(vm, char, string->length + 1); + strcpy(temp, string->chars); int i, j; - for (i = j = 0; string[i]; ++i) { - if(!isspace(string[i]) || (i > 0 && !isspace(string[i-1]))) { - string[j++] = string[i]; + for (i = j = 0; temp[i]; ++i) { + if(!isspace(temp[i]) || (i > 0 && !isspace(temp[i-1]))) { + temp[j++] = temp[i]; } } - string[j+1] = '\0'; + temp[j+1] = '\0'; + temp = SHRINK_ARRAY(vm, temp, char, string->length + 1, strlen(temp)); - return OBJ_VAL(copyString(vm, string, strlen(string) - 1)); + return OBJ_VAL(takeString(vm, temp, strlen(temp)-1)); } static Value wrapString(DictuVM *vm, int argCount, Value *args) { @@ -693,24 +696,28 @@ static Value wrapString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - char *string = AS_CSTRING(args[0]); + ObjString *string = AS_STRING(args[0]); + char *temp = ALLOCATE(vm, char, string->length + 1); + int len = AS_NUMBER(args[1]); int last = 0; int count = 0; - for (int cur = 0; string[cur] != '\0'; cur++, count++) { - if (isspace(string[cur])) { + for (int cur = 0; string->chars[cur] != '\0'; cur++, count++) { + temp[cur] = string->chars[cur]; + + if (isspace(temp[cur])) { last = cur; - } + } if (count >= len) { - string[last] = '\n'; + temp[last] = '\n'; count = 0; } } - return OBJ_VAL(copyString(vm, string, strlen(string) - 1)); + return OBJ_VAL(takeString(vm, temp, strlen(temp))); } void declareStringMethods(DictuVM *vm) { diff --git a/tests/strings/collapseSpaces.du b/tests/strings/collapseSpaces.du index c448c4441..1ef92a439 100644 --- a/tests/strings/collapseSpaces.du +++ b/tests/strings/collapseSpaces.du @@ -12,6 +12,7 @@ class TestStringCollapseSpaces < UnitTest { const testString = "This is a huge string of a lot of spaces."; const expected = "This is a huge string of a lot of spaces."; const res = testString.collapseSpaces(); + print(res); this.assertEquals(res, expected); } } From 5181778da40c23a7fe85311ffb232c19721b0746 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sat, 20 Jan 2024 20:17:04 -0700 Subject: [PATCH 069/148] update docs Signed-off-by: Brian Downs --- docs/docs/strings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 159915724..8a3f6ebaf 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -319,7 +319,7 @@ Returns a string with extraneous whitespace removed. "This is a huge string of a lot of spaces.".collapseSpaces(); // "This is a huge string of a lot of spaces." ``` -### string.wrap() -> String +### string.wrap(Number) -> String Returns a new string with new lines inserted at the given length. From 818f19c729f79717044f8134a4e8cbcc0524c5f0 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 21 Jan 2024 19:25:38 -0700 Subject: [PATCH 070/148] add addtional test Signed-off-by: Brian Downs --- tests/strings/collapseSpaces.du | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/strings/collapseSpaces.du b/tests/strings/collapseSpaces.du index 1ef92a439..d885ee3ff 100644 --- a/tests/strings/collapseSpaces.du +++ b/tests/strings/collapseSpaces.du @@ -12,8 +12,8 @@ class TestStringCollapseSpaces < UnitTest { const testString = "This is a huge string of a lot of spaces."; const expected = "This is a huge string of a lot of spaces."; const res = testString.collapseSpaces(); - print(res); this.assertEquals(res, expected); + this.assertNotEquals(testString, expected); } } From c01149d0b99c14d0460efd140824bcbf7960f11c Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 21 Jan 2024 20:22:13 -0700 Subject: [PATCH 071/148] update docs Signed-off-by: Brian Downs --- docs/docs/strings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/strings.md b/docs/docs/strings.md index 8a3f6ebaf..bc946f67e 100644 --- a/docs/docs/strings.md +++ b/docs/docs/strings.md @@ -324,5 +324,5 @@ Returns a string with extraneous whitespace removed. Returns a new string with new lines inserted at the given length. ```cs -"This is a really really long string that will need to be broken up for whatever reason the caller has determined. Not out business as to why, but we can provide the functionality for them to do so.".wrap(80); +"This is a really really long string that will need to be broken up for whatever reason the caller has determined. Not our business as to why, but we can provide the functionality for them to do so.".wrap(80); ``` From 47fa9a95091f413a6ee74c3715f6770962fff27d Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Mon, 22 Jan 2024 17:49:26 +0000 Subject: [PATCH 072/148] Reuse length variable and only resize if we need to --- src/vm/datatypes/strings.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 0202ec04f..32860c813 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -680,14 +680,18 @@ static Value collapseSpacesString(DictuVM *vm, int argCount, Value *args) { int i, j; for (i = j = 0; temp[i]; ++i) { - if(!isspace(temp[i]) || (i > 0 && !isspace(temp[i-1]))) { + if (!isspace(temp[i]) || (i > 0 && !isspace(temp[i-1]))) { temp[j++] = temp[i]; } } + temp[j+1] = '\0'; - temp = SHRINK_ARRAY(vm, temp, char, string->length + 1, strlen(temp)); - return OBJ_VAL(takeString(vm, temp, strlen(temp)-1)); + if (i != j) { + temp = SHRINK_ARRAY(vm, temp, char, string->length + 1, j); + } + + return OBJ_VAL(takeString(vm, temp, j)); } static Value wrapString(DictuVM *vm, int argCount, Value *args) { From 7f997ccda24bac3f9d6c963d293aa641e2fd7e77 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Mon, 22 Jan 2024 17:55:56 +0000 Subject: [PATCH 073/148] Correct memory tracking --- src/vm/datatypes/strings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/datatypes/strings.c b/src/vm/datatypes/strings.c index 32860c813..e58ca3e6d 100644 --- a/src/vm/datatypes/strings.c +++ b/src/vm/datatypes/strings.c @@ -688,7 +688,7 @@ static Value collapseSpacesString(DictuVM *vm, int argCount, Value *args) { temp[j+1] = '\0'; if (i != j) { - temp = SHRINK_ARRAY(vm, temp, char, string->length + 1, j); + temp = SHRINK_ARRAY(vm, temp, char, string->length + 1, j + 1); } return OBJ_VAL(takeString(vm, temp, j)); From 0d3327d3947def6a8a02e0dfff817a41ca7d75be Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 22 Jan 2024 22:28:30 +0100 Subject: [PATCH 074/148] chore: update docs regarding sortFunc --- docs/docs/collections/lists.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/collections/lists.md b/docs/docs/collections/lists.md index a385e247e..7ae4f18d7 100644 --- a/docs/docs/collections/lists.md +++ b/docs/docs/collections/lists.md @@ -236,7 +236,8 @@ print(list1); // [-1, 1, 2, 3, 4, 5, 10] #### list.sortFunc(Func) -Sorts a list with a Custom Callback +Sorts a list with a Custom Callback, The callback function passed to `.sortFunc` takes two elements of the list `a` and `b`. +The return value should be a number whose sign indicates the relative order of the two elements: negative if `a` is less than `b`, positive if `a` is greater than `b`, and zero if they are equal. ```cs var list1 = [[1, "Dictu"], [-1, "SomeValue"], [5, "!"], [4, "Awesome"], [2, "is"]]; From ffc4bb817fbc598ce2f779d31cdf34d4bda188f1 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 02:38:36 +0100 Subject: [PATCH 075/148] Wip: buffer api --- src/optionals/buffer.c | 705 ++++++++++++++++++++++++++++++++++++++ src/optionals/buffer.h | 12 + src/optionals/optionals.c | 1 + src/optionals/optionals.h | 1 + 4 files changed, 719 insertions(+) create mode 100644 src/optionals/buffer.c create mode 100644 src/optionals/buffer.h diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c new file mode 100644 index 000000000..83f5bed2c --- /dev/null +++ b/src/optionals/buffer.c @@ -0,0 +1,705 @@ +#include "buffer.h" +#include + +typedef struct { + uint8_t *bytes; + int size; +} Buffer; + +#define AS_BUFFER(v) ((Buffer *)AS_ABSTRACT(v)->data) + +ObjAbstract *newBufferObj(DictuVM *vm, double capacity); + +void freeBuffer(DictuVM *vm, ObjAbstract *abstract) { + Buffer *buffer = (Buffer *)abstract->data; + free(buffer->bytes); + FREE(vm, Buffer, abstract->data); +} + +char *bufferToString(ObjAbstract *abstract) { +UNUSED(abstract); + + char *queueString = malloc(sizeof(char) * 9); + snprintf(queueString, 9, ""); + return queueString; +} + +void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { + (void)vm; + Buffer *ffi = (Buffer *)abstract->data; + + if (ffi == NULL) + return; +} + +bool ensureSize(Buffer* buffer, size_t offset, size_t size){ + return buffer->size - offset >= size; +} + +static Value bufferResize(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "resize() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "resize() argument must be a numbers"); + return EMPTY_VAL; + } + + double capacity = AS_NUMBER(args[1]); + if (capacity <= 0) { + return newResultError(vm, "capacity must be greater than 0"); + } + Buffer *buffer = AS_BUFFER(args[0]); + buffer->bytes = realloc(buffer->bytes, capacity); + if (capacity > buffer->size) { + size_t added = capacity - buffer->size; + memset(buffer->bytes + added, 0, added); + } + buffer->size = capacity; + return newResultSuccess(vm, args[0]); +} + +static Value bufferLen(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "len() takes no arguments"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + return NUMBER_VAL(buffer->size); +} + +static Value bufferString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "string() takes no arguments"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + return OBJ_VAL(copyString(vm, (const char*)buffer->bytes, buffer->size)); +} + +static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeUint16LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeUint16LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeUint16LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + uint16_t correctVal = (uint16_t)value; + + if(!ensureSize(buffer, index, sizeof(uint16_t))){ + return newResultError(vm, "index must be smaller then buffer size -2"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint16_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeUint32LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeUint32LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeUint32LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + uint32_t correctVal = (uint32_t)value; + + if(!ensureSize(buffer, index, sizeof(uint32_t))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint32_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeUint64LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeUint64LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeUint64LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + uint64_t correctVal = (uint64_t)value; + + if(!ensureSize(buffer, index, sizeof(uint64_t))){ + return newResultError(vm, "index must be smaller then buffer size - 8"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint64_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeint64LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeint64LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeint64LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + int64_t correctVal = (int64_t)value; + + if(!ensureSize(buffer, index, sizeof(int64_t))){ + return newResultError(vm, "index must be smaller then buffer size - 8"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int64_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeint32LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeint32LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeint32LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + int32_t correctVal = (int32_t)value; + + if(!ensureSize(buffer, index, sizeof(int32_t))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int32_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeint16LE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeint16LE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeint16LE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + int16_t correctVal = (int16_t)value; + + if(!ensureSize(buffer, index, sizeof(int16_t))){ + return newResultError(vm, "index must be smaller then buffer size - 2"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int16_t)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeFloatLE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeFloatLE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeFloatLE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + float correctVal = (float)value; + + if(!ensureSize(buffer, index, sizeof(float))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(float)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeDoubleLE() takes 2 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeDoubleLE() index argument must be a numbers"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeDoubleLE() value argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + + double correctVal = value; + + if(!ensureSize(buffer, index, sizeof(double))){ + return newResultError(vm, "index must be smaller then buffer size - 8"); + } + uint8_t* ptr = (uint8_t*)&correctVal; + memcpy(buffer->bytes+(size_t)index, ptr, sizeof(double)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readDoubleLE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readDoubleLE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 8"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readFloatLE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readFloatLE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + float value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readUint64LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readUint64LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + uint64_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 8"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readUint32LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readUint32LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + uint32_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readUint16LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readUint16LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + uint16_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readint64LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readint64LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + int64_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readint32LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readint32LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + int32_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + +static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "readint32LE() takes 1 argument"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readint32LE() index argument must be a numbers"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + int16_t value; + if(!ensureSize(buffer, index, sizeof(value))){ + return newResultError(vm, "index must be smaller then buffer size - 4"); + } + memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + + +static Value bufferGet(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "get() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "get() argument must be a numbers"); + return EMPTY_VAL; + } + + double index = AS_NUMBER(args[1]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } + + return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); +} + +static Value bufferSet(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "set() takes 2 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "set() index argument must be a numbers"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "set() value argument must be a numbers"); + return EMPTY_VAL; + } + + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } + + buffer->bytes[(size_t)index] = (uint8_t)value; + + return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); +} + +static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 2) { + runtimeError(vm, "writeString() takes 2 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeString() index argument must be a numbers"); + return EMPTY_VAL; + } + + if (!IS_STRING(args[2])) { + runtimeError(vm, "writeString() value argument must be a string"); + return EMPTY_VAL; + } + + double index = AS_NUMBER(args[1]); + ObjString* str = AS_STRING(args[2]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } + + if(buffer->size - index < str->length) { + return newResultError(vm, "buffer is not large enough to fit the string"); + } + memcpy(buffer->bytes+(size_t)index, str->chars, str->length); + return newResultSuccess(vm, NIL_VAL); +} + +static Value bufferSubAarray(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); + size_t start = 0; + size_t end = buffer->size; + int length = buffer->size; + if (argCount > 0) { + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "subarray() start argument must be a number"); + return EMPTY_VAL; + } + double startParam = AS_NUMBER(args[1]); + if (startParam >= buffer->size) { + return newResultError(vm, "start greater or equals then buffer length"); + } else { + start = startParam; + length = end - start; + } + } + if (argCount == 2) { + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "subarray() end argument must be a number"); + return EMPTY_VAL; + } + double endParam = AS_NUMBER(args[2]); + if(endParam > buffer->size){ + return newResultError(vm, "end greater then buffer length"); + } else { + end = endParam; + length = end - start; + } + } + if(length <= 0){ + return newResultError(vm, "length is 0"); + } + ObjAbstract* newBuffer = newBufferObj(vm, length); + Buffer* nb = (Buffer *)newBuffer->data; + for(int i = 0; i < length; i++){ + nb->bytes[i] = buffer->bytes[start + i]; + } + return newResultSuccess(vm, OBJ_VAL(newBuffer)); +} + +ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { + ObjAbstract *abstract = newAbstract(vm, freeBuffer, bufferToString); + push(vm, OBJ_VAL(abstract)); + + Buffer *buffer = ALLOCATE(vm, Buffer, 1); + buffer->bytes = calloc(1, capacity); + buffer->size = capacity; + + /** + * Setup Buffer object methods + */ + defineNative(vm, &abstract->values, "resize", bufferResize); + defineNative(vm, &abstract->values, "set", bufferSet); + defineNative(vm, &abstract->values, "get", bufferGet); + defineNative(vm, &abstract->values, "subarray", bufferSubAarray); + defineNative(vm, &abstract->values, "string", bufferString); + defineNative(vm, &abstract->values, "len", bufferLen); + + + defineNative(vm, &abstract->values, "writeString", bufferWriteString); + + defineNative(vm, &abstract->values, "readUInt64LE", bufferReadUint64LE); + defineNative(vm, &abstract->values, "readUInt32LE", bufferReadUint32LE); + defineNative(vm, &abstract->values, "readUInt16LE", bufferReadUint16LE); + defineNative(vm, &abstract->values, "readInt64LE", bufferReadint64LE); + defineNative(vm, &abstract->values, "readInt32LE", bufferReadint32LE); + defineNative(vm, &abstract->values, "readInt16LE", bufferReadint16LE); + + defineNative(vm, &abstract->values, "readFloatLE", bufferReadfloat32LE); + defineNative(vm, &abstract->values, "readDoubleLE", bufferReadfloat64LE); + + defineNative(vm, &abstract->values, "writeUInt64LE", bufferWriteUint64LE); + defineNative(vm, &abstract->values, "writeUInt32LE", bufferWriteUint32LE); + defineNative(vm, &abstract->values, "writeUInt16LE", bufferWriteUint16LE); + defineNative(vm, &abstract->values, "writeInt64LE", bufferWriteint64LE); + defineNative(vm, &abstract->values, "writeInt32LE", bufferWriteint32LE); + defineNative(vm, &abstract->values, "writeInt16LE", bufferWriteint16LE); + + defineNative(vm, &abstract->values, "writeFloatLE", bufferWritefloat32LE); + defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); + + + + abstract->data = buffer; + abstract->grayFunc = grayBuffer; + pop(vm); + + return abstract; +} + +static Value newBuffer(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "new() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[0])) { + runtimeError(vm, "new() argument must be a numbers"); + return EMPTY_VAL; + } + + double capacity = AS_NUMBER(args[0]); + if (capacity <= 0) { + return newResultError(vm, "capacity must be greater than 0"); + } + + return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); +} + +static Value newBufferFromString(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1) { + runtimeError(vm, "fromString() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[0])) { + runtimeError(vm, "fromString() argument must be a string"); + return EMPTY_VAL; + } + + ObjString* str = AS_STRING(args[0]); + if (str->length <= 0) { + return newResultError(vm, "capacity must be greater than 0"); + } + ObjAbstract* b = newBufferObj(vm, str->length); + Buffer* buffer = (Buffer*) b->data; + memcpy(buffer->bytes, str->chars, str->length); + return newResultSuccess(vm, OBJ_VAL(b)); +} + + +Value createBufferModule(DictuVM *vm) { + ObjString *name = copyString(vm, "Buffer", 6); + push(vm, OBJ_VAL(name)); + ObjModule *module = newModule(vm, name); + push(vm, OBJ_VAL(module)); + + /** + * Define Buffer methods + */ + defineNative(vm, &module->values, "new", newBuffer); + defineNative(vm, &module->values, "fromString", newBufferFromString); + + pop(vm); + pop(vm); + + return OBJ_VAL(module); +} \ No newline at end of file diff --git a/src/optionals/buffer.h b/src/optionals/buffer.h new file mode 100644 index 000000000..570836e0e --- /dev/null +++ b/src/optionals/buffer.h @@ -0,0 +1,12 @@ +#ifndef dictu_buffer_h +#define dictu_buffer_h + +#include +#include + +#include "optionals.h" +#include "../vm/vm.h" + +Value createBufferModule(DictuVM *vm); + +#endif //dictu_math_h \ No newline at end of file diff --git a/src/optionals/optionals.c b/src/optionals/optionals.c index d76a5e3ab..f175f2d71 100644 --- a/src/optionals/optionals.c +++ b/src/optionals/optionals.c @@ -30,6 +30,7 @@ BuiltinModules modules[] = { {"HTTP", &createHTTPModule, true}, #endif {"BigInt", &createBigIntModule, false}, + {"Buffer", &createBufferModule, false}, {NULL, NULL, false} }; diff --git a/src/optionals/optionals.h b/src/optionals/optionals.h index f39f11c04..169218c21 100644 --- a/src/optionals/optionals.h +++ b/src/optionals/optionals.h @@ -27,6 +27,7 @@ #include "stack.h" #include "bigint.h" #include "object/object.h" +#include "buffer.h" #include "unittest/unittest.h" typedef Value (*BuiltinModule)(DictuVM *vm); From beab8d88c784b5083490f07f2dffa65ac1efebe6 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 02:58:41 +0100 Subject: [PATCH 076/148] fix: i cant code --- src/optionals/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 83f5bed2c..d79a353dd 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -55,7 +55,7 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { buffer->bytes = realloc(buffer->bytes, capacity); if (capacity > buffer->size) { size_t added = capacity - buffer->size; - memset(buffer->bytes + added, 0, added); + memset(buffer->bytes + buffer->size, 0, added); } buffer->size = capacity; return newResultSuccess(vm, args[0]); From af320759ea15d654384d967630375e9ec75cf14b Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 03:04:01 +0100 Subject: [PATCH 077/148] refactor: rename --- src/optionals/buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index d79a353dd..f48b1de79 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -553,7 +553,7 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { return newResultSuccess(vm, NIL_VAL); } -static Value bufferSubAarray(DictuVM *vm, int argCount, Value *args) { +static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); size_t start = 0; size_t end = buffer->size; @@ -609,7 +609,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "resize", bufferResize); defineNative(vm, &abstract->values, "set", bufferSet); defineNative(vm, &abstract->values, "get", bufferGet); - defineNative(vm, &abstract->values, "subarray", bufferSubAarray); + defineNative(vm, &abstract->values, "subarray", bufferSubArray); defineNative(vm, &abstract->values, "string", bufferString); defineNative(vm, &abstract->values, "len", bufferLen); From 8748948fd61c2691f1bc8f7148a43f5a2a073e89 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 18:45:01 +0100 Subject: [PATCH 078/148] refactor: less copy pasta --- src/optionals/buffer.c | 253 +++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 133 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index f48b1de79..eb82a2c5e 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -19,9 +19,9 @@ void freeBuffer(DictuVM *vm, ObjAbstract *abstract) { char *bufferToString(ObjAbstract *abstract) { UNUSED(abstract); - char *queueString = malloc(sizeof(char) * 9); - snprintf(queueString, 9, ""); - return queueString; + char *bufferString = malloc(sizeof(char) * 9); + snprintf(bufferString, 9, ""); + return bufferString; } void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { @@ -36,6 +36,18 @@ bool ensureSize(Buffer* buffer, size_t offset, size_t size){ return buffer->size - offset >= size; } +bool writeInternal(Buffer* buffer, size_t offset, uint8_t* data, size_t len){ + if(!ensureSize(buffer, offset, len)) + return false; + memcpy(buffer->bytes+offset, data, len); + return true; +} + +uint8_t* getReadPtr(Buffer* buffer, size_t offset, size_t len){ + if(!ensureSize(buffer, offset, len)) + return NULL; + return buffer->bytes+offset; +} static Value bufferResize(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { runtimeError(vm, "resize() takes 1 argument (%d given).", argCount); @@ -43,17 +55,18 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { } if (!IS_NUMBER(args[1])) { - runtimeError(vm, "resize() argument must be a numbers"); + runtimeError(vm, "resize() size argument must be a number"); return EMPTY_VAL; } double capacity = AS_NUMBER(args[1]); if (capacity <= 0) { - return newResultError(vm, "capacity must be greater than 0"); + return newResultError(vm, "size must be greater than 0"); } Buffer *buffer = AS_BUFFER(args[0]); buffer->bytes = realloc(buffer->bytes, capacity); if (capacity > buffer->size) { + // 0 init everything if we grew the buffer size_t added = capacity - buffer->size; memset(buffer->bytes + buffer->size, 0, added); } @@ -76,177 +89,152 @@ static Value bufferString(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "string() takes no arguments"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); return OBJ_VAL(copyString(vm, (const char*)buffer->bytes, buffer->size)); } static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeUint16LE() takes 2 argument"); + runtimeError(vm, "writeUInt16LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUint16LE() index argument must be a numbers"); + runtimeError(vm, "writeUInt16LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUint16LE() value argument must be a numbers"); + runtimeError(vm, "writeUInt16LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); uint16_t correctVal = (uint16_t)value; - - if(!ensureSize(buffer, index, sizeof(uint16_t))){ - return newResultError(vm, "index must be smaller then buffer size -2"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint16_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size -2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeUint32LE() takes 2 argument"); + runtimeError(vm, "writeUInt32LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUint32LE() index argument must be a numbers"); + runtimeError(vm, "writeUInt32LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUint32LE() value argument must be a numbers"); + runtimeError(vm, "writeUInt32LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); uint32_t correctVal = (uint32_t)value; - - if(!ensureSize(buffer, index, sizeof(uint32_t))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint32_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeUint64LE() takes 2 argument"); + runtimeError(vm, "writeUInt64LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUint64LE() index argument must be a numbers"); + runtimeError(vm, "writeUInt64LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUint64LE() value argument must be a numbers"); + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "writeUInt64LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); uint64_t correctVal = (uint64_t)value; - - if(!ensureSize(buffer, index, sizeof(uint64_t))){ + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) return newResultError(vm, "index must be smaller then buffer size - 8"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(uint64_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeint64LE() takes 2 argument"); + runtimeError(vm, "writeInt64LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeint64LE() index argument must be a numbers"); + runtimeError(vm, "writeInt64LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeint64LE() value argument must be a numbers"); + runtimeError(vm, "writeInt64LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); - int64_t correctVal = (int64_t)value; - - if(!ensureSize(buffer, index, sizeof(int64_t))){ - return newResultError(vm, "index must be smaller then buffer size - 8"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int64_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeint32LE() takes 2 argument"); + runtimeError(vm, "writeInt32LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeint32LE() index argument must be a numbers"); + runtimeError(vm, "writeInt32LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeint32LE() value argument must be a numbers"); + runtimeError(vm, "writeInt32LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); int32_t correctVal = (int32_t)value; - - if(!ensureSize(buffer, index, sizeof(int32_t))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int32_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { - runtimeError(vm, "writeint16LE() takes 2 argument"); + runtimeError(vm, "writeInt16LE() takes 2 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeint16LE() index argument must be a numbers"); + runtimeError(vm, "writeInt16LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeint16LE() value argument must be a numbers"); + runtimeError(vm, "writeInt16LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); int16_t correctVal = (int16_t)value; - - if(!ensureSize(buffer, index, sizeof(int16_t))){ - return newResultError(vm, "index must be smaller then buffer size - 2"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(int16_t)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { @@ -257,24 +245,20 @@ static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeFloatLE() index argument must be a numbers"); + runtimeError(vm, "writeFloatLE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeFloatLE() value argument must be a numbers"); + runtimeError(vm, "writeFloatLE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); float correctVal = (float)value; - - if(!ensureSize(buffer, index, sizeof(float))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(float)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { @@ -285,11 +269,11 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeDoubleLE() index argument must be a numbers"); + runtimeError(vm, "writeDoubleLE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeDoubleLE() value argument must be a numbers"); + runtimeError(vm, "writeDoubleLE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -297,12 +281,9 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { double correctVal = value; - if(!ensureSize(buffer, index, sizeof(double))){ - return newResultError(vm, "index must be smaller then buffer size - 8"); - } - uint8_t* ptr = (uint8_t*)&correctVal; - memcpy(buffer->bytes+(size_t)index, ptr, sizeof(double)); - return newResultSuccess(vm, NUMBER_VAL(value)); + if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { @@ -313,16 +294,17 @@ static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readDoubleLE() index argument must be a numbers"); + runtimeError(vm, "readDoubleLE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value; - if(!ensureSize(buffer, index, sizeof(value))){ + + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { @@ -333,136 +315,141 @@ static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readFloatLE() index argument must be a numbers"); + runtimeError(vm, "readFloatLE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); float value; - if(!ensureSize(buffer, index, sizeof(value))){ + + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readUint64LE() takes 1 argument"); + runtimeError(vm, "readUInt64LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUint64LE() index argument must be a numbers"); + runtimeError(vm, "readUInt64LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); uint64_t value; - if(!ensureSize(buffer, index, sizeof(value))){ + + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readUint32LE() takes 1 argument"); + runtimeError(vm, "readUInt32LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUint32LE() index argument must be a numbers"); + runtimeError(vm, "readUInt32LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); uint32_t value; - if(!ensureSize(buffer, index, sizeof(value))){ + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readUint16LE() takes 1 argument"); + runtimeError(vm, "readUInt16LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUint16LE() index argument must be a numbers"); + runtimeError(vm, "readUInt16LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); + uint16_t value; - if(!ensureSize(buffer, index, sizeof(value))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readint64LE() takes 1 argument"); + runtimeError(vm, "readInt64LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readint64LE() index argument must be a numbers"); + runtimeError(vm, "readInt64LE() index argument must be a numbers"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); int64_t value; - if(!ensureSize(buffer, index, sizeof(value))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readint32LE() takes 1 argument"); + runtimeError(vm, "readInt32LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readint32LE() index argument must be a numbers"); + runtimeError(vm, "readInt32LE() index argument must be a numbers"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); + int32_t value; - if(!ensureSize(buffer, index, sizeof(value))){ + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { - runtimeError(vm, "readint32LE() takes 1 argument"); + runtimeError(vm, "readInt16LE() takes 1 argument"); return EMPTY_VAL; } Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readint32LE() index argument must be a numbers"); + runtimeError(vm, "readInt16LE() index argument must be a numbers"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); + int16_t value; - if(!ensureSize(buffer, index, sizeof(value))){ - return newResultError(vm, "index must be smaller then buffer size - 4"); - } - memcpy(&value, buffer->bytes+(size_t)index, sizeof(value)); - return newResultSuccess(vm, NUMBER_VAL(value)); + uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); + if(ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); + memcpy(&value, ptr, sizeof(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } From 7f9a908399c2b7e223827a8e858ce3ab60273e23 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 19:01:14 +0100 Subject: [PATCH 079/148] more fixing --- src/optionals/buffer.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index eb82a2c5e..f58b07f4e 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -398,7 +398,7 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt64LE() index argument must be a numbers"); + runtimeError(vm, "readInt64LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -418,7 +418,7 @@ static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt32LE() index argument must be a numbers"); + runtimeError(vm, "readInt32LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -439,7 +439,7 @@ static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt16LE() index argument must be a numbers"); + runtimeError(vm, "readInt16LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -460,7 +460,7 @@ static Value bufferGet(DictuVM *vm, int argCount, Value *args) { } if (!IS_NUMBER(args[1])) { - runtimeError(vm, "get() argument must be a numbers"); + runtimeError(vm, "get() argument must be a number"); return EMPTY_VAL; } @@ -483,12 +483,12 @@ static Value bufferSet(DictuVM *vm, int argCount, Value *args) { } if (!IS_NUMBER(args[1])) { - runtimeError(vm, "set() index argument must be a numbers"); + runtimeError(vm, "set() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "set() value argument must be a numbers"); + runtimeError(vm, "set() value argument must be a number"); return EMPTY_VAL; } @@ -514,7 +514,7 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { } if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeString() index argument must be a numbers"); + runtimeError(vm, "writeString() index argument must be a number"); return EMPTY_VAL; } @@ -657,14 +657,14 @@ static Value newBufferFromString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - if (!IS_NUMBER(args[0])) { + if (!IS_STRING(args[0])) { runtimeError(vm, "fromString() argument must be a string"); return EMPTY_VAL; } ObjString* str = AS_STRING(args[0]); if (str->length <= 0) { - return newResultError(vm, "capacity must be greater than 0"); + return newResultError(vm, "string length needs to be greater then 0"); } ObjAbstract* b = newBufferObj(vm, str->length); Buffer* buffer = (Buffer*) b->data; From 2b03fc836db38d2c814d91aeba54d33f6e1452fb Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 22:55:29 +0100 Subject: [PATCH 080/148] feat: basic docs for buffer module --- docs/docs/standard-lib/buffer.md | 283 +++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 docs/docs/standard-lib/buffer.md diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md new file mode 100644 index 000000000..d171b7ae2 --- /dev/null +++ b/docs/docs/standard-lib/buffer.md @@ -0,0 +1,283 @@ +--- +layout: default +title: Buffer +nav_order: 6 +parent: Standard Library +--- + +# Buffer +{: .no_toc } + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +--- + +## Buffer +To make use of the Buffer module an import is required. + +```js +import Buffer; +``` + +### Buffer.new() -> Result\ + +Returns a Result with a new buffer with the given size in bytes. + +```cs +const buffer = Buffer.new(1024).unwrap(); +print(buffer); +// +``` + +### Buffer.fromString(String) -> Result\ + +Returns a Result with a new buffer created from the given string. + +```cs +const buffer = Buffer.fromString("Dictu!").unwrap(); +print(buffer); +// +``` + +### Buffer.resize(Number) -> Result\ + +Resizes the buffer to the given size, the argument needs to be greater then 0 or the function will return a error. + +```cs +const buffer = Buffer.new(8).unwrap(); +print(buffer.resize(16).unwrap()); +// 16 +``` + +### Buffer.get(Number) -> Result\ + +Returns the value of byte at the given index. +```cs +const buffer = Buffer.new("Dictu!").unwrap(); +print(buffer.get(0).unwrap()); + +// 68 (ASCII value of 'D') +``` + +### Buffer.set(Number, Number) -> Result\ + +Sets the given index of the buffer to the second argument. +Returns a Number result with the new value. +```cs +const buffer = Buffer.fromString("dictu!").unwrap(); +buffer.set(0, 68).unwrap(); +print(buffer.string()); // "Dictu!" +``` + +### Buffer.subarray(Number: start -> Optional, Number: end -> Optional) -> Result\ + +Returns a new Buffer with the optional given start and end parameters. +* `start`: The start index within the buffer, default `0` +* `end`: The end index within the buffer(non inclusive), default: `buffer.len()` +```cs +const buffer = Buffer.fromString("Dictu!").unwrap(); +const sub = buffer.subarray(0, buffer.len()-1).unwrap(); +print(sub.string()); // "Dictu" +``` + +### Buffer.string() -> String + +Returns a string representation of the buffer. +```cs +const buffer = Buffer.fromString("Dictu!").unwrap(); +const str = buffer.string(); +print(str); // "Dictu!" +``` + +### Buffer.len() -> Number + +Returns the byte length of the buffer. +```cs +const buffer = Buffer.new(9).unwrap(); +const len = buffer.len(); +print(len); // 9 +``` + +### Buffer.writeString(Number, String) -> Result\ + +Sets a string into buffer given the starting index, if the string doesn't fit in the buffer a error is returned. +```cs +const buffer = Buffer.new(6).unwrap(); +buffer.writeString(0, "Dictu!"); +``` + +### Buffer.readString(Number: start -> Optional, Number: end -> Optional) -> Result\ + +Returns a String with the optional given start and end parameters, this works very similar to subarray. +* `start`: The start index within the buffer, default `0` +* `end`: The end index within the buffer(non inclusive), default: `buffer.len()` +```cs +const buffer = Buffer.new(6).unwrap(); +buffer.writeString(0, "Dictu!"); +const sub = buffer.string(0, buffer.len()-1).unwrap(); +print(sub) // "Dictu" +``` + +### Buffer.readUInt64LE(Number) -> Result\ + +Returns the u64(unsigned 8 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeUInt64LE(0, 12000); +print(buffer.readUInt64LE(0).unwrap()) // 12000 +``` + +### Buffer.readUInt32LE(Number) -> Result\ + +Returns the u32(unsigned 4 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeUInt32LE(0, 1337); +print(buffer.readUInt32LE(0).unwrap()) // 1337 +``` + +### Buffer.readUInt16LE(Number) -> Result\ + +Returns the u16(unsigned 2 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeUInt16LE(0, 1337); +print(buffer.readUInt16LE(0).unwrap()) // 1337 +``` + +### Buffer.readInt64LE(Number) -> Result\ + +Returns the i64(signed 8 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeInt64LE(0, -12000); +print(buffer.readInt64LE(0).unwrap()) // -12000 +``` + +### Buffer.readInt32LE(Number) -> Result\ + +Returns the i32(signed 4 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeUInt32LE(0, -1337); +print(buffer.readUInt32LE(0).unwrap()) // -1337 +``` + +### Buffer.readInt16LE(Number) -> Result\ + +Returns the i16(signed 2 byte integer in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeUInt16LE(0, -1337); +print(buffer.readUInt16LE(0).unwrap()) // -1337 +``` + +### Buffer.writeUInt64LE(Number, Number) -> Result\ + +Writes a u64(unsigned 8 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeUInt64LE(0, 12000); +``` + +### Buffer.writeUInt32LE(Number, Number) -> Result\ + +Writes a u32(unsigned 4 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeUInt32LE(0, 1337); +``` + +### Buffer.writeUInt16LE(Number, Number) -> Result\ + +Writes a u16(unsigned 2 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeUInt16LE(0, 1337); +``` + +### Buffer.writeInt64LE(Number, Number) -> Result\ + +Writes a i64(signed 8 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeInt64LE(0, 12000); +``` + +### Buffer.writeInt32LE(Number, Number) -> Result\ + +Writes a i32(signed 4 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeInt32LE(0, 1337); +``` + +### Buffer.writeInt16LE(Number, Number) -> Result\ + +Writes a i16(signed 2 byte integer in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeInt16LE(0, 1337); +``` + +### Buffer.writeFloatLE(Number, Number) -> Result\ + +Writes a float(4 byte signed floating point number in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeFloatLE(0, 14.34); +``` + +### Buffer.writeDoubleLE(Number, Number) -> Result\ + +Writes a double(8 byte signed floating point number in little endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeDoubleLE(0, 14.34); +``` + +### Buffer.readFloatLE(Number) -> Result\ + +Returns the float(signed 4 byte floating point number in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeFloatLE(0, 14.34); +print(buffer.readFloatLE(0).unwrap()) // 14.34 +``` + +### Buffer.readDoubleLE(Number) -> Result\ + +Returns the double(signed 8 byte floating point number in little endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeDoubleLE(0, 14.34); +print(buffer.readDoubleLE(0).unwrap()) // 14.34 +``` \ No newline at end of file From fd43d1f4ea00fbae10811e49b3f86ae8fd4b6881 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 23:10:46 +0100 Subject: [PATCH 081/148] feat: buffer max and readString --- docs/docs/standard-lib/buffer.md | 2 ++ src/optionals/buffer.c | 55 +++++++++++++++++++++++++++++--- src/optionals/buffer.h | 2 ++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index d171b7ae2..575062c25 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -23,6 +23,8 @@ To make use of the Buffer module an import is required. import Buffer; ``` +The maximum byte size for a buffer is `2147483647 - 1` + ### Buffer.new() -> Result\ Returns a Result with a new buffer with the given size in bytes. diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index f58b07f4e..ba33724c3 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -1,5 +1,5 @@ #include "buffer.h" -#include +#include typedef struct { uint8_t *bytes; @@ -48,6 +48,7 @@ uint8_t* getReadPtr(Buffer* buffer, size_t offset, size_t len){ return NULL; return buffer->bytes+offset; } + static Value bufferResize(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { runtimeError(vm, "resize() takes 1 argument (%d given).", argCount); @@ -60,8 +61,8 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { } double capacity = AS_NUMBER(args[1]); - if (capacity <= 0) { - return newResultError(vm, "size must be greater than 0"); + if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { + return newResultError(vm, "size must be greater than 0 and smaller then 2147483647"); } Buffer *buffer = AS_BUFFER(args[0]); buffer->bytes = realloc(buffer->bytes, capacity); @@ -346,6 +347,9 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); + const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; + if(value > MAX_VALUE) + return newResultError(vm, "value would overflow internal reprentation"); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -407,6 +411,9 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { if(ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); + const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; + if((uint64_t)value > MAX_VALUE) + return newResultError(vm, "value would overflow internal reprentation"); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -540,6 +547,43 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { return newResultSuccess(vm, NIL_VAL); } +static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); + size_t start = 0; + size_t end = buffer->size; + int length = buffer->size; + if (argCount > 0) { + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readString() start argument must be a number"); + return EMPTY_VAL; + } + double startParam = AS_NUMBER(args[1]); + if (startParam >= buffer->size) { + return newResultError(vm, "start greater or equals then buffer length"); + } else { + start = startParam; + length = end - start; + } + } + if (argCount == 2) { + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "readString() end argument must be a number"); + return EMPTY_VAL; + } + double endParam = AS_NUMBER(args[2]); + if(endParam > buffer->size){ + return newResultError(vm, "end greater then buffer length"); + } else { + end = endParam; + length = end - start; + } + } + if(length <= 0){ + return newResultError(vm, "length is 0"); + } + return newResultSuccess(vm, OBJ_VAL(copyString(vm, (const char*)buffer->bytes+start, length))); +} + static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); size_t start = 0; @@ -602,6 +646,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "writeString", bufferWriteString); + defineNative(vm, &abstract->values, "readString", bufferReadString); defineNative(vm, &abstract->values, "readUInt64LE", bufferReadUint64LE); defineNative(vm, &abstract->values, "readUInt32LE", bufferReadUint32LE); @@ -644,8 +689,8 @@ static Value newBuffer(DictuVM *vm, int argCount, Value *args) { } double capacity = AS_NUMBER(args[0]); - if (capacity <= 0) { - return newResultError(vm, "capacity must be greater than 0"); + if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { + return newResultError(vm, "capacity must be greater than 0 and less then 2147483647"); } return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); diff --git a/src/optionals/buffer.h b/src/optionals/buffer.h index 570836e0e..ed2cfdad6 100644 --- a/src/optionals/buffer.h +++ b/src/optionals/buffer.h @@ -7,6 +7,8 @@ #include "optionals.h" #include "../vm/vm.h" +#define BUFFER_SIZE_MAX 2147483647 + Value createBufferModule(DictuVM *vm); #endif //dictu_math_h \ No newline at end of file From 7cfd14d911cf56884339d090e9d2c5eac08c29a9 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 23 Jan 2024 23:21:57 +0100 Subject: [PATCH 082/148] refactor: order of modules --- docs/docs/standard-lib/buffer.md | 2 +- docs/docs/standard-lib/datetime.md | 2 +- docs/docs/standard-lib/env.md | 2 +- docs/docs/standard-lib/hashlib.md | 2 +- docs/docs/standard-lib/http.md | 2 +- docs/docs/standard-lib/inspect.md | 2 +- docs/docs/standard-lib/io.md | 2 +- docs/docs/standard-lib/json.md | 2 +- docs/docs/standard-lib/log.md | 2 +- docs/docs/standard-lib/math.md | 2 +- docs/docs/standard-lib/net.md | 2 +- docs/docs/standard-lib/object.md | 2 +- docs/docs/standard-lib/path.md | 2 +- docs/docs/standard-lib/process.md | 2 +- docs/docs/standard-lib/queue.md | 2 +- docs/docs/standard-lib/random.md | 2 +- docs/docs/standard-lib/socket.md | 2 +- docs/docs/standard-lib/sqlite.md | 2 +- docs/docs/standard-lib/stack.md | 2 +- docs/docs/standard-lib/system.md | 2 +- docs/docs/standard-lib/term.md | 2 +- docs/docs/standard-lib/unittest.md | 2 +- docs/docs/standard-lib/uuid.md | 2 +- 23 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 575062c25..25cfbddaf 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -1,7 +1,7 @@ --- layout: default title: Buffer -nav_order: 6 +nav_order: 4 parent: Standard Library --- diff --git a/docs/docs/standard-lib/datetime.md b/docs/docs/standard-lib/datetime.md index b6558bbd8..2e27c3ad9 100644 --- a/docs/docs/standard-lib/datetime.md +++ b/docs/docs/standard-lib/datetime.md @@ -1,7 +1,7 @@ --- layout: default title: Datetime -nav_order: 4 +nav_order: 5 parent: Standard Library --- diff --git a/docs/docs/standard-lib/env.md b/docs/docs/standard-lib/env.md index 0ee26cf11..fb7ac73c4 100644 --- a/docs/docs/standard-lib/env.md +++ b/docs/docs/standard-lib/env.md @@ -1,7 +1,7 @@ --- layout: default title: Env -nav_order: 5 +nav_order: 6 parent: Standard Library --- diff --git a/docs/docs/standard-lib/hashlib.md b/docs/docs/standard-lib/hashlib.md index ea7063cca..a0ee80cfa 100644 --- a/docs/docs/standard-lib/hashlib.md +++ b/docs/docs/standard-lib/hashlib.md @@ -1,7 +1,7 @@ --- layout: default title: Hashlib -nav_order: 6 +nav_order: 7 parent: Standard Library --- diff --git a/docs/docs/standard-lib/http.md b/docs/docs/standard-lib/http.md index f45826f6c..89a809a43 100644 --- a/docs/docs/standard-lib/http.md +++ b/docs/docs/standard-lib/http.md @@ -1,7 +1,7 @@ --- layout: default title: HTTP -nav_order: 7 +nav_order: 8 parent: Standard Library --- diff --git a/docs/docs/standard-lib/inspect.md b/docs/docs/standard-lib/inspect.md index 307518604..32664ef60 100644 --- a/docs/docs/standard-lib/inspect.md +++ b/docs/docs/standard-lib/inspect.md @@ -1,7 +1,7 @@ --- layout: default title: Inspect -nav_order: 8 +nav_order: 9 parent: Standard Library --- diff --git a/docs/docs/standard-lib/io.md b/docs/docs/standard-lib/io.md index 5d3071db1..51a2c79f3 100644 --- a/docs/docs/standard-lib/io.md +++ b/docs/docs/standard-lib/io.md @@ -1,7 +1,7 @@ --- layout: default title: IO -nav_order: 9 +nav_order: 10 parent: Standard Library --- diff --git a/docs/docs/standard-lib/json.md b/docs/docs/standard-lib/json.md index ada1a8a79..cc2a73e57 100644 --- a/docs/docs/standard-lib/json.md +++ b/docs/docs/standard-lib/json.md @@ -1,7 +1,7 @@ --- layout: default title: JSON -nav_order: 10 +nav_order: 11 parent: Standard Library --- diff --git a/docs/docs/standard-lib/log.md b/docs/docs/standard-lib/log.md index e14f0cc50..8f3e91a48 100644 --- a/docs/docs/standard-lib/log.md +++ b/docs/docs/standard-lib/log.md @@ -1,7 +1,7 @@ --- layout: default title: Log -nav_order: 11 +nav_order: 12 parent: Standard Library --- diff --git a/docs/docs/standard-lib/math.md b/docs/docs/standard-lib/math.md index d7d94ae70..36266e769 100644 --- a/docs/docs/standard-lib/math.md +++ b/docs/docs/standard-lib/math.md @@ -1,7 +1,7 @@ --- layout: default title: Math -nav_order: 12 +nav_order: 13 parent: Standard Library --- diff --git a/docs/docs/standard-lib/net.md b/docs/docs/standard-lib/net.md index 1d59f56a7..6ecbf240c 100644 --- a/docs/docs/standard-lib/net.md +++ b/docs/docs/standard-lib/net.md @@ -1,7 +1,7 @@ --- layout: default title: Net -nav_order: 13 +nav_order: 14 parent: Standard Library --- diff --git a/docs/docs/standard-lib/object.md b/docs/docs/standard-lib/object.md index dc5cbaf9c..3c2b76e47 100644 --- a/docs/docs/standard-lib/object.md +++ b/docs/docs/standard-lib/object.md @@ -1,7 +1,7 @@ --- layout: default title: Object -nav_order: 14 +nav_order: 15 parent: Standard Library --- diff --git a/docs/docs/standard-lib/path.md b/docs/docs/standard-lib/path.md index acdef7c30..6b4af35d9 100644 --- a/docs/docs/standard-lib/path.md +++ b/docs/docs/standard-lib/path.md @@ -1,7 +1,7 @@ --- layout: default title: Path -nav_order: 15 +nav_order: 16 parent: Standard Library --- diff --git a/docs/docs/standard-lib/process.md b/docs/docs/standard-lib/process.md index 165f8b1c4..35431043d 100644 --- a/docs/docs/standard-lib/process.md +++ b/docs/docs/standard-lib/process.md @@ -1,7 +1,7 @@ --- layout: default title: Process -nav_order: 16 +nav_order: 17 parent: Standard Library --- diff --git a/docs/docs/standard-lib/queue.md b/docs/docs/standard-lib/queue.md index a8db6d283..60e617bb9 100644 --- a/docs/docs/standard-lib/queue.md +++ b/docs/docs/standard-lib/queue.md @@ -1,7 +1,7 @@ --- layout: default title: Queue -nav_order: 17 +nav_order: 18 parent: Standard Library --- diff --git a/docs/docs/standard-lib/random.md b/docs/docs/standard-lib/random.md index b4f330dd9..d5c266175 100644 --- a/docs/docs/standard-lib/random.md +++ b/docs/docs/standard-lib/random.md @@ -1,7 +1,7 @@ --- layout: default title: Random -nav_order: 18 +nav_order: 19 parent: Standard Library --- diff --git a/docs/docs/standard-lib/socket.md b/docs/docs/standard-lib/socket.md index 8fcec8337..bf84425f6 100644 --- a/docs/docs/standard-lib/socket.md +++ b/docs/docs/standard-lib/socket.md @@ -1,7 +1,7 @@ --- layout: default title: Socket -nav_order: 19 +nav_order: 20 parent: Standard Library --- diff --git a/docs/docs/standard-lib/sqlite.md b/docs/docs/standard-lib/sqlite.md index 2bf9c6ed7..cc217fbdf 100644 --- a/docs/docs/standard-lib/sqlite.md +++ b/docs/docs/standard-lib/sqlite.md @@ -1,7 +1,7 @@ --- layout: default title: Sqlite -nav_order: 20 +nav_order: 21 parent: Standard Library --- diff --git a/docs/docs/standard-lib/stack.md b/docs/docs/standard-lib/stack.md index 10756fa8d..5299b4c2c 100644 --- a/docs/docs/standard-lib/stack.md +++ b/docs/docs/standard-lib/stack.md @@ -1,7 +1,7 @@ --- layout: default title: Stack -nav_order: 21 +nav_order: 22 parent: Standard Library --- diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index acdaef63a..7f5f23e5e 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -1,7 +1,7 @@ --- layout: default title: System -nav_order: 22 +nav_order: 23 parent: Standard Library --- diff --git a/docs/docs/standard-lib/term.md b/docs/docs/standard-lib/term.md index b46c73919..19331a0c7 100644 --- a/docs/docs/standard-lib/term.md +++ b/docs/docs/standard-lib/term.md @@ -1,7 +1,7 @@ --- layout: default title: Term -nav_order: 23 +nav_order: 24 parent: Standard Library --- diff --git a/docs/docs/standard-lib/unittest.md b/docs/docs/standard-lib/unittest.md index be88a70d8..9a6021b79 100644 --- a/docs/docs/standard-lib/unittest.md +++ b/docs/docs/standard-lib/unittest.md @@ -1,7 +1,7 @@ --- layout: default title: UnitTest -nav_order: 24 +nav_order: 25 parent: Standard Library --- diff --git a/docs/docs/standard-lib/uuid.md b/docs/docs/standard-lib/uuid.md index 2e6f0e93b..8bbf2eee2 100644 --- a/docs/docs/standard-lib/uuid.md +++ b/docs/docs/standard-lib/uuid.md @@ -1,7 +1,7 @@ --- layout: default title: UUID -nav_order: 25 +nav_order: 26 parent: Standard Library --- From bfaa6a8eb5c0d71b06eba71de62af32c5c249ecb Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 24 Jan 2024 01:45:55 +0100 Subject: [PATCH 083/148] fix: typos --- src/optionals/buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index ba33724c3..d5376aedb 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -115,7 +115,7 @@ static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { uint16_t correctVal = (uint16_t)value; if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size -2"); + return newResultError(vm, "index must be smaller then buffer size - 2"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -349,7 +349,7 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { memcpy(&value, ptr, sizeof(value)); const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; if(value > MAX_VALUE) - return newResultError(vm, "value would overflow internal reprentation"); + return newResultError(vm, "value would overflow internal representation"); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -413,7 +413,7 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { memcpy(&value, ptr, sizeof(value)); const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; if((uint64_t)value > MAX_VALUE) - return newResultError(vm, "value would overflow internal reprentation"); + return newResultError(vm, "value would overflow internal representation"); return newResultSuccess(vm, NUMBER_VAL(value)); } From ce167fdfee021b4338c18a9864eb0fb57aa06b58 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 24 Jan 2024 19:44:08 +0100 Subject: [PATCH 084/148] feat: add big endian functions and docs --- docs/docs/standard-lib/buffer.md | 94 ++++++++ src/optionals/buffer.c | 381 ++++++++++++++++++++++--------- src/optionals/buffer.h | 3 + 3 files changed, 365 insertions(+), 113 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 25cfbddaf..1ce4e6b92 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -278,6 +278,100 @@ print(buffer.readFloatLE(0).unwrap()) // 14.34 Returns the double(signed 8 byte floating point number in little endian) value given the starting index. Returns a result with the value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeDoubleLE(0, 14.34); +print(buffer.readDoubleLE(0).unwrap()) // 14.34 +``` + +### Buffer.writeUInt64BE(Number, Number) -> Result\ + +Writes a u64(unsigned 8 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeUInt64LE(0, 12000); +``` + +### Buffer.writeUInt32BE(Number, Number) -> Result\ + +Writes a u32(unsigned 4 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeUInt32LE(0, 1337); +``` + +### Buffer.writeUInt16BE(Number, Number) -> Result\ + +Writes a u16(unsigned 2 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeUInt16LE(0, 1337); +``` + +### Buffer.writeInt64BE(Number, Number) -> Result\ + +Writes a i64(signed 8 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeInt64LE(0, 12000); +``` + +### Buffer.writeInt32BE(Number, Number) -> Result\ + +Writes a i32(signed 4 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeInt32LE(0, 1337); +``` + +### Buffer.writeInt16BE(Number, Number) -> Result\ + +Writes a i16(signed 2 byte integer in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeInt16LE(0, 1337); +``` + +### Buffer.writeFloatBE(Number, Number) -> Result\ + +Writes a float(4 byte signed floating point number in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeFloatLE(0, 14.34); +``` + +### Buffer.writeDoubleBE(Number, Number) -> Result\ + +Writes a double(8 byte signed floating point number in big endian) at the index(the first argument). +Returns a result with the set value or a error. +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeDoubleLE(0, 14.34); +``` + +### Buffer.readFloatBE(Number) -> Result\ + +Returns the float(signed 4 byte floating point number in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeFloatLE(0, 14.34); +print(buffer.readFloatLE(0).unwrap()) // 14.34 +``` + +### Buffer.readDoubleBE(Number) -> Result\ + +Returns the double(signed 8 byte floating point number in big endian) value given the starting index. +Returns a result with the value or a error. + ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeDoubleLE(0, 14.34); diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index d5376aedb..5dec032e3 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -4,6 +4,7 @@ typedef struct { uint8_t *bytes; int size; + bool bigEndian; } Buffer; #define AS_BUFFER(v) ((Buffer *)AS_ABSTRACT(v)->data) @@ -17,7 +18,7 @@ void freeBuffer(DictuVM *vm, ObjAbstract *abstract) { } char *bufferToString(ObjAbstract *abstract) { -UNUSED(abstract); + UNUSED(abstract); char *bufferString = malloc(sizeof(char) * 9); snprintf(bufferString, 9, ""); @@ -32,21 +33,48 @@ void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { return; } -bool ensureSize(Buffer* buffer, size_t offset, size_t size){ - return buffer->size - offset >= size; +uint8_t *swap(uint8_t *ptr, size_t len, bool bigEndian) { + if (len < 2) + return ptr; + if (!bigEndian) { +#ifdef IS_BIG_ENDIAN +#else + return ptr; +#endif + } else { +#ifndef IS_BIG_ENDIAN +#else + return ptr; +#endif + } + int start = 0; + int end = (len)-1; + uint8_t temp; + while (start < end) { + temp = ptr[start]; + ptr[start] = ptr[end]; + ptr[end] = temp; + start++; + end--; + } + return ptr; } -bool writeInternal(Buffer* buffer, size_t offset, uint8_t* data, size_t len){ - if(!ensureSize(buffer, offset, len)) - return false; - memcpy(buffer->bytes+offset, data, len); - return true; +bool ensureSize(Buffer *buffer, size_t offset, size_t size) { + return buffer->size - offset >= size; } -uint8_t* getReadPtr(Buffer* buffer, size_t offset, size_t len){ - if(!ensureSize(buffer, offset, len)) - return NULL; - return buffer->bytes+offset; +bool writeInternal(Buffer *buffer, size_t offset, uint8_t *data, size_t len) { + if (!ensureSize(buffer, offset, len)) + return false; + memcpy(buffer->bytes + offset, data, len); + return true; +} + +uint8_t *getReadPtr(Buffer *buffer, size_t offset, size_t len) { + if (!ensureSize(buffer, offset, len)) + return NULL; + return buffer->bytes + offset; } static Value bufferResize(DictuVM *vm, int argCount, Value *args) { @@ -62,7 +90,8 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { double capacity = AS_NUMBER(args[1]); if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { - return newResultError(vm, "size must be greater than 0 and smaller then 2147483647"); + return newResultError( + vm, "size must be greater than 0 and smaller then 2147483647"); } Buffer *buffer = AS_BUFFER(args[0]); buffer->bytes = realloc(buffer->bytes, capacity); @@ -80,9 +109,9 @@ static Value bufferLen(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "len() takes no arguments"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); - return NUMBER_VAL(buffer->size); + return NUMBER_VAL(buffer->size); } static Value bufferString(DictuVM *vm, int argCount, Value *args) { @@ -92,7 +121,7 @@ static Value bufferString(DictuVM *vm, int argCount, Value *args) { } Buffer *buffer = AS_BUFFER(args[0]); - return OBJ_VAL(copyString(vm, (const char*)buffer->bytes, buffer->size)); + return OBJ_VAL(copyString(vm, (const char *)buffer->bytes, buffer->size)); } static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { @@ -100,13 +129,13 @@ static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeUInt16LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeUInt16LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeUInt16LE() value argument must be a number"); return EMPTY_VAL; } @@ -114,9 +143,13 @@ static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); uint16_t correctVal = (uint16_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { @@ -124,13 +157,13 @@ static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeUInt32LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeUInt32LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeUInt32LE() value argument must be a number"); return EMPTY_VAL; } @@ -138,9 +171,12 @@ static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); uint32_t correctVal = (uint32_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { @@ -148,7 +184,7 @@ static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeUInt64LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeUInt64LE() index argument must be a number"); @@ -162,8 +198,11 @@ static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); uint64_t correctVal = (uint64_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -172,21 +211,24 @@ static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeInt64LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeInt64LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeInt64LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); double value = AS_NUMBER(args[2]); int64_t correctVal = (int64_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -195,13 +237,13 @@ static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeInt32LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeInt32LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeInt32LE() value argument must be a number"); return EMPTY_VAL; } @@ -209,8 +251,11 @@ static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); int32_t correctVal = (int32_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -219,13 +264,13 @@ static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeInt16LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeInt16LE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeInt16LE() value argument must be a number"); return EMPTY_VAL; } @@ -233,9 +278,12 @@ static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); int16_t correctVal = (int16_t)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { @@ -243,13 +291,13 @@ static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeFloatLE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeFloatLE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeFloatLE() value argument must be a number"); return EMPTY_VAL; } @@ -257,8 +305,11 @@ static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { double value = AS_NUMBER(args[2]); float correctVal = (float)value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -267,13 +318,13 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "writeDoubleLE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); + Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { runtimeError(vm, "writeDoubleLE() index argument must be a number"); return EMPTY_VAL; } - if (!IS_NUMBER(args[2])) { + if (!IS_NUMBER(args[2])) { runtimeError(vm, "writeDoubleLE() value argument must be a number"); return EMPTY_VAL; } @@ -282,8 +333,11 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { double correctVal = value; - if(!writeInternal(buffer, index, (uint8_t*)&correctVal, sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -301,10 +355,12 @@ static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); double value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -322,10 +378,11 @@ static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); float value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -343,13 +400,14 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); uint64_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if(value > MAX_VALUE) - return newResultError(vm, "value would overflow internal representation"); + if (value > MAX_VALUE) + return newResultError(vm, "value would overflow internal representation"); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -366,10 +424,11 @@ static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { } double index = AS_NUMBER(args[1]); uint32_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -387,10 +446,11 @@ static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); uint16_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -407,13 +467,14 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { } double index = AS_NUMBER(args[1]); int64_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); - const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if((uint64_t)value > MAX_VALUE) - return newResultError(vm, "value would overflow internal representation"); + const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; + if ((uint64_t)value > MAX_VALUE) + return newResultError(vm, "value would overflow internal representation"); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -431,10 +492,11 @@ static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); int32_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -452,13 +514,88 @@ static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { double index = AS_NUMBER(args[1]); int16_t value; - uint8_t* ptr = getReadPtr(buffer, index, sizeof(value)); - if(ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } +typedef Value buffer_func_t(DictuVM *vm, int argCount, Value *args); +// is this hacky? +static Value runBigEndian(DictuVM *vm, int argCount, Value *args, + buffer_func_t *f) { + Buffer *buffer = AS_BUFFER(args[0]); + buffer->bigEndian = true; + Value result = f(vm, argCount, args); + buffer->bigEndian = false; + return result; +} + +static Value bufferReadUint64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadUint64LE); +} + +static Value bufferReadUint32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadUint32LE); +} + +static Value bufferReadUint16BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadUint16LE); +} + +static Value bufferReadint64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadint64LE); +} + +static Value bufferReadint32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadint32LE); +} + +static Value bufferReadint16BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadint16LE); +} + +static Value bufferReadfloat32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadfloat32LE); +} + +static Value bufferReadfloat64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferReadfloat64LE); +} + +static Value bufferWriteUint64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteUint64LE); +} + +static Value bufferWriteUint32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteUint32LE); +} + +static Value bufferWriteUint16BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteUint16LE); +} + +static Value bufferWriteint64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteint64LE); +} + +static Value bufferWriteint32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteint32LE); +} + +static Value bufferWriteint16BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWriteint16LE); +} + +static Value bufferWritefloat32BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWritefloat32LE); +} + +static Value bufferWritefloat64BE(DictuVM *vm, int argCount, Value *args) { + return runBigEndian(vm, argCount, args, &bufferWritefloat64LE); +} static Value bufferGet(DictuVM *vm, int argCount, Value *args) { if (argCount != 1) { @@ -531,7 +668,7 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { } double index = AS_NUMBER(args[1]); - ObjString* str = AS_STRING(args[2]); + ObjString *str = AS_STRING(args[2]); if (index < 0) { return newResultError(vm, "index must be greater than -1"); } @@ -540,10 +677,10 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { return newResultError(vm, "index must be smaller then buffer size"); } - if(buffer->size - index < str->length) { + if (buffer->size - index < str->length) { return newResultError(vm, "buffer is not large enough to fit the string"); } - memcpy(buffer->bytes+(size_t)index, str->chars, str->length); + memcpy(buffer->bytes + (size_t)index, str->chars, str->length); return newResultSuccess(vm, NIL_VAL); } @@ -559,10 +696,10 @@ static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { } double startParam = AS_NUMBER(args[1]); if (startParam >= buffer->size) { - return newResultError(vm, "start greater or equals then buffer length"); + return newResultError(vm, "start greater or equals then buffer length"); } else { - start = startParam; - length = end - start; + start = startParam; + length = end - start; } } if (argCount == 2) { @@ -571,17 +708,18 @@ static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } double endParam = AS_NUMBER(args[2]); - if(endParam > buffer->size){ - return newResultError(vm, "end greater then buffer length"); + if (endParam > buffer->size) { + return newResultError(vm, "end greater then buffer length"); } else { - end = endParam; - length = end - start; + end = endParam; + length = end - start; } } - if(length <= 0){ - return newResultError(vm, "length is 0"); + if (length <= 0) { + return newResultError(vm, "length is 0"); } - return newResultSuccess(vm, OBJ_VAL(copyString(vm, (const char*)buffer->bytes+start, length))); + return newResultSuccess( + vm, OBJ_VAL(copyString(vm, (const char *)buffer->bytes + start, length))); } static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { @@ -596,10 +734,10 @@ static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { } double startParam = AS_NUMBER(args[1]); if (startParam >= buffer->size) { - return newResultError(vm, "start greater or equals then buffer length"); + return newResultError(vm, "start greater or equals then buffer length"); } else { - start = startParam; - length = end - start; + start = startParam; + length = end - start; } } if (argCount == 2) { @@ -608,19 +746,19 @@ static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } double endParam = AS_NUMBER(args[2]); - if(endParam > buffer->size){ - return newResultError(vm, "end greater then buffer length"); + if (endParam > buffer->size) { + return newResultError(vm, "end greater then buffer length"); } else { - end = endParam; - length = end - start; + end = endParam; + length = end - start; } } - if(length <= 0){ - return newResultError(vm, "length is 0"); + if (length <= 0) { + return newResultError(vm, "length is 0"); } - ObjAbstract* newBuffer = newBufferObj(vm, length); - Buffer* nb = (Buffer *)newBuffer->data; - for(int i = 0; i < length; i++){ + ObjAbstract *newBuffer = newBufferObj(vm, length); + Buffer *nb = (Buffer *)newBuffer->data; + for (int i = 0; i < length; i++) { nb->bytes[i] = buffer->bytes[start + i]; } return newResultSuccess(vm, OBJ_VAL(newBuffer)); @@ -631,6 +769,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { push(vm, OBJ_VAL(abstract)); Buffer *buffer = ALLOCATE(vm, Buffer, 1); + buffer->bigEndian = false; buffer->bytes = calloc(1, capacity); buffer->size = capacity; @@ -644,7 +783,6 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "string", bufferString); defineNative(vm, &abstract->values, "len", bufferLen); - defineNative(vm, &abstract->values, "writeString", bufferWriteString); defineNative(vm, &abstract->values, "readString", bufferReadString); @@ -669,6 +807,25 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); + defineNative(vm, &abstract->values, "readUInt64BE", bufferReadUint64BE); + defineNative(vm, &abstract->values, "readUInt32BE", bufferReadUint32BE); + defineNative(vm, &abstract->values, "readUInt16BE", bufferReadUint16BE); + defineNative(vm, &abstract->values, "readInt64BE", bufferReadint64BE); + defineNative(vm, &abstract->values, "readInt32BE", bufferReadint32BE); + defineNative(vm, &abstract->values, "readInt16BE", bufferReadint16BE); + + defineNative(vm, &abstract->values, "readFloatBE", bufferReadfloat32BE); + defineNative(vm, &abstract->values, "readDoubleBE", bufferReadfloat64BE); + + defineNative(vm, &abstract->values, "writeUInt64BE", bufferWriteUint64BE); + defineNative(vm, &abstract->values, "writeUInt32BE", bufferWriteUint32BE); + defineNative(vm, &abstract->values, "writeUInt16BE", bufferWriteUint16BE); + defineNative(vm, &abstract->values, "writeInt64BE", bufferWriteint64BE); + defineNative(vm, &abstract->values, "writeInt32BE", bufferWriteint32BE); + defineNative(vm, &abstract->values, "writeInt16BE", bufferWriteint16BE); + + defineNative(vm, &abstract->values, "writeFloatBE", bufferWritefloat32BE); + defineNative(vm, &abstract->values, "writeDoubleBE", bufferWritefloat64BE); abstract->data = buffer; abstract->grayFunc = grayBuffer; @@ -690,7 +847,8 @@ static Value newBuffer(DictuVM *vm, int argCount, Value *args) { double capacity = AS_NUMBER(args[0]); if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { - return newResultError(vm, "capacity must be greater than 0 and less then 2147483647"); + return newResultError( + vm, "capacity must be greater than 0 and less then 2147483647"); } return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); @@ -707,26 +865,23 @@ static Value newBufferFromString(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - ObjString* str = AS_STRING(args[0]); + ObjString *str = AS_STRING(args[0]); if (str->length <= 0) { return newResultError(vm, "string length needs to be greater then 0"); } - ObjAbstract* b = newBufferObj(vm, str->length); - Buffer* buffer = (Buffer*) b->data; + ObjAbstract *b = newBufferObj(vm, str->length); + Buffer *buffer = (Buffer *)b->data; memcpy(buffer->bytes, str->chars, str->length); return newResultSuccess(vm, OBJ_VAL(b)); } - Value createBufferModule(DictuVM *vm) { ObjString *name = copyString(vm, "Buffer", 6); push(vm, OBJ_VAL(name)); ObjModule *module = newModule(vm, name); push(vm, OBJ_VAL(module)); - /** - * Define Buffer methods - */ + defineNative(vm, &module->values, "new", newBuffer); defineNative(vm, &module->values, "fromString", newBufferFromString); diff --git a/src/optionals/buffer.h b/src/optionals/buffer.h index ed2cfdad6..cc566fc92 100644 --- a/src/optionals/buffer.h +++ b/src/optionals/buffer.h @@ -6,9 +6,12 @@ #include "optionals.h" #include "../vm/vm.h" +#include #define BUFFER_SIZE_MAX 2147483647 +#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1}) + Value createBufferModule(DictuVM *vm); #endif //dictu_math_h \ No newline at end of file From fa04753c19785841119db7b0484aa119dfedf14b Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 24 Jan 2024 19:59:01 +0100 Subject: [PATCH 085/148] uodate function names --- docs/docs/standard-lib/buffer.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 1ce4e6b92..0372428ec 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -290,7 +290,7 @@ Writes a u64(unsigned 8 byte integer in big endian) at the index(the first argum Returns a result with the set value or a error. ```cs const buffer = Buffer.new(8).unwrap(); -buffer.writeUInt64LE(0, 12000); +buffer.writeUInt64BE(0, 12000); ``` ### Buffer.writeUInt32BE(Number, Number) -> Result\ @@ -299,7 +299,7 @@ Writes a u32(unsigned 4 byte integer in big endian) at the index(the first argum Returns a result with the set value or a error. ```cs const buffer = Buffer.new(4).unwrap(); -buffer.writeUInt32LE(0, 1337); +buffer.writeUInt32BE(0, 1337); ``` ### Buffer.writeUInt16BE(Number, Number) -> Result\ @@ -308,7 +308,7 @@ Writes a u16(unsigned 2 byte integer in big endian) at the index(the first argum Returns a result with the set value or a error. ```cs const buffer = Buffer.new(2).unwrap(); -buffer.writeUInt16LE(0, 1337); +buffer.writeUInt16BE(0, 1337); ``` ### Buffer.writeInt64BE(Number, Number) -> Result\ @@ -317,7 +317,7 @@ Writes a i64(signed 8 byte integer in big endian) at the index(the first argumen Returns a result with the set value or a error. ```cs const buffer = Buffer.new(8).unwrap(); -buffer.writeInt64LE(0, 12000); +buffer.writeInt64BE(0, 12000); ``` ### Buffer.writeInt32BE(Number, Number) -> Result\ @@ -326,7 +326,7 @@ Writes a i32(signed 4 byte integer in big endian) at the index(the first argumen Returns a result with the set value or a error. ```cs const buffer = Buffer.new(4).unwrap(); -buffer.writeInt32LE(0, 1337); +buffer.writeInt32BE(0, 1337); ``` ### Buffer.writeInt16BE(Number, Number) -> Result\ @@ -335,7 +335,7 @@ Writes a i16(signed 2 byte integer in big endian) at the index(the first argumen Returns a result with the set value or a error. ```cs const buffer = Buffer.new(2).unwrap(); -buffer.writeInt16LE(0, 1337); +buffer.writeInt16BE(0, 1337); ``` ### Buffer.writeFloatBE(Number, Number) -> Result\ @@ -344,7 +344,7 @@ Writes a float(4 byte signed floating point number in big endian) at the index(t Returns a result with the set value or a error. ```cs const buffer = Buffer.new(4).unwrap(); -buffer.writeFloatLE(0, 14.34); +buffer.writeFloatBE(0, 14.34); ``` ### Buffer.writeDoubleBE(Number, Number) -> Result\ @@ -353,7 +353,7 @@ Writes a double(8 byte signed floating point number in big endian) at the index( Returns a result with the set value or a error. ```cs const buffer = Buffer.new(8).unwrap(); -buffer.writeDoubleLE(0, 14.34); +buffer.writeDoubleBE(0, 14.34); ``` ### Buffer.readFloatBE(Number) -> Result\ @@ -363,8 +363,8 @@ Returns a result with the value or a error. ```cs const buffer = Buffer.new(4).unwrap(); -buffer.writeFloatLE(0, 14.34); -print(buffer.readFloatLE(0).unwrap()) // 14.34 +buffer.writeFloatBE(0, 14.34); +print(buffer.readFloatBE(0).unwrap()) // 14.34 ``` ### Buffer.readDoubleBE(Number) -> Result\ @@ -374,6 +374,6 @@ Returns a result with the value or a error. ```cs const buffer = Buffer.new(8).unwrap(); -buffer.writeDoubleLE(0, 14.34); -print(buffer.readDoubleLE(0).unwrap()) // 14.34 +buffer.writeDoubleBE(0, 14.34); +print(buffer.readDoubleBE(0).unwrap()) // 14.34 ``` \ No newline at end of file From aa79e7179f85d439a4f67352e98de2184363b7ab Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 24 Jan 2024 22:14:55 +0100 Subject: [PATCH 086/148] refactor: fix messages to adjust for big endian functions --- src/optionals/buffer.c | 178 +++++++++++++++++++++++++++-------------- src/optionals/buffer.h | 3 +- 2 files changed, 121 insertions(+), 60 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 5dec032e3..ea76e7a9f 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -125,18 +125,23 @@ static Value bufferString(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeUInt16LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeUInt16BE() takes 2 argument" + : "writeUInt16LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUInt16LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt16BE() index argument must be a number" + : "writeUInt16LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUInt16LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt16BE() value argument must be a number" + : "writeUInt16LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -153,18 +158,23 @@ static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeUInt32LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeUInt32BE() takes 2 argument" + : "writeUInt32LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUInt32LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt32BE() index argument must be a number" + : "writeUInt32LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUInt32LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt32BE() value argument must be a number" + : "writeUInt32LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -180,18 +190,23 @@ static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeUInt64LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeUInt64BE() takes 2 argument" + : "writeUInt64LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeUInt64LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt64BE() index argument must be a number" + : "writeUInt64LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeUInt64LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeUInt64BE() value argument must be a number" + : "writeUInt64LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -207,18 +222,23 @@ static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeInt64LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeInt64BE() takes 2 argument" + : "writeInt64LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeInt64LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt64BE() index argument must be a number" + : "writeInt64LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeInt64LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt64BE() value argument must be a number" + : "writeInt64LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -233,18 +253,23 @@ static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeInt32LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeInt32BE() takes 2 argument" + : "writeInt32LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeInt32LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt32BE() index argument must be a number" + : "writeInt32LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeInt32LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt32BE() value argument must be a number" + : "writeInt32LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -260,18 +285,23 @@ static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeInt16LE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeInt16BE() takes 2 argument" + : "writeInt16LE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeInt16LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt16BE() index argument must be a number" + : "writeInt16LE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeInt16LE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeInt16BE() value argument must be a number" + : "writeInt16LE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -287,18 +317,23 @@ static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeFloatLE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeFloatBE() takes 2 argument" + : "writeFloatLE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeFloatLE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeFloatBE() index argument must be a number" + : "writeFloatLE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeFloatLE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeFloatBE() value argument must be a number" + : "writeFloatLE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -314,18 +349,23 @@ static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { - runtimeError(vm, "writeDoubleLE() takes 2 argument"); + runtimeError(vm, buffer->bigEndian ? "writeDoubleBE() takes 2 argument" + : "writeDoubleLE() takes 2 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeDoubleLE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeDoubleBE() index argument must be a number" + : "writeDoubleLE() index argument must be a number"); return EMPTY_VAL; } if (!IS_NUMBER(args[2])) { - runtimeError(vm, "writeDoubleLE() value argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "writeDoubleBE() value argument must be a number" + : "writeDoubleLE() value argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -342,14 +382,17 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readDoubleLE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readDoubleBE() takes 1 argument" + : "readDoubleLE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readDoubleLE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readDoubleBE() index argument must be a number" + : "readDoubleLE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -365,14 +408,17 @@ static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readFloatLE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readFloatBE() takes 1 argument" + : "readFloatLE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readFloatLE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readFloatBE() index argument must be a number" + : "readFloatLE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -387,14 +433,17 @@ static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readUInt64LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readUInt64BE() takes 1 argument" + : "readUInt64LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUInt64LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readUInt64BE() index argument must be a number" + : "readUInt64LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -412,14 +461,17 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readUInt32LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readUInt32BE() takes 1 argument" + : "readUInt32LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUInt32LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readUInt32BE() index argument must be a number" + : "readUInt32LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -433,14 +485,17 @@ static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readUInt16LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readUInt16BE() takes 1 argument" + : "readUInt16LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readUInt16LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readUInt16BE() index argument must be a number" + : "readUInt16LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -455,14 +510,17 @@ static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readInt64LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readInt64BE() takes 1 argument" + : "readInt64LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt64LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readInt64BE() index argument must be a number" + : "readInt64LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -479,14 +537,17 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readInt32LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readInt32BE() takes 1 argument" + : "readInt32LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt32LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readInt32BE() index argument must be a number" + : "readInt32LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -501,14 +562,17 @@ static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { } static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 1) { - runtimeError(vm, "readInt16LE() takes 1 argument"); + runtimeError(vm, buffer->bigEndian ? "readInt16BE() takes 1 argument" + : "readInt16LE() takes 1 argument"); return EMPTY_VAL; } - Buffer *buffer = AS_BUFFER(args[0]); if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readInt16LE() index argument must be a number"); + runtimeError(vm, buffer->bigEndian + ? "readInt16BE() index argument must be a number" + : "readInt16LE() index argument must be a number"); return EMPTY_VAL; } double index = AS_NUMBER(args[1]); @@ -806,7 +870,6 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "writeFloatLE", bufferWritefloat32LE); defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); - defineNative(vm, &abstract->values, "readUInt64BE", bufferReadUint64BE); defineNative(vm, &abstract->values, "readUInt32BE", bufferReadUint32BE); defineNative(vm, &abstract->values, "readUInt16BE", bufferReadUint16BE); @@ -881,7 +944,6 @@ Value createBufferModule(DictuVM *vm) { ObjModule *module = newModule(vm, name); push(vm, OBJ_VAL(module)); - defineNative(vm, &module->values, "new", newBuffer); defineNative(vm, &module->values, "fromString", newBufferFromString); diff --git a/src/optionals/buffer.h b/src/optionals/buffer.h index cc566fc92..376e2713a 100644 --- a/src/optionals/buffer.h +++ b/src/optionals/buffer.h @@ -2,7 +2,6 @@ #define dictu_buffer_h #include -#include #include "optionals.h" #include "../vm/vm.h" @@ -14,4 +13,4 @@ Value createBufferModule(DictuVM *vm); -#endif //dictu_math_h \ No newline at end of file +#endif //dictu_buffer_h \ No newline at end of file From 9d66d98d1fbcebdab8b6b495c9f070fcfb640ac9 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 24 Jan 2024 22:38:11 +0100 Subject: [PATCH 087/148] fix: thiis was reversed --- src/optionals/buffer.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index ea76e7a9f..14861c131 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -36,16 +36,11 @@ void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { uint8_t *swap(uint8_t *ptr, size_t len, bool bigEndian) { if (len < 2) return ptr; - if (!bigEndian) { -#ifdef IS_BIG_ENDIAN -#else + if (!bigEndian && !IS_BIG_ENDIAN) { return ptr; -#endif - } else { -#ifndef IS_BIG_ENDIAN -#else + } else if(IS_BIG_ENDIAN && bigEndian) { + return ptr; -#endif } int start = 0; int end = (len)-1; From 205f995b648e96b5b4f4df603b21439b564a4e76 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Wed, 24 Jan 2024 14:52:56 -0700 Subject: [PATCH 088/148] add pretty print to object mod Signed-off-by: Brian Downs --- src/optionals/json.c | 2 +- src/optionals/json.h | 1 + src/optionals/object/object.c | 16 ++++++++++++++++ src/optionals/object/object.h | 1 + tests/object/import.du | 1 + tests/object/prettyPrint.du | 30 ++++++++++++++++++++++++++++++ 6 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/object/prettyPrint.du diff --git a/src/optionals/json.c b/src/optionals/json.c index a711e7dbb..63c0691bc 100644 --- a/src/optionals/json.c +++ b/src/optionals/json.c @@ -171,7 +171,7 @@ json_value* stringifyJson(DictuVM *vm, Value value) { return NULL; } -static Value stringify(DictuVM *vm, int argCount, Value *args) { +Value stringify(DictuVM *vm, int argCount, Value *args) { if (argCount != 1 && argCount != 2) { runtimeError(vm, "stringify() takes 1 or 2 arguments (%d given).", argCount); return EMPTY_VAL; diff --git a/src/optionals/json.h b/src/optionals/json.h index 02697a793..0b9b8f328 100644 --- a/src/optionals/json.h +++ b/src/optionals/json.h @@ -7,5 +7,6 @@ #include "../vm/vm.h" Value createJSONModule(DictuVM *vm); +Value stringify(DictuVM *vm, int argCount, Value *args); #endif //dictu_json_h diff --git a/src/optionals/object/object.c b/src/optionals/object/object.c index ea5791eb1..471a1923f 100644 --- a/src/optionals/object/object.c +++ b/src/optionals/object/object.c @@ -59,7 +59,21 @@ static Value objectHash(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(copyString(vm, (char *)str, 21)); } +static Value objectPrettyPrint(DictuVM *vm, int argCount, Value *args) { + if (argCount != 1 && argCount != 2) { + runtimeError(vm, "prettyPrint() takes 1 or arguments (%d given)", argCount); + return EMPTY_VAL; + } + + return OBJ_VAL(stringify(vm, argCount, args)); +} + Value createObjectModule(DictuVM *vm) { + ObjString *name = copyString(vm, "Object", 6); + push(vm, OBJ_VAL(name)); + ObjModule *module = newModule(vm, name); + push(vm, OBJ_VAL(module)); + ObjClosure *closure = compileModuleToClosure(vm, "Object", DICTU_OBJECT_SOURCE); if (closure == NULL) { @@ -75,6 +89,8 @@ Value createObjectModule(DictuVM *vm) { defineNative(vm, &closure->function->module->values, "getClassRef", objectGetClassRef); defineNative(vm, &closure->function->module->values, "hash", objectHash); + defineNative(vm, &module->values, "prettyPrint", objectPrettyPrint); + pop(vm); return OBJ_VAL(closure); diff --git a/src/optionals/object/object.h b/src/optionals/object/object.h index c8384cf80..3d66276cb 100644 --- a/src/optionals/object/object.h +++ b/src/optionals/object/object.h @@ -5,6 +5,7 @@ #include "../optionals.h" #include "../../vm/vm.h" +#include "../json.h" Value createObjectModule(DictuVM *vm); diff --git a/tests/object/import.du b/tests/object/import.du index 3780daa58..7b2f11606 100644 --- a/tests/object/import.du +++ b/tests/object/import.du @@ -6,3 +6,4 @@ import "createFrom.du"; import "hash.du"; +import "prettyPrint"; diff --git a/tests/object/prettyPrint.du b/tests/object/prettyPrint.du new file mode 100644 index 000000000..9f999459a --- /dev/null +++ b/tests/object/prettyPrint.du @@ -0,0 +1,30 @@ +/** + * prettyPrint.du + * + * Testing the Object.prettyPrint method + */ +from UnitTest import UnitTest; + +import Object; + +class Test {} + +class TestObjectPrettyPrint < UnitTest { + testObjectPrettyPrint() { + this.assertEquals(Object.prettyPrint(1).unwrap(), "1"); + this.assertEquals(Object.prettyPrint("1").unwrap(), '"1"'); + this.assertEquals(Object.prettyPrint([1, 2, 3]).unwrap(), '[1, 2, 3]'); + this.assertEquals(Object.prettyPrint({"a": 1}).unwrap(), '{"a": 1}'); + this.assertEquals(Object.prettyPrint(nil).unwrap(), 'null'); + this.assertEquals(Object.prettyPrint(true).unwrap(), 'true'); + this.assertEquals(Object.prettyPrint(false).unwrap(), 'false'); + this.assertError(Object.prettyPrint(Test())); + } + + testObjectPrettyPrintWithIndent() { + this.assertEquals(Object.prettyPrint([1, 2, 3], 2).unwrap(), '[\n 1,\n 2,\n 3\n]'); + this.assertEquals(Object.prettyPrint({"a": 1}, 2).unwrap(), '{\n "a": 1\n}'); + } +} + +TestObjectPrettyPrint().run(); From b38fef9160cf750dd3b63e7e2a094b196e720027 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Wed, 24 Jan 2024 16:33:42 -0700 Subject: [PATCH 089/148] add docs, fix test typo Signed-off-by: Brian Downs --- docs/docs/standard-lib/object.md | 24 ++++++++++++++++++++++++ tests/object/import.du | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/docs/standard-lib/object.md b/docs/docs/standard-lib/object.md index dc5cbaf9c..fd0441206 100644 --- a/docs/docs/standard-lib/object.md +++ b/docs/docs/standard-lib/object.md @@ -61,3 +61,27 @@ This method will return a string of the object's hash value. ```cs Object.hash("Dictu"); ``` + +### Object.prettyPrint(Value, indent -> Optional) -> Result\ + +This method will return a string representation of the given value. + +**NOTE** Strings, dicts, lists, numbers, and nil are valid values for pretty printing at this time. + +```cs +Object.prettyPrint([1, 2, 3]).unwrap(); + +// Output +'[1, 2, 3]' +``` + +```cs +Object.prettyPrint({"a": 1}, 4).unwrap() + +// Output +' +{ + "a": 1 +} +' +``` diff --git a/tests/object/import.du b/tests/object/import.du index 7b2f11606..30c20717d 100644 --- a/tests/object/import.du +++ b/tests/object/import.du @@ -6,4 +6,4 @@ import "createFrom.du"; import "hash.du"; -import "prettyPrint"; +import "prettyPrint.du"; From ad205883c9f60a17f98a361811b021be113dbfde Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Wed, 24 Jan 2024 16:40:46 -0700 Subject: [PATCH 090/148] remove unneeded file Signed-off-by: Brian Downs --- dmi.db | Bin 20480 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dmi.db diff --git a/dmi.db b/dmi.db deleted file mode 100644 index 4ac664aa16d6d44e6394bb4a0563ed549e7e2a07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20480 zcmeI#K~EY%6u|LaK{?TS<6uml^@5S~;-!ffR~QYEU2z$bk{-y`9g~fK3g{jC1^a!x z^nnk?iO`5Up(q&uV&(t%s%}*F(2DsYjm$?S_?VJC1c{clyhg4Z>zcQrB}UXBG06+%u*UX^t8C` zj@-ke8(h1UVQwk4mBm?h72SC-`QaBzJ3Icb;w#f-t=%xK@b$5=bjEyA%Bj0|gH-=B zbE7%Sg4UB8j Date: Thu, 25 Jan 2024 09:59:34 -0700 Subject: [PATCH 091/148] extend sleep longer Signed-off-by: Brian Downs --- tests/process/kill.du | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/process/kill.du b/tests/process/kill.du index 2328522cb..c15162be2 100644 --- a/tests/process/kill.du +++ b/tests/process/kill.du @@ -18,7 +18,7 @@ class TestProcessKill < UnitTest { } testProcessKillNoSignal() { - Process.exec(["sleep", "100"]); + Process.exec(["sleep", "3600"]); const out = Process.run(["pgrep", "sleep"], true).unwrap(); const pids = out.split("\n"); From 9fa05670fb55a52c1f597b81378d070f3729f06a Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 25 Jan 2024 19:58:34 +0100 Subject: [PATCH 092/148] feat: add clang format, buffer.values() and Tests --- .clang-format | 2 + docs/docs/standard-lib/buffer.md | 10 + src/optionals/buffer.c | 1462 +++++++++++++++--------------- tests/buffer/allocate.du | 27 + tests/buffer/get.du | 32 + tests/buffer/import.du | 15 + tests/buffer/integers.du | 58 ++ tests/buffer/resize.du | 36 + tests/buffer/set.du | 33 + tests/buffer/string.du | 19 + tests/buffer/stringFuncs.du | 49 + tests/buffer/subarray.du | 46 + tests/runTests.du | 1 + 13 files changed, 1083 insertions(+), 707 deletions(-) create mode 100644 .clang-format create mode 100644 tests/buffer/allocate.du create mode 100644 tests/buffer/get.du create mode 100644 tests/buffer/import.du create mode 100644 tests/buffer/integers.du create mode 100644 tests/buffer/resize.du create mode 100644 tests/buffer/set.du create mode 100644 tests/buffer/string.du create mode 100644 tests/buffer/stringFuncs.du create mode 100644 tests/buffer/subarray.du diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..ae03cfa57 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +IndentWidth: 4 +AccessModifierOffset: -4 \ No newline at end of file diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 0372428ec..59ab4712f 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -104,6 +104,16 @@ const len = buffer.len(); print(len); // 9 ``` +### Buffer.values() -> List + +Returns a list with the integer values of the buffer. +```cs +const buffer = Buffer.fromString("Dictu!").unwrap(); +const v = buffer.values(); +print(v); // [68, 105, 99, 116, 117, 33] +``` + + ### Buffer.writeString(Number, String) -> Result\ Sets a string into buffer given the starting index, if the string doesn't fit in the buffer a error is returned. diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 14861c131..23f7acf66 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -2,9 +2,9 @@ #include typedef struct { - uint8_t *bytes; - int size; - bool bigEndian; + uint8_t *bytes; + int size; + bool bigEndian; } Buffer; #define AS_BUFFER(v) ((Buffer *)AS_ABSTRACT(v)->data) @@ -12,938 +12,986 @@ typedef struct { ObjAbstract *newBufferObj(DictuVM *vm, double capacity); void freeBuffer(DictuVM *vm, ObjAbstract *abstract) { - Buffer *buffer = (Buffer *)abstract->data; - free(buffer->bytes); - FREE(vm, Buffer, abstract->data); + Buffer *buffer = (Buffer *)abstract->data; + free(buffer->bytes); + FREE(vm, Buffer, abstract->data); } char *bufferToString(ObjAbstract *abstract) { - UNUSED(abstract); + UNUSED(abstract); - char *bufferString = malloc(sizeof(char) * 9); - snprintf(bufferString, 9, ""); - return bufferString; + char *bufferString = malloc(sizeof(char) * 9); + snprintf(bufferString, 9, ""); + return bufferString; } void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { - (void)vm; - Buffer *ffi = (Buffer *)abstract->data; + (void)vm; + Buffer *ffi = (Buffer *)abstract->data; - if (ffi == NULL) - return; + if (ffi == NULL) + return; } uint8_t *swap(uint8_t *ptr, size_t len, bool bigEndian) { - if (len < 2) - return ptr; - if (!bigEndian && !IS_BIG_ENDIAN) { - return ptr; - } else if(IS_BIG_ENDIAN && bigEndian) { + if (len < 2) + return ptr; + if (!bigEndian && !IS_BIG_ENDIAN) { + return ptr; + } else if (IS_BIG_ENDIAN && bigEndian) { + return ptr; + } + int start = 0; + int end = (len)-1; + uint8_t temp; + while (start < end) { + temp = ptr[start]; + ptr[start] = ptr[end]; + ptr[end] = temp; + start++; + end--; + } return ptr; - } - int start = 0; - int end = (len)-1; - uint8_t temp; - while (start < end) { - temp = ptr[start]; - ptr[start] = ptr[end]; - ptr[end] = temp; - start++; - end--; - } - return ptr; } bool ensureSize(Buffer *buffer, size_t offset, size_t size) { - return buffer->size - offset >= size; + return buffer->size - offset >= size; } bool writeInternal(Buffer *buffer, size_t offset, uint8_t *data, size_t len) { - if (!ensureSize(buffer, offset, len)) - return false; - memcpy(buffer->bytes + offset, data, len); - return true; + if (!ensureSize(buffer, offset, len)) + return false; + memcpy(buffer->bytes + offset, data, len); + return true; } uint8_t *getReadPtr(Buffer *buffer, size_t offset, size_t len) { - if (!ensureSize(buffer, offset, len)) - return NULL; - return buffer->bytes + offset; + if (!ensureSize(buffer, offset, len)) + return NULL; + return buffer->bytes + offset; } static Value bufferResize(DictuVM *vm, int argCount, Value *args) { - if (argCount != 1) { - runtimeError(vm, "resize() takes 1 argument (%d given).", argCount); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "resize() size argument must be a number"); - return EMPTY_VAL; - } - - double capacity = AS_NUMBER(args[1]); - if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { - return newResultError( - vm, "size must be greater than 0 and smaller then 2147483647"); - } - Buffer *buffer = AS_BUFFER(args[0]); - buffer->bytes = realloc(buffer->bytes, capacity); - if (capacity > buffer->size) { - // 0 init everything if we grew the buffer - size_t added = capacity - buffer->size; - memset(buffer->bytes + buffer->size, 0, added); - } - buffer->size = capacity; - return newResultSuccess(vm, args[0]); + if (argCount != 1) { + runtimeError(vm, "resize() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "resize() size argument must be a number"); + return EMPTY_VAL; + } + + double capacity = AS_NUMBER(args[1]); + if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { + return newResultError( + vm, "size must be greater than 0 and smaller then 2147483647"); + } + Buffer *buffer = AS_BUFFER(args[0]); + buffer->bytes = realloc(buffer->bytes, capacity); + if (capacity > buffer->size) { + // 0 init everything if we grew the buffer + size_t added = capacity - buffer->size; + memset(buffer->bytes + buffer->size, 0, added); + } + buffer->size = capacity; + return newResultSuccess(vm, args[0]); } static Value bufferLen(DictuVM *vm, int argCount, Value *args) { - if (argCount != 0) { - runtimeError(vm, "len() takes no arguments"); - return EMPTY_VAL; - } - Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 0) { + runtimeError(vm, "len() takes no arguments"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); - return NUMBER_VAL(buffer->size); + return NUMBER_VAL(buffer->size); +} + +static Value bufferValues(DictuVM *vm, int argCount, Value *args) { + if (argCount != 0) { + runtimeError(vm, "values() takes no arguments"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); + ObjList *list = newList(vm); + push(vm, OBJ_VAL(list)); + + for (int i = 0; i < buffer->size; ++i) { + writeValueArray(vm, &list->values, NUMBER_VAL(buffer->bytes[i])); + } + pop(vm); + return OBJ_VAL(list); } static Value bufferString(DictuVM *vm, int argCount, Value *args) { - if (argCount != 0) { - runtimeError(vm, "string() takes no arguments"); - return EMPTY_VAL; - } - Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 0) { + runtimeError(vm, "string() takes no arguments"); + return EMPTY_VAL; + } + Buffer *buffer = AS_BUFFER(args[0]); - return OBJ_VAL(copyString(vm, (const char *)buffer->bytes, buffer->size)); + return OBJ_VAL(copyString(vm, (const char *)buffer->bytes, buffer->size)); } static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeUInt16BE() takes 2 argument" - : "writeUInt16LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian + ? "writeUInt16BE() takes 2 argument" + : "writeUInt16LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt16BE() index argument must be a number" : "writeUInt16LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt16BE() value argument must be a number" : "writeUInt16LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - uint16_t correctVal = (uint16_t)value; + uint16_t correctVal = (uint16_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeUInt32BE() takes 2 argument" - : "writeUInt32LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian + ? "writeUInt32BE() takes 2 argument" + : "writeUInt32LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt32BE() index argument must be a number" : "writeUInt32LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt32BE() value argument must be a number" : "writeUInt32LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - uint32_t correctVal = (uint32_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + uint32_t correctVal = (uint32_t)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeUInt64BE() takes 2 argument" - : "writeUInt64LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian + ? "writeUInt64BE() takes 2 argument" + : "writeUInt64LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt64BE() index argument must be a number" : "writeUInt64LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeUInt64BE() value argument must be a number" : "writeUInt64LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - uint64_t correctVal = (uint64_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + uint64_t correctVal = (uint64_t)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeInt64BE() takes 2 argument" - : "writeInt64LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian ? "writeInt64BE() takes 2 argument" + : "writeInt64LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt64BE() index argument must be a number" : "writeInt64LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt64BE() value argument must be a number" : "writeInt64LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); - int64_t correctVal = (int64_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + int64_t correctVal = (int64_t)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeInt32BE() takes 2 argument" - : "writeInt32LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian ? "writeInt32BE() takes 2 argument" + : "writeInt32LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt32BE() index argument must be a number" : "writeInt32LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt32BE() value argument must be a number" : "writeInt32LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - int32_t correctVal = (int32_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + int32_t correctVal = (int32_t)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeInt16BE() takes 2 argument" - : "writeInt16LE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian ? "writeInt16BE() takes 2 argument" + : "writeInt16LE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt16BE() index argument must be a number" : "writeInt16LE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeInt16BE() value argument must be a number" : "writeInt16LE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - int16_t correctVal = (int16_t)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + int16_t correctVal = (int16_t)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeFloatBE() takes 2 argument" - : "writeFloatLE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian ? "writeFloatBE() takes 2 argument" + : "writeFloatLE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeFloatBE() index argument must be a number" : "writeFloatLE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeFloatBE() value argument must be a number" : "writeFloatLE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - float correctVal = (float)value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + float correctVal = (float)value; + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 2) { - runtimeError(vm, buffer->bigEndian ? "writeDoubleBE() takes 2 argument" - : "writeDoubleLE() takes 2 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, buffer->bigEndian + ? "writeDoubleBE() takes 2 argument" + : "writeDoubleLE() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "writeDoubleBE() index argument must be a number" : "writeDoubleLE() index argument must be a number"); - return EMPTY_VAL; - } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, buffer->bigEndian + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + buffer->bigEndian ? "writeDoubleBE() value argument must be a number" : "writeDoubleLE() value argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); - double correctVal = value; + double correctVal = value; - if (!writeInternal( - buffer, index, - swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), - sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); - return newResultSuccess(vm, NUMBER_VAL(correctVal)); + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readDoubleBE() takes 1 argument" - : "readDoubleLE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readDoubleBE() takes 1 argument" + : "readDoubleLE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "readDoubleBE() index argument must be a number" : "readDoubleLE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - double value; + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readFloatBE() takes 1 argument" - : "readFloatLE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian - ? "readFloatBE() index argument must be a number" - : "readFloatLE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - float value; - - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readFloatBE() takes 1 argument" + : "readFloatLE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, buffer->bigEndian + ? "readFloatBE() index argument must be a number" + : "readFloatLE() index argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + float value; + + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readUInt64BE() takes 1 argument" - : "readUInt64LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readUInt64BE() takes 1 argument" + : "readUInt64LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "readUInt64BE() index argument must be a number" : "readUInt64LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - uint64_t value; - - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); - memcpy(&value, ptr, sizeof(value)); - const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if (value > MAX_VALUE) - return newResultError(vm, "value would overflow internal representation"); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + uint64_t value; + + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); + memcpy(&value, ptr, sizeof(value)); + const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; + if (value > MAX_VALUE) + return newResultError(vm, + "value would overflow internal representation"); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readUInt32BE() takes 1 argument" - : "readUInt32LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readUInt32BE() takes 1 argument" + : "readUInt32LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "readUInt32BE() index argument must be a number" : "readUInt32LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - uint32_t value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + uint32_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readUInt16BE() takes 1 argument" - : "readUInt16LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readUInt16BE() takes 1 argument" + : "readUInt16LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + buffer->bigEndian ? "readUInt16BE() index argument must be a number" : "readUInt16LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); - uint16_t value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + uint16_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readInt64BE() takes 1 argument" - : "readInt64LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian - ? "readInt64BE() index argument must be a number" - : "readInt64LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - int64_t value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); - memcpy(&value, ptr, sizeof(value)); - const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if ((uint64_t)value > MAX_VALUE) - return newResultError(vm, "value would overflow internal representation"); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readInt64BE() takes 1 argument" + : "readInt64LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, buffer->bigEndian + ? "readInt64BE() index argument must be a number" + : "readInt64LE() index argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + int64_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 8"); + memcpy(&value, ptr, sizeof(value)); + const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; + if ((uint64_t)value > MAX_VALUE) + return newResultError(vm, + "value would overflow internal representation"); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readInt32BE() takes 1 argument" - : "readInt32LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian - ? "readInt32BE() index argument must be a number" - : "readInt32LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - - int32_t value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readInt32BE() takes 1 argument" + : "readInt32LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, buffer->bigEndian + ? "readInt32BE() index argument must be a number" + : "readInt32LE() index argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + + int32_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 4"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - if (argCount != 1) { - runtimeError(vm, buffer->bigEndian ? "readInt16BE() takes 1 argument" - : "readInt16LE() takes 1 argument"); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, buffer->bigEndian - ? "readInt16BE() index argument must be a number" - : "readInt16LE() index argument must be a number"); - return EMPTY_VAL; - } - double index = AS_NUMBER(args[1]); - - int16_t value; - uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); - if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); - memcpy(&value, ptr, sizeof(value)); - swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); - return newResultSuccess(vm, NUMBER_VAL(value)); + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, buffer->bigEndian ? "readInt16BE() takes 1 argument" + : "readInt16LE() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, buffer->bigEndian + ? "readInt16BE() index argument must be a number" + : "readInt16LE() index argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + + int16_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 2"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); } typedef Value buffer_func_t(DictuVM *vm, int argCount, Value *args); // is this hacky? static Value runBigEndian(DictuVM *vm, int argCount, Value *args, buffer_func_t *f) { - Buffer *buffer = AS_BUFFER(args[0]); - buffer->bigEndian = true; - Value result = f(vm, argCount, args); - buffer->bigEndian = false; - return result; + Buffer *buffer = AS_BUFFER(args[0]); + buffer->bigEndian = true; + Value result = f(vm, argCount, args); + buffer->bigEndian = false; + return result; } static Value bufferReadUint64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadUint64LE); + return runBigEndian(vm, argCount, args, &bufferReadUint64LE); } static Value bufferReadUint32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadUint32LE); + return runBigEndian(vm, argCount, args, &bufferReadUint32LE); } static Value bufferReadUint16BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadUint16LE); + return runBigEndian(vm, argCount, args, &bufferReadUint16LE); } static Value bufferReadint64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadint64LE); + return runBigEndian(vm, argCount, args, &bufferReadint64LE); } static Value bufferReadint32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadint32LE); + return runBigEndian(vm, argCount, args, &bufferReadint32LE); } static Value bufferReadint16BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadint16LE); + return runBigEndian(vm, argCount, args, &bufferReadint16LE); } static Value bufferReadfloat32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadfloat32LE); + return runBigEndian(vm, argCount, args, &bufferReadfloat32LE); } static Value bufferReadfloat64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferReadfloat64LE); + return runBigEndian(vm, argCount, args, &bufferReadfloat64LE); } static Value bufferWriteUint64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteUint64LE); + return runBigEndian(vm, argCount, args, &bufferWriteUint64LE); } static Value bufferWriteUint32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteUint32LE); + return runBigEndian(vm, argCount, args, &bufferWriteUint32LE); } static Value bufferWriteUint16BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteUint16LE); + return runBigEndian(vm, argCount, args, &bufferWriteUint16LE); } static Value bufferWriteint64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteint64LE); + return runBigEndian(vm, argCount, args, &bufferWriteint64LE); } static Value bufferWriteint32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteint32LE); + return runBigEndian(vm, argCount, args, &bufferWriteint32LE); } static Value bufferWriteint16BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWriteint16LE); + return runBigEndian(vm, argCount, args, &bufferWriteint16LE); } static Value bufferWritefloat32BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWritefloat32LE); + return runBigEndian(vm, argCount, args, &bufferWritefloat32LE); } static Value bufferWritefloat64BE(DictuVM *vm, int argCount, Value *args) { - return runBigEndian(vm, argCount, args, &bufferWritefloat64LE); + return runBigEndian(vm, argCount, args, &bufferWritefloat64LE); } static Value bufferGet(DictuVM *vm, int argCount, Value *args) { - if (argCount != 1) { - runtimeError(vm, "get() takes 1 argument (%d given).", argCount); - return EMPTY_VAL; - } + if (argCount != 1) { + runtimeError(vm, "get() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "get() argument must be a number"); - return EMPTY_VAL; - } + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "get() argument must be a number"); + return EMPTY_VAL; + } - double index = AS_NUMBER(args[1]); - if (index < 0) { - return newResultError(vm, "index must be greater than -1"); - } - Buffer *buffer = AS_BUFFER(args[0]); - if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); - } + double index = AS_NUMBER(args[1]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } - return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); + return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); } static Value bufferSet(DictuVM *vm, int argCount, Value *args) { - if (argCount != 2) { - runtimeError(vm, "set() takes 2 argument (%d given).", argCount); - return EMPTY_VAL; - } + if (argCount != 2) { + runtimeError(vm, "set() takes 2 argument (%d given).", argCount); + return EMPTY_VAL; + } - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "set() index argument must be a number"); - return EMPTY_VAL; - } + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "set() index argument must be a number"); + return EMPTY_VAL; + } - if (!IS_NUMBER(args[2])) { - runtimeError(vm, "set() value argument must be a number"); - return EMPTY_VAL; - } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "set() value argument must be a number"); + return EMPTY_VAL; + } - double index = AS_NUMBER(args[1]); - double value = AS_NUMBER(args[2]); - if (index < 0) { - return newResultError(vm, "index must be greater than -1"); - } - Buffer *buffer = AS_BUFFER(args[0]); - if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); - } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } - buffer->bytes[(size_t)index] = (uint8_t)value; + buffer->bytes[(size_t)index] = (uint8_t)value; - return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); + return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); } static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { - if (argCount != 2) { - runtimeError(vm, "writeString() takes 2 argument (%d given).", argCount); - return EMPTY_VAL; - } - - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "writeString() index argument must be a number"); - return EMPTY_VAL; - } - - if (!IS_STRING(args[2])) { - runtimeError(vm, "writeString() value argument must be a string"); - return EMPTY_VAL; - } - - double index = AS_NUMBER(args[1]); - ObjString *str = AS_STRING(args[2]); - if (index < 0) { - return newResultError(vm, "index must be greater than -1"); - } - Buffer *buffer = AS_BUFFER(args[0]); - if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); - } - - if (buffer->size - index < str->length) { - return newResultError(vm, "buffer is not large enough to fit the string"); - } - memcpy(buffer->bytes + (size_t)index, str->chars, str->length); - return newResultSuccess(vm, NIL_VAL); + if (argCount != 2) { + runtimeError(vm, "writeString() takes 2 argument (%d given).", + argCount); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "writeString() index argument must be a number"); + return EMPTY_VAL; + } + + if (!IS_STRING(args[2])) { + runtimeError(vm, "writeString() value argument must be a string"); + return EMPTY_VAL; + } + + double index = AS_NUMBER(args[1]); + ObjString *str = AS_STRING(args[2]); + if (index < 0) { + return newResultError(vm, "index must be greater than -1"); + } + Buffer *buffer = AS_BUFFER(args[0]); + if (index >= buffer->size) { + return newResultError(vm, "index must be smaller then buffer size"); + } + + if (buffer->size - index < str->length) { + return newResultError(vm, + "buffer is not large enough to fit the string"); + } + memcpy(buffer->bytes + (size_t)index, str->chars, str->length); + return newResultSuccess(vm, NIL_VAL); } static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - size_t start = 0; - size_t end = buffer->size; - int length = buffer->size; - if (argCount > 0) { - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "readString() start argument must be a number"); - return EMPTY_VAL; - } - double startParam = AS_NUMBER(args[1]); - if (startParam >= buffer->size) { - return newResultError(vm, "start greater or equals then buffer length"); - } else { - start = startParam; - length = end - start; - } - } - if (argCount == 2) { - if (!IS_NUMBER(args[2])) { - runtimeError(vm, "readString() end argument must be a number"); - return EMPTY_VAL; + Buffer *buffer = AS_BUFFER(args[0]); + size_t start = 0; + size_t end = buffer->size; + int length = buffer->size; + if (argCount > 0) { + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readString() start argument must be a number"); + return EMPTY_VAL; + } + double startParam = AS_NUMBER(args[1]); + if (startParam >= buffer->size) { + return newResultError(vm, + "start greater or equals then buffer length"); + } else { + start = startParam; + length = end - start; + } + } + if (argCount == 2) { + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "readString() end argument must be a number"); + return EMPTY_VAL; + } + double endParam = AS_NUMBER(args[2]); + if (endParam > buffer->size) { + return newResultError(vm, "end greater then buffer length"); + } else { + end = endParam; + length = end - start; + } } - double endParam = AS_NUMBER(args[2]); - if (endParam > buffer->size) { - return newResultError(vm, "end greater then buffer length"); - } else { - end = endParam; - length = end - start; + if (length <= 0) { + return newResultError(vm, "string length is 0"); } - } - if (length <= 0) { - return newResultError(vm, "length is 0"); - } - return newResultSuccess( - vm, OBJ_VAL(copyString(vm, (const char *)buffer->bytes + start, length))); + return newResultSuccess( + vm, + OBJ_VAL(copyString(vm, (const char *)buffer->bytes + start, length))); } static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { - Buffer *buffer = AS_BUFFER(args[0]); - size_t start = 0; - size_t end = buffer->size; - int length = buffer->size; - if (argCount > 0) { - if (!IS_NUMBER(args[1])) { - runtimeError(vm, "subarray() start argument must be a number"); - return EMPTY_VAL; - } - double startParam = AS_NUMBER(args[1]); - if (startParam >= buffer->size) { - return newResultError(vm, "start greater or equals then buffer length"); - } else { - start = startParam; - length = end - start; - } - } - if (argCount == 2) { - if (!IS_NUMBER(args[2])) { - runtimeError(vm, "subarray() end argument must be a number"); - return EMPTY_VAL; - } - double endParam = AS_NUMBER(args[2]); - if (endParam > buffer->size) { - return newResultError(vm, "end greater then buffer length"); - } else { - end = endParam; - length = end - start; - } - } - if (length <= 0) { - return newResultError(vm, "length is 0"); - } - ObjAbstract *newBuffer = newBufferObj(vm, length); - Buffer *nb = (Buffer *)newBuffer->data; - for (int i = 0; i < length; i++) { - nb->bytes[i] = buffer->bytes[start + i]; - } - return newResultSuccess(vm, OBJ_VAL(newBuffer)); + Buffer *buffer = AS_BUFFER(args[0]); + size_t start = 0; + size_t end = buffer->size; + int length = buffer->size; + if (argCount > 0) { + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "subarray() start argument must be a number"); + return EMPTY_VAL; + } + double startParam = AS_NUMBER(args[1]); + if (startParam >= buffer->size) { + return newResultError(vm, + "start greater or equals then buffer length"); + } else { + start = startParam; + length = end - start; + } + } + if (argCount == 2) { + if (!IS_NUMBER(args[2])) { + runtimeError(vm, "subarray() end argument must be a number"); + return EMPTY_VAL; + } + double endParam = AS_NUMBER(args[2]); + if (endParam > buffer->size) { + return newResultError(vm, "end greater then buffer length"); + } else { + end = endParam; + length = end - start; + } + } + if (length <= 0) { + return newResultError(vm, "array length is 0"); + } + ObjAbstract *newBuffer = newBufferObj(vm, length); + Buffer *nb = (Buffer *)newBuffer->data; + for (int i = 0; i < length; i++) { + nb->bytes[i] = buffer->bytes[start + i]; + } + return newResultSuccess(vm, OBJ_VAL(newBuffer)); } ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { - ObjAbstract *abstract = newAbstract(vm, freeBuffer, bufferToString); - push(vm, OBJ_VAL(abstract)); - - Buffer *buffer = ALLOCATE(vm, Buffer, 1); - buffer->bigEndian = false; - buffer->bytes = calloc(1, capacity); - buffer->size = capacity; - - /** - * Setup Buffer object methods - */ - defineNative(vm, &abstract->values, "resize", bufferResize); - defineNative(vm, &abstract->values, "set", bufferSet); - defineNative(vm, &abstract->values, "get", bufferGet); - defineNative(vm, &abstract->values, "subarray", bufferSubArray); - defineNative(vm, &abstract->values, "string", bufferString); - defineNative(vm, &abstract->values, "len", bufferLen); - - defineNative(vm, &abstract->values, "writeString", bufferWriteString); - defineNative(vm, &abstract->values, "readString", bufferReadString); - - defineNative(vm, &abstract->values, "readUInt64LE", bufferReadUint64LE); - defineNative(vm, &abstract->values, "readUInt32LE", bufferReadUint32LE); - defineNative(vm, &abstract->values, "readUInt16LE", bufferReadUint16LE); - defineNative(vm, &abstract->values, "readInt64LE", bufferReadint64LE); - defineNative(vm, &abstract->values, "readInt32LE", bufferReadint32LE); - defineNative(vm, &abstract->values, "readInt16LE", bufferReadint16LE); - - defineNative(vm, &abstract->values, "readFloatLE", bufferReadfloat32LE); - defineNative(vm, &abstract->values, "readDoubleLE", bufferReadfloat64LE); - - defineNative(vm, &abstract->values, "writeUInt64LE", bufferWriteUint64LE); - defineNative(vm, &abstract->values, "writeUInt32LE", bufferWriteUint32LE); - defineNative(vm, &abstract->values, "writeUInt16LE", bufferWriteUint16LE); - defineNative(vm, &abstract->values, "writeInt64LE", bufferWriteint64LE); - defineNative(vm, &abstract->values, "writeInt32LE", bufferWriteint32LE); - defineNative(vm, &abstract->values, "writeInt16LE", bufferWriteint16LE); - - defineNative(vm, &abstract->values, "writeFloatLE", bufferWritefloat32LE); - defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); - - defineNative(vm, &abstract->values, "readUInt64BE", bufferReadUint64BE); - defineNative(vm, &abstract->values, "readUInt32BE", bufferReadUint32BE); - defineNative(vm, &abstract->values, "readUInt16BE", bufferReadUint16BE); - defineNative(vm, &abstract->values, "readInt64BE", bufferReadint64BE); - defineNative(vm, &abstract->values, "readInt32BE", bufferReadint32BE); - defineNative(vm, &abstract->values, "readInt16BE", bufferReadint16BE); - - defineNative(vm, &abstract->values, "readFloatBE", bufferReadfloat32BE); - defineNative(vm, &abstract->values, "readDoubleBE", bufferReadfloat64BE); - - defineNative(vm, &abstract->values, "writeUInt64BE", bufferWriteUint64BE); - defineNative(vm, &abstract->values, "writeUInt32BE", bufferWriteUint32BE); - defineNative(vm, &abstract->values, "writeUInt16BE", bufferWriteUint16BE); - defineNative(vm, &abstract->values, "writeInt64BE", bufferWriteint64BE); - defineNative(vm, &abstract->values, "writeInt32BE", bufferWriteint32BE); - defineNative(vm, &abstract->values, "writeInt16BE", bufferWriteint16BE); - - defineNative(vm, &abstract->values, "writeFloatBE", bufferWritefloat32BE); - defineNative(vm, &abstract->values, "writeDoubleBE", bufferWritefloat64BE); - - abstract->data = buffer; - abstract->grayFunc = grayBuffer; - pop(vm); - - return abstract; + ObjAbstract *abstract = newAbstract(vm, freeBuffer, bufferToString); + push(vm, OBJ_VAL(abstract)); + + Buffer *buffer = ALLOCATE(vm, Buffer, 1); + buffer->bigEndian = false; + buffer->bytes = calloc(1, capacity); + buffer->size = capacity; + + /** + * Setup Buffer object methods + */ + defineNative(vm, &abstract->values, "resize", bufferResize); + defineNative(vm, &abstract->values, "set", bufferSet); + defineNative(vm, &abstract->values, "get", bufferGet); + defineNative(vm, &abstract->values, "subarray", bufferSubArray); + defineNative(vm, &abstract->values, "string", bufferString); + defineNative(vm, &abstract->values, "len", bufferLen); + defineNative(vm, &abstract->values, "values", bufferValues); + + defineNative(vm, &abstract->values, "writeString", bufferWriteString); + defineNative(vm, &abstract->values, "readString", bufferReadString); + + defineNative(vm, &abstract->values, "readUInt64LE", bufferReadUint64LE); + defineNative(vm, &abstract->values, "readUInt32LE", bufferReadUint32LE); + defineNative(vm, &abstract->values, "readUInt16LE", bufferReadUint16LE); + defineNative(vm, &abstract->values, "readInt64LE", bufferReadint64LE); + defineNative(vm, &abstract->values, "readInt32LE", bufferReadint32LE); + defineNative(vm, &abstract->values, "readInt16LE", bufferReadint16LE); + + defineNative(vm, &abstract->values, "readFloatLE", bufferReadfloat32LE); + defineNative(vm, &abstract->values, "readDoubleLE", bufferReadfloat64LE); + + defineNative(vm, &abstract->values, "writeUInt64LE", bufferWriteUint64LE); + defineNative(vm, &abstract->values, "writeUInt32LE", bufferWriteUint32LE); + defineNative(vm, &abstract->values, "writeUInt16LE", bufferWriteUint16LE); + defineNative(vm, &abstract->values, "writeInt64LE", bufferWriteint64LE); + defineNative(vm, &abstract->values, "writeInt32LE", bufferWriteint32LE); + defineNative(vm, &abstract->values, "writeInt16LE", bufferWriteint16LE); + + defineNative(vm, &abstract->values, "writeFloatLE", bufferWritefloat32LE); + defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); + + defineNative(vm, &abstract->values, "readUInt64BE", bufferReadUint64BE); + defineNative(vm, &abstract->values, "readUInt32BE", bufferReadUint32BE); + defineNative(vm, &abstract->values, "readUInt16BE", bufferReadUint16BE); + defineNative(vm, &abstract->values, "readInt64BE", bufferReadint64BE); + defineNative(vm, &abstract->values, "readInt32BE", bufferReadint32BE); + defineNative(vm, &abstract->values, "readInt16BE", bufferReadint16BE); + + defineNative(vm, &abstract->values, "readFloatBE", bufferReadfloat32BE); + defineNative(vm, &abstract->values, "readDoubleBE", bufferReadfloat64BE); + + defineNative(vm, &abstract->values, "writeUInt64BE", bufferWriteUint64BE); + defineNative(vm, &abstract->values, "writeUInt32BE", bufferWriteUint32BE); + defineNative(vm, &abstract->values, "writeUInt16BE", bufferWriteUint16BE); + defineNative(vm, &abstract->values, "writeInt64BE", bufferWriteint64BE); + defineNative(vm, &abstract->values, "writeInt32BE", bufferWriteint32BE); + defineNative(vm, &abstract->values, "writeInt16BE", bufferWriteint16BE); + + defineNative(vm, &abstract->values, "writeFloatBE", bufferWritefloat32BE); + defineNative(vm, &abstract->values, "writeDoubleBE", bufferWritefloat64BE); + + abstract->data = buffer; + abstract->grayFunc = grayBuffer; + pop(vm); + + return abstract; } static Value newBuffer(DictuVM *vm, int argCount, Value *args) { - if (argCount != 1) { - runtimeError(vm, "new() takes 1 argument (%d given).", argCount); - return EMPTY_VAL; - } + if (argCount != 1) { + runtimeError(vm, "new() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } - if (!IS_NUMBER(args[0])) { - runtimeError(vm, "new() argument must be a numbers"); - return EMPTY_VAL; - } + if (!IS_NUMBER(args[0])) { + runtimeError(vm, "new() argument must be a numbers"); + return EMPTY_VAL; + } - double capacity = AS_NUMBER(args[0]); - if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { - return newResultError( - vm, "capacity must be greater than 0 and less then 2147483647"); - } + double capacity = AS_NUMBER(args[0]); + if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { + return newResultError( + vm, "capacity must be greater than 0 and less then 2147483647"); + } - return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); + return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); } static Value newBufferFromString(DictuVM *vm, int argCount, Value *args) { - if (argCount != 1) { - runtimeError(vm, "fromString() takes 1 argument (%d given).", argCount); - return EMPTY_VAL; - } - - if (!IS_STRING(args[0])) { - runtimeError(vm, "fromString() argument must be a string"); - return EMPTY_VAL; - } - - ObjString *str = AS_STRING(args[0]); - if (str->length <= 0) { - return newResultError(vm, "string length needs to be greater then 0"); - } - ObjAbstract *b = newBufferObj(vm, str->length); - Buffer *buffer = (Buffer *)b->data; - memcpy(buffer->bytes, str->chars, str->length); - return newResultSuccess(vm, OBJ_VAL(b)); + if (argCount != 1) { + runtimeError(vm, "fromString() takes 1 argument (%d given).", argCount); + return EMPTY_VAL; + } + + if (!IS_STRING(args[0])) { + runtimeError(vm, "fromString() argument must be a string"); + return EMPTY_VAL; + } + + ObjString *str = AS_STRING(args[0]); + if (str->length <= 0) { + return newResultError(vm, "string length needs to be greater then 0"); + } + ObjAbstract *b = newBufferObj(vm, str->length); + Buffer *buffer = (Buffer *)b->data; + memcpy(buffer->bytes, str->chars, str->length); + return newResultSuccess(vm, OBJ_VAL(b)); } Value createBufferModule(DictuVM *vm) { - ObjString *name = copyString(vm, "Buffer", 6); - push(vm, OBJ_VAL(name)); - ObjModule *module = newModule(vm, name); - push(vm, OBJ_VAL(module)); + ObjString *name = copyString(vm, "Buffer", 6); + push(vm, OBJ_VAL(name)); + ObjModule *module = newModule(vm, name); + push(vm, OBJ_VAL(module)); - defineNative(vm, &module->values, "new", newBuffer); - defineNative(vm, &module->values, "fromString", newBufferFromString); + defineNative(vm, &module->values, "new", newBuffer); + defineNative(vm, &module->values, "fromString", newBufferFromString); - pop(vm); - pop(vm); + pop(vm); + pop(vm); - return OBJ_VAL(module); + return OBJ_VAL(module); } \ No newline at end of file diff --git a/tests/buffer/allocate.du b/tests/buffer/allocate.du new file mode 100644 index 000000000..2005c3c8c --- /dev/null +++ b/tests/buffer/allocate.du @@ -0,0 +1,27 @@ +/** +* allocate.du +* +* Testing the buffer.new() and buffer.fromString() methods +* +* .new(Number) creates a new Buffer with the given size. +* .newFromString(String) creates a Buffer from the given String. +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferAllocate < UnitTest { + + testBufferAllocate() { + const b = Buffer.new(10).unwrap(); + this.assertEquals(b.len(), 10); + this.assertEquals(b.values(), [0,0,0,0,0,0,0,0,0,0]); + } + testBufferAllocateString() { + const b = Buffer.fromString("Dictu!").unwrap(); + this.assertEquals(b.len(), 6); + this.assertEquals(b.string(), "Dictu!"); + } + +} + +TestBufferAllocate().run(); \ No newline at end of file diff --git a/tests/buffer/get.du b/tests/buffer/get.du new file mode 100644 index 000000000..2ddabf3fe --- /dev/null +++ b/tests/buffer/get.du @@ -0,0 +1,32 @@ +/** +* get.du +* +* Testing the buffer.get() method +* +* .get(Number) returns the given vaue at the index. +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferGet < UnitTest { + testBufferGet() { + const b = Buffer.fromString("Dictu!").unwrap(); + const check = b.values(); + for(var i = 0; i < b.len(); i+= 1) { + const res = b.get(i); + this.assertEquals(res.success(), true); + this.assertEquals(res.unwrap(), check[i]); + } + } + testBufferGetOutOfBounds() { + const b = Buffer.new(4).unwrap(); + var res = b.get(4); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "index must be smaller then buffer size"); + res = b.get(-1); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "index must be greater than -1"); + } +} + +TestBufferGet().run(); diff --git a/tests/buffer/import.du b/tests/buffer/import.du new file mode 100644 index 000000000..b603d4a00 --- /dev/null +++ b/tests/buffer/import.du @@ -0,0 +1,15 @@ +/** +* import.du +* +* General import file for all the Buffer tests +*/ + +// buffer.values and buffer.len are used a lot throughout the tests. +import "allocate.du"; +import "set.du"; +import "get.du"; +import "resize.du"; +import "string.du"; +import "stringFuncs.du"; +import "subarray.du"; +import "integers.du"; \ No newline at end of file diff --git a/tests/buffer/integers.du b/tests/buffer/integers.du new file mode 100644 index 000000000..5be373b77 --- /dev/null +++ b/tests/buffer/integers.du @@ -0,0 +1,58 @@ +/** +* integers.du +* +* Testing the buffer integers methods. +* +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferIntegers < UnitTest { + runTest(size, v, f, rf) { + const buffer = Buffer.new(size).unwrap(); + var res = f(buffer, v, false); + this.assertEquals(res.success(), true); + res = rf(buffer, false); + const leArray = buffer.values(); + this.assertEquals(res.success(), true); + this.assertEquals(res.unwrap(), v); + res = f(buffer, v, true); + this.assertEquals(res.success(), true); + res = rf(buffer, true); + this.assertEquals(res.success(), true); + this.assertEquals(res.unwrap(), v); + const beArray = buffer.values(); + leArray.reverse(); + this.assertEquals(leArray, beArray); + } + testBufferIntegers() { + this.runTest(2, 2000, def(buffer, v, bigEndian) => bigEndian ? buffer.writeUInt16BE(0, v) : buffer.writeUInt16LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readUInt16BE(0) : buffer.readUInt16LE(0)); + this.runTest(2, -4321, def(buffer, v, bigEndian) => bigEndian ? buffer.writeInt16BE(0, v) : buffer.writeInt16LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readInt16BE(0) : buffer.readInt16LE(0)); + + this.runTest(4, 2300, def(buffer, v, bigEndian) => bigEndian ? buffer.writeUInt32BE(0, v) : buffer.writeUInt32LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readUInt32BE(0) : buffer.readUInt32LE(0)); + this.runTest(4, -2345, def(buffer, v, bigEndian) => bigEndian ? buffer.writeInt32BE(0, v) : buffer.writeInt32LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readInt32BE(0) : buffer.readInt32LE(0)); + + this.runTest(8, 20000000, def(buffer, v, bigEndian) => bigEndian ? buffer.writeUInt64BE(0, v) : buffer.writeUInt64LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readUInt64BE(0) : buffer.readUInt64LE(0)); + this.runTest(8, -20000000, def(buffer, v, bigEndian) => bigEndian ? buffer.writeInt64BE(0, v) : buffer.writeInt64LE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readInt64BE(0) : buffer.readInt64LE(0)); + + this.runTest(8, 234.34534, def(buffer, v, bigEndian) => bigEndian ? buffer.writeDoubleBE(0, v) : buffer.writeDoubleLE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readDoubleBE(0) : buffer.readDoubleLE(0)); + this.runTest(8, -234.34534, def(buffer, v, bigEndian) => bigEndian ? buffer.writeDoubleBE(0, v) : buffer.writeDoubleLE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readDoubleBE(0) : buffer.readDoubleLE(0)); + + this.runTest(4, 1, def(buffer, v, bigEndian) => bigEndian ? buffer.writeFloatBE(0, v) : buffer.writeFloatLE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readFloatBE(0) : buffer.readFloatLE(0)); + this.runTest(4, -1, def(buffer, v, bigEndian) => bigEndian ? buffer.writeFloatBE(0, v) : buffer.writeFloatLE(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readFloatBE(0) : buffer.readFloatLE(0)); + + } + +} + +TestBufferIntegers().run(); diff --git a/tests/buffer/resize.du b/tests/buffer/resize.du new file mode 100644 index 000000000..9ceff2af7 --- /dev/null +++ b/tests/buffer/resize.du @@ -0,0 +1,36 @@ +/** +* resize.du +* +* Testing the buffer.resize() methods +* +* .resize(Number) resizes the Buffer to the given size +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferResize < UnitTest { + + testBufferResize() { + const b = Buffer.new(10).unwrap(); + this.assertEquals(b.len(), 10); + this.assertEquals(b.values(), [0,0,0,0,0,0,0,0,0,0]); + b.resize(15); + this.assertEquals(b.len(), 15); + this.assertEquals(b.values(), [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); + b.resize(1); + this.assertEquals(b.len(), 1); + this.assertEquals(b.values(), [0]); + } + testBufferResizeOutOfBounds() { + const b = Buffer.new(5).unwrap(); + var res = b.resize(-1); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller then 2147483647"); + res = b.resize(2147483647); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller then 2147483647"); + } + +} + +TestBufferResize().run(); diff --git a/tests/buffer/set.du b/tests/buffer/set.du new file mode 100644 index 000000000..9b2aafb7b --- /dev/null +++ b/tests/buffer/set.du @@ -0,0 +1,33 @@ +/** +* set.du +* +* Testing the buffer.set() method +* +* .set(Number, Number) sets a given integer value into the buffer; +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferSet < UnitTest { + testBufferSet() { + const b = Buffer.new(8).unwrap(); + const check = []; + for(var i = 0; i < b.len(); i+= 1) { + const res = b.set(i, i*2); + this.assertEquals(res.success(), true); + check.push(i*2); + } + this.assertEquals(b.values(), check); + } + testBufferSetOutOfBounds() { + const b = Buffer.new(4).unwrap(); + var res = b.set(4, 0); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "index must be smaller then buffer size"); + res = b.set(-1, 0); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "index must be greater than -1"); + } +} + +TestBufferSet().run(); diff --git a/tests/buffer/string.du b/tests/buffer/string.du new file mode 100644 index 000000000..ee4a4a4ab --- /dev/null +++ b/tests/buffer/string.du @@ -0,0 +1,19 @@ +/** +* string.du +* +* Testing the buffer.string() method +* +* .string() returns a string of the buffer. +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferString < UnitTest { + + testBufferString() { + const b = Buffer.fromString("Dictu!").unwrap(); + this.assertEquals(b.string(), "Dictu!"); + } +} + +TestBufferString().run(); diff --git a/tests/buffer/stringFuncs.du b/tests/buffer/stringFuncs.du new file mode 100644 index 000000000..f19dc5e4f --- /dev/null +++ b/tests/buffer/stringFuncs.du @@ -0,0 +1,49 @@ +/** +* stringFuncs.du +* +* Testing the buffer.readString() and buffer.writeString() methods +* +* .writeString(Number -> Optional) writes a string into the buffer +* .readString(Number -> Optional, Number -> Optional) returns a result of the string given optionally index and end. +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferStringFuncs < UnitTest { + + testBufferReadString() { + const b = Buffer.fromString("Dictu!").unwrap(); + var res = b.readString(0, b.len()-1); + this.assertEquals(res.success(), true); + this.assertEquals(res.unwrap(), "Dictu"); + res = b.readString(2); + this.assertEquals(res.success(), true); + this.assertEquals(res.unwrap(), "ctu!"); + } + testBufferWriteString() { + const b = Buffer.new(10).unwrap(); + const res = b.writeString(0, "Dictu!"); + this.assertEquals(res.success(), true); + } + testBufferWriteStringOutOfBounds() { + const b = Buffer.new(4).unwrap(); + const res = b.writeString(0, "Dictu!"); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "buffer is not large enough to fit the string"); + } + testBufferReadStringOutOfBounds() { + const b = Buffer.fromString("Dictu!").unwrap(); + var res = b.readString(23); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "start greater or equals then buffer length"); + res = b.readString(3,3); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "string length is 0"); + res = b.readString(3,34); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "end greater then buffer length"); + } + +} + +TestBufferStringFuncs().run(); diff --git a/tests/buffer/subarray.du b/tests/buffer/subarray.du new file mode 100644 index 000000000..9320788f6 --- /dev/null +++ b/tests/buffer/subarray.du @@ -0,0 +1,46 @@ +/** +* subarray.du +* +* Testing the buffer.subarray() method. +* +* .subarray(Number -> Optional, Number -> Optional) returns a subarray given optionally the index and end. +*/ +from UnitTest import UnitTest; +import Buffer; + +class TestBufferSubArray < UnitTest { + + testBufferSubarray() { + const b = Buffer.new(10).unwrap(); + var sub = b.subarray(0); + this.assertEquals(sub.success(), true); + var v = sub.unwrap(); + this.assertEquals(v.values(), b.values()); + sub = b.subarray(5); + this.assertEquals(sub.success(), true); + v = sub.unwrap(); + this.assertEquals(v.values(), [0,0,0,0,0]); + } + testBufferSubarrayStr() { + const b = Buffer.fromString("Dictu is awesome!").unwrap(); + const sub = b.subarray(0, 5); + this.assertEquals(sub.success(), true); + const v = sub.unwrap(); + this.assertEquals(v.string(), "Dictu"); + } + testBufferSubarrayOutOfBounds() { + const b = Buffer.fromString("Dictu!").unwrap(); + var res = b.subarray(25); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "start greater or equals then buffer length"); + res = b.subarray(0, 25); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "end greater then buffer length"); + res = b.subarray(0, 0); + this.assertEquals(res.success(), false); + this.assertEquals(res.unwrapError(), "array length is 0"); + + } +} + +TestBufferSubArray().run(); diff --git a/tests/runTests.du b/tests/runTests.du index b239da431..9c1636152 100644 --- a/tests/runTests.du +++ b/tests/runTests.du @@ -53,6 +53,7 @@ import "random/import.du"; import "hashlib/import.du"; import "object/import.du"; import "term/import.du"; +import "buffer/import.du"; // If we got here no runtime errors were thrown, therefore all tests passed. print("All tests passed successfully!"); From ed9eb32bd2114b8bb12462066cdad1272bef145a Mon Sep 17 00:00:00 2001 From: Liz3 Date: Thu, 25 Jan 2024 20:50:35 +0100 Subject: [PATCH 093/148] fix: do this correctly --- src/optionals/buffer.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 23f7acf66..037e99f9e 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -486,11 +486,12 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { if (ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); - const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if (value > MAX_VALUE) - return newResultError(vm, - "value would overflow internal representation"); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + const uint64_t MAX_VALUE = 9007199254740992; + if (value > MAX_VALUE){ + return newResultError(vm, + "value too large for internal internal representation"); + } return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -565,10 +566,7 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { if (ptr == NULL) return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); - const uint64_t MAX_VALUE = (uint64_t)DBL_MAX; - if ((uint64_t)value > MAX_VALUE) - return newResultError(vm, - "value would overflow internal representation"); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); } From 9d382162e9f2b0d34f00060fb97e7c7ab287556f Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 25 Jan 2024 21:42:12 +0100 Subject: [PATCH 094/148] fixes and add signed 8bit read/write --- docs/docs/standard-lib/buffer.md | 99 ++++++++++++++++++++++++++++++-- src/optionals/buffer.c | 57 +++++++++++++++++- tests/buffer/integers.du | 5 ++ 3 files changed, 156 insertions(+), 5 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 59ab4712f..225e9712e 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -138,6 +138,7 @@ print(sub) // "Dictu" Returns the u64(unsigned 8 byte integer in little endian) value given the starting index. Returns a result with the value or a error. +**Note**: The maximum value supported is: `9007199254740992`, if a read of a larger value is attempted a error is returned. ```cs const buffer = Buffer.new(8).unwrap(); @@ -185,8 +186,8 @@ Returns a result with the value or a error. ```cs const buffer = Buffer.new(4).unwrap(); -buffer.writeUInt32LE(0, -1337); -print(buffer.readUInt32LE(0).unwrap()) // -1337 +buffer.writeInt32LE(0, -1337); +print(buffer.readInt32LE(0).unwrap()) // -1337 ``` ### Buffer.readInt16LE(Number) -> Result\ @@ -196,8 +197,20 @@ Returns a result with the value or a error. ```cs const buffer = Buffer.new(2).unwrap(); -buffer.writeUInt16LE(0, -1337); -print(buffer.readUInt16LE(0).unwrap()) // -1337 +buffer.writeInt16LE(0, -1337); +print(buffer.readInt16LE(0).unwrap()) // -1337 +``` + +### Buffer.readInt8(Number) -> Result\ + +Returns the i8(signed 1 byte integer) value given the starting index. +Returns a result with the value or a error. +**Note**: For the unsigned equivalent use get(). + +```cs +const buffer = Buffer.new(1).unwrap(); +buffer.writeUInt8(0, -12); +print(buffer.readInt8(0).unwrap()) // -12 ``` ### Buffer.writeUInt64LE(Number, Number) -> Result\ @@ -254,6 +267,17 @@ const buffer = Buffer.new(2).unwrap(); buffer.writeInt16LE(0, 1337); ``` +### Buffer.writeInt8(Number, Number) -> Result\ + +Writes a i8(signed 1 byte integer) at the index(the first argument). +Returns a result with the set value or a error. +**Note**: For the unsigned equivalent use set(). + +```cs +const buffer = Buffer.new(1).unwrap(); +buffer.writeInt8(0, -12); +``` + ### Buffer.writeFloatLE(Number, Number) -> Result\ Writes a float(4 byte signed floating point number in little endian) at the index(the first argument). @@ -366,6 +390,73 @@ const buffer = Buffer.new(8).unwrap(); buffer.writeDoubleBE(0, 14.34); ``` +### Buffer.readUInt64BE(Number) -> Result\ + +Returns the u64(unsigned 8 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. +**Note**: The maximum value supported is: `9007199254740992`, if a read of a larger value is attempted a error is returned. + +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeUInt64BE(0, 12000); +print(buffer.readUInt64BE(0).unwrap()) // 12000 +``` + +### Buffer.readUInt32BE(Number) -> Result\ + +Returns the u32(unsigned 4 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeUInt32BE(0, 1337); +print(buffer.readUInt32BE(0).unwrap()) // 1337 +``` + +### Buffer.readUInt16BE(Number) -> Result\ + +Returns the u16(unsigned 2 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeUInt16BE(0, 1337); +print(buffer.readUInt16BE(0).unwrap()) // 1337 +``` + +### Buffer.readInt64BE(Number) -> Result\ + +Returns the i64(signed 8 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(8).unwrap(); +buffer.writeInt64BE(0, -12000); +print(buffer.readInt64BE(0).unwrap()) // -12000 +``` + +### Buffer.readInt32BE(Number) -> Result\ + +Returns the i32(signed 4 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(4).unwrap(); +buffer.writeInt32BE(0, -1337); +print(buffer.readInt32BE(0).unwrap()) // -1337 +``` + +### Buffer.readInt16BE(Number) -> Result\ + +Returns the i16(signed 2 byte integer in big endian) value given the starting index. +Returns a result with the value or a error. + +```cs +const buffer = Buffer.new(2).unwrap(); +buffer.writeInt16BE(0, -1337); +print(buffer.readInt16BE(0).unwrap()) // -1337 +``` + ### Buffer.readFloatBE(Number) -> Result\ Returns the float(signed 4 byte floating point number in big endian) value given the starting index. diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 037e99f9e..8dec277fc 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -134,7 +134,35 @@ static Value bufferString(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(copyString(vm, (const char *)buffer->bytes, buffer->size)); } +static Value bufferWriteint8(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 2) { + runtimeError(vm, "writeInt8() takes 2 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, + "writeInt8() index argument must be a number"); + return EMPTY_VAL; + } + if (!IS_NUMBER(args[2])) { + runtimeError(vm, + "writeInt8() value argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + double value = AS_NUMBER(args[2]); + int8_t correctVal = (int8_t)value; + + if (!writeInternal( + buffer, index, + swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), + sizeof(correctVal))) + return newResultError(vm, "index must be smaller then buffer size - 1"); + return newResultSuccess(vm, NUMBER_VAL(correctVal)); +} static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { Buffer *buffer = AS_BUFFER(args[0]); if (argCount != 2) { @@ -487,10 +515,13 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { return newResultError(vm, "index must be smaller then buffer size - 8"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + + // Above this value theres no guarantee that the integer value is correctly represented, + // so if are above that we don't allow it, const uint64_t MAX_VALUE = 9007199254740992; if (value > MAX_VALUE){ return newResultError(vm, - "value too large for internal internal representation"); + "value too large for internal representation"); } return newResultSuccess(vm, NUMBER_VAL(value)); } @@ -621,6 +652,28 @@ static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { return newResultSuccess(vm, NUMBER_VAL(value)); } +static Value bufferReadint8(DictuVM *vm, int argCount, Value *args) { + Buffer *buffer = AS_BUFFER(args[0]); + if (argCount != 1) { + runtimeError(vm, "readInt8() takes 1 argument"); + return EMPTY_VAL; + } + + if (!IS_NUMBER(args[1])) { + runtimeError(vm, "readInt8() index argument must be a number"); + return EMPTY_VAL; + } + double index = AS_NUMBER(args[1]); + + int8_t value; + uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); + if (ptr == NULL) + return newResultError(vm, "index must be smaller then buffer size - 1"); + memcpy(&value, ptr, sizeof(value)); + swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + return newResultSuccess(vm, NUMBER_VAL(value)); +} + typedef Value buffer_func_t(DictuVM *vm, int argCount, Value *args); // is this hacky? static Value runBigEndian(DictuVM *vm, int argCount, Value *args, @@ -897,6 +950,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "readInt64LE", bufferReadint64LE); defineNative(vm, &abstract->values, "readInt32LE", bufferReadint32LE); defineNative(vm, &abstract->values, "readInt16LE", bufferReadint16LE); + defineNative(vm, &abstract->values, "readInt8", bufferReadint8); defineNative(vm, &abstract->values, "readFloatLE", bufferReadfloat32LE); defineNative(vm, &abstract->values, "readDoubleLE", bufferReadfloat64LE); @@ -907,6 +961,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "writeInt64LE", bufferWriteint64LE); defineNative(vm, &abstract->values, "writeInt32LE", bufferWriteint32LE); defineNative(vm, &abstract->values, "writeInt16LE", bufferWriteint16LE); + defineNative(vm, &abstract->values, "writeInt8", bufferWriteint8); defineNative(vm, &abstract->values, "writeFloatLE", bufferWritefloat32LE); defineNative(vm, &abstract->values, "writeDoubleLE", bufferWritefloat64LE); diff --git a/tests/buffer/integers.du b/tests/buffer/integers.du index 5be373b77..7a9421ad3 100644 --- a/tests/buffer/integers.du +++ b/tests/buffer/integers.du @@ -25,7 +25,12 @@ class TestBufferIntegers < UnitTest { leArray.reverse(); this.assertEquals(leArray, beArray); } + testBufferIntegers() { + + this.runTest(1, -123, def(buffer, v, bigEndian) => bigEndian ? buffer.writeInt8(0, v) : buffer.writeInt8(0, v), + def(buffer, bigEndian) => bigEndian ? buffer.readInt8(0) : buffer.readInt8(0)); + this.runTest(2, 2000, def(buffer, v, bigEndian) => bigEndian ? buffer.writeUInt16BE(0, v) : buffer.writeUInt16LE(0, v), def(buffer, bigEndian) => bigEndian ? buffer.readUInt16BE(0) : buffer.readUInt16LE(0)); this.runTest(2, -4321, def(buffer, v, bigEndian) => bigEndian ? buffer.writeInt16BE(0, v) : buffer.writeInt16LE(0, v), From d0afa604879b3f65e813f50dc98e0c48a8548c65 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 25 Jan 2024 21:55:01 +0100 Subject: [PATCH 095/148] refactor: remove unneeded includes --- src/optionals/buffer.c | 1 - src/optionals/buffer.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 8dec277fc..f470bcec5 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -1,5 +1,4 @@ #include "buffer.h" -#include typedef struct { uint8_t *bytes; diff --git a/src/optionals/buffer.h b/src/optionals/buffer.h index 376e2713a..9d77f06e8 100644 --- a/src/optionals/buffer.h +++ b/src/optionals/buffer.h @@ -1,11 +1,9 @@ #ifndef dictu_buffer_h #define dictu_buffer_h -#include #include "optionals.h" #include "../vm/vm.h" -#include #define BUFFER_SIZE_MAX 2147483647 From 49a037f9126fdd2c7af6ebd046a44da600f2137f Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 29 Jan 2024 00:34:22 +0100 Subject: [PATCH 096/148] chore: typos --- docs/docs/standard-lib/buffer.md | 72 ++++++++++++++++---------------- tests/buffer/get.du | 2 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/docs/standard-lib/buffer.md b/docs/docs/standard-lib/buffer.md index 225e9712e..4148eb7d2 100644 --- a/docs/docs/standard-lib/buffer.md +++ b/docs/docs/standard-lib/buffer.md @@ -47,7 +47,7 @@ print(buffer); ### Buffer.resize(Number) -> Result\ -Resizes the buffer to the given size, the argument needs to be greater then 0 or the function will return a error. +Resizes the buffer to the given size. The argument needs to be greater than 0 or the function will return an error. ```cs const buffer = Buffer.new(8).unwrap(); @@ -116,7 +116,7 @@ print(v); // [68, 105, 99, 116, 117, 33] ### Buffer.writeString(Number, String) -> Result\ -Sets a string into buffer given the starting index, if the string doesn't fit in the buffer a error is returned. +Sets a string into buffer given the starting index. If the string doesn't fit in the buffer an error is returned. ```cs const buffer = Buffer.new(6).unwrap(); buffer.writeString(0, "Dictu!"); @@ -137,7 +137,7 @@ print(sub) // "Dictu" ### Buffer.readUInt64LE(Number) -> Result\ Returns the u64(unsigned 8 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. **Note**: The maximum value supported is: `9007199254740992`, if a read of a larger value is attempted a error is returned. ```cs @@ -149,7 +149,7 @@ print(buffer.readUInt64LE(0).unwrap()) // 12000 ### Buffer.readUInt32LE(Number) -> Result\ Returns the u32(unsigned 4 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -160,7 +160,7 @@ print(buffer.readUInt32LE(0).unwrap()) // 1337 ### Buffer.readUInt16LE(Number) -> Result\ Returns the u16(unsigned 2 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(2).unwrap(); @@ -171,7 +171,7 @@ print(buffer.readUInt16LE(0).unwrap()) // 1337 ### Buffer.readInt64LE(Number) -> Result\ Returns the i64(signed 8 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(8).unwrap(); @@ -182,7 +182,7 @@ print(buffer.readInt64LE(0).unwrap()) // -12000 ### Buffer.readInt32LE(Number) -> Result\ Returns the i32(signed 4 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -193,7 +193,7 @@ print(buffer.readInt32LE(0).unwrap()) // -1337 ### Buffer.readInt16LE(Number) -> Result\ Returns the i16(signed 2 byte integer in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(2).unwrap(); @@ -204,7 +204,7 @@ print(buffer.readInt16LE(0).unwrap()) // -1337 ### Buffer.readInt8(Number) -> Result\ Returns the i8(signed 1 byte integer) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. **Note**: For the unsigned equivalent use get(). ```cs @@ -216,7 +216,7 @@ print(buffer.readInt8(0).unwrap()) // -12 ### Buffer.writeUInt64LE(Number, Number) -> Result\ Writes a u64(unsigned 8 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeUInt64LE(0, 12000); @@ -225,7 +225,7 @@ buffer.writeUInt64LE(0, 12000); ### Buffer.writeUInt32LE(Number, Number) -> Result\ Writes a u32(unsigned 4 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeUInt32LE(0, 1337); @@ -234,7 +234,7 @@ buffer.writeUInt32LE(0, 1337); ### Buffer.writeUInt16LE(Number, Number) -> Result\ Writes a u16(unsigned 2 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(2).unwrap(); buffer.writeUInt16LE(0, 1337); @@ -243,7 +243,7 @@ buffer.writeUInt16LE(0, 1337); ### Buffer.writeInt64LE(Number, Number) -> Result\ Writes a i64(signed 8 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeInt64LE(0, 12000); @@ -252,7 +252,7 @@ buffer.writeInt64LE(0, 12000); ### Buffer.writeInt32LE(Number, Number) -> Result\ Writes a i32(signed 4 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeInt32LE(0, 1337); @@ -261,7 +261,7 @@ buffer.writeInt32LE(0, 1337); ### Buffer.writeInt16LE(Number, Number) -> Result\ Writes a i16(signed 2 byte integer in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(2).unwrap(); buffer.writeInt16LE(0, 1337); @@ -270,7 +270,7 @@ buffer.writeInt16LE(0, 1337); ### Buffer.writeInt8(Number, Number) -> Result\ Writes a i8(signed 1 byte integer) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. **Note**: For the unsigned equivalent use set(). ```cs @@ -281,7 +281,7 @@ buffer.writeInt8(0, -12); ### Buffer.writeFloatLE(Number, Number) -> Result\ Writes a float(4 byte signed floating point number in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeFloatLE(0, 14.34); @@ -290,7 +290,7 @@ buffer.writeFloatLE(0, 14.34); ### Buffer.writeDoubleLE(Number, Number) -> Result\ Writes a double(8 byte signed floating point number in little endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeDoubleLE(0, 14.34); @@ -299,7 +299,7 @@ buffer.writeDoubleLE(0, 14.34); ### Buffer.readFloatLE(Number) -> Result\ Returns the float(signed 4 byte floating point number in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -310,7 +310,7 @@ print(buffer.readFloatLE(0).unwrap()) // 14.34 ### Buffer.readDoubleLE(Number) -> Result\ Returns the double(signed 8 byte floating point number in little endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(8).unwrap(); @@ -321,7 +321,7 @@ print(buffer.readDoubleLE(0).unwrap()) // 14.34 ### Buffer.writeUInt64BE(Number, Number) -> Result\ Writes a u64(unsigned 8 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeUInt64BE(0, 12000); @@ -330,7 +330,7 @@ buffer.writeUInt64BE(0, 12000); ### Buffer.writeUInt32BE(Number, Number) -> Result\ Writes a u32(unsigned 4 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeUInt32BE(0, 1337); @@ -339,7 +339,7 @@ buffer.writeUInt32BE(0, 1337); ### Buffer.writeUInt16BE(Number, Number) -> Result\ Writes a u16(unsigned 2 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(2).unwrap(); buffer.writeUInt16BE(0, 1337); @@ -348,7 +348,7 @@ buffer.writeUInt16BE(0, 1337); ### Buffer.writeInt64BE(Number, Number) -> Result\ Writes a i64(signed 8 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeInt64BE(0, 12000); @@ -357,7 +357,7 @@ buffer.writeInt64BE(0, 12000); ### Buffer.writeInt32BE(Number, Number) -> Result\ Writes a i32(signed 4 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeInt32BE(0, 1337); @@ -366,7 +366,7 @@ buffer.writeInt32BE(0, 1337); ### Buffer.writeInt16BE(Number, Number) -> Result\ Writes a i16(signed 2 byte integer in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(2).unwrap(); buffer.writeInt16BE(0, 1337); @@ -375,7 +375,7 @@ buffer.writeInt16BE(0, 1337); ### Buffer.writeFloatBE(Number, Number) -> Result\ Writes a float(4 byte signed floating point number in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(4).unwrap(); buffer.writeFloatBE(0, 14.34); @@ -384,7 +384,7 @@ buffer.writeFloatBE(0, 14.34); ### Buffer.writeDoubleBE(Number, Number) -> Result\ Writes a double(8 byte signed floating point number in big endian) at the index(the first argument). -Returns a result with the set value or a error. +Returns a result with the set value or an error incase the byte size from the start index would exceed the buffer bounds. ```cs const buffer = Buffer.new(8).unwrap(); buffer.writeDoubleBE(0, 14.34); @@ -393,7 +393,7 @@ buffer.writeDoubleBE(0, 14.34); ### Buffer.readUInt64BE(Number) -> Result\ Returns the u64(unsigned 8 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. **Note**: The maximum value supported is: `9007199254740992`, if a read of a larger value is attempted a error is returned. ```cs @@ -405,7 +405,7 @@ print(buffer.readUInt64BE(0).unwrap()) // 12000 ### Buffer.readUInt32BE(Number) -> Result\ Returns the u32(unsigned 4 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -416,7 +416,7 @@ print(buffer.readUInt32BE(0).unwrap()) // 1337 ### Buffer.readUInt16BE(Number) -> Result\ Returns the u16(unsigned 2 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(2).unwrap(); @@ -427,7 +427,7 @@ print(buffer.readUInt16BE(0).unwrap()) // 1337 ### Buffer.readInt64BE(Number) -> Result\ Returns the i64(signed 8 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(8).unwrap(); @@ -438,7 +438,7 @@ print(buffer.readInt64BE(0).unwrap()) // -12000 ### Buffer.readInt32BE(Number) -> Result\ Returns the i32(signed 4 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -449,7 +449,7 @@ print(buffer.readInt32BE(0).unwrap()) // -1337 ### Buffer.readInt16BE(Number) -> Result\ Returns the i16(signed 2 byte integer in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(2).unwrap(); @@ -460,7 +460,7 @@ print(buffer.readInt16BE(0).unwrap()) // -1337 ### Buffer.readFloatBE(Number) -> Result\ Returns the float(signed 4 byte floating point number in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(4).unwrap(); @@ -471,7 +471,7 @@ print(buffer.readFloatBE(0).unwrap()) // 14.34 ### Buffer.readDoubleBE(Number) -> Result\ Returns the double(signed 8 byte floating point number in big endian) value given the starting index. -Returns a result with the value or a error. +If the given index + byte length does exceed the buffer bounds an error is returned. ```cs const buffer = Buffer.new(8).unwrap(); diff --git a/tests/buffer/get.du b/tests/buffer/get.du index 2ddabf3fe..49aeb62c5 100644 --- a/tests/buffer/get.du +++ b/tests/buffer/get.du @@ -3,7 +3,7 @@ * * Testing the buffer.get() method * -* .get(Number) returns the given vaue at the index. +* .get(Number) returns the given value at the index. */ from UnitTest import UnitTest; import Buffer; From 59c39ba2739c726fead0c30f3e35dbbe4c1e144f Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 29 Jan 2024 02:13:45 +0100 Subject: [PATCH 097/148] fix: reimplement max check for int64_t read --- src/optionals/buffer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index f470bcec5..05c9925cd 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -598,6 +598,13 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); + // Above this value theres no guarantee that the integer value is correctly represented, + // so if are above that we don't allow it, + const int64_t MAX_VALUE = 9007199254740992; + if (value > MAX_VALUE || value < -MAX_VALUE){ + return newResultError(vm, + "value too large for internal representation"); + } return newResultSuccess(vm, NUMBER_VAL(value)); } From ac680bc1ec1461728414b0f33b7d0ab4591ba2cc Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 28 Jan 2024 22:53:07 -0700 Subject: [PATCH 098/148] resolve pr comments Signed-off-by: Brian Downs --- docs/docs/standard-lib/object.md | 6 +++--- src/optionals/object/object.c | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/docs/standard-lib/object.md b/docs/docs/standard-lib/object.md index fd0441206..c1d754f97 100644 --- a/docs/docs/standard-lib/object.md +++ b/docs/docs/standard-lib/object.md @@ -62,11 +62,11 @@ This method will return a string of the object's hash value. Object.hash("Dictu"); ``` -### Object.prettyPrint(Value, indent -> Optional) -> Result\ +### Object.prettyPrint(Value, Number: indent -> Optional) -> Result\ This method will return a string representation of the given value. -**NOTE** Strings, dicts, lists, numbers, and nil are valid values for pretty printing at this time. +**NOTE** Strings, dicts, lists, numbers, booleans, and nil are valid values for pretty printing at this time. ```cs Object.prettyPrint([1, 2, 3]).unwrap(); @@ -76,7 +76,7 @@ Object.prettyPrint([1, 2, 3]).unwrap(); ``` ```cs -Object.prettyPrint({"a": 1}, 4).unwrap() +Object.prettyPrint({"a": 1}, 4).unwrap(); // Output ' diff --git a/src/optionals/object/object.c b/src/optionals/object/object.c index 471a1923f..17f5b5865 100644 --- a/src/optionals/object/object.c +++ b/src/optionals/object/object.c @@ -69,11 +69,6 @@ static Value objectPrettyPrint(DictuVM *vm, int argCount, Value *args) { } Value createObjectModule(DictuVM *vm) { - ObjString *name = copyString(vm, "Object", 6); - push(vm, OBJ_VAL(name)); - ObjModule *module = newModule(vm, name); - push(vm, OBJ_VAL(module)); - ObjClosure *closure = compileModuleToClosure(vm, "Object", DICTU_OBJECT_SOURCE); if (closure == NULL) { @@ -89,7 +84,7 @@ Value createObjectModule(DictuVM *vm) { defineNative(vm, &closure->function->module->values, "getClassRef", objectGetClassRef); defineNative(vm, &closure->function->module->values, "hash", objectHash); - defineNative(vm, &module->values, "prettyPrint", objectPrettyPrint); + defineNative(vm, &closure->function->module->values, "prettyPrint", objectPrettyPrint); pop(vm); From 4805c2c2aaad6a83e46957c063bdc7d3836c6509 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 29 Jan 2024 16:51:47 +0100 Subject: [PATCH 099/148] fix: more typos --- src/optionals/buffer.c | 56 ++++++++++++++++++------------------- tests/buffer/get.du | 2 +- tests/buffer/resize.du | 4 +-- tests/buffer/set.du | 2 +- tests/buffer/stringFuncs.du | 4 +-- tests/buffer/subarray.du | 4 +-- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 05c9925cd..62b47c756 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -85,7 +85,7 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { double capacity = AS_NUMBER(args[1]); if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { return newResultError( - vm, "size must be greater than 0 and smaller then 2147483647"); + vm, "size must be greater than 0 and smaller than 2147483647"); } Buffer *buffer = AS_BUFFER(args[0]); buffer->bytes = realloc(buffer->bytes, capacity); @@ -159,7 +159,7 @@ static Value bufferWriteint8(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 1"); + return newResultError(vm, "index must be smaller than buffer size - 1"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { @@ -194,7 +194,7 @@ static Value bufferWriteUint16LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultError(vm, "index must be smaller than buffer size - 2"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -229,7 +229,7 @@ static Value bufferWriteUint32LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -264,7 +264,7 @@ static Value bufferWriteUint64LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -297,7 +297,7 @@ static Value bufferWriteint64LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -331,7 +331,7 @@ static Value bufferWriteint32LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -365,7 +365,7 @@ static Value bufferWriteint16LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultError(vm, "index must be smaller than buffer size - 2"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -399,7 +399,7 @@ static Value bufferWritefloat32LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -435,7 +435,7 @@ static Value bufferWritefloat64LE(DictuVM *vm, int argCount, Value *args) { buffer, index, swap((uint8_t *)&correctVal, sizeof(correctVal), buffer->bigEndian), sizeof(correctVal))) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); return newResultSuccess(vm, NUMBER_VAL(correctVal)); } @@ -459,7 +459,7 @@ static Value bufferReadfloat64LE(DictuVM *vm, int argCount, Value *args) { uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); @@ -485,7 +485,7 @@ static Value bufferReadfloat32LE(DictuVM *vm, int argCount, Value *args) { uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -511,7 +511,7 @@ static Value bufferReadUint64LE(DictuVM *vm, int argCount, Value *args) { uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); @@ -544,7 +544,7 @@ static Value bufferReadUint32LE(DictuVM *vm, int argCount, Value *args) { uint32_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -570,7 +570,7 @@ static Value bufferReadUint16LE(DictuVM *vm, int argCount, Value *args) { uint16_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultError(vm, "index must be smaller than buffer size - 2"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -594,7 +594,7 @@ static Value bufferReadint64LE(DictuVM *vm, int argCount, Value *args) { int64_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 8"); + return newResultError(vm, "index must be smaller than buffer size - 8"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); @@ -627,7 +627,7 @@ static Value bufferReadint32LE(DictuVM *vm, int argCount, Value *args) { int32_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 4"); + return newResultError(vm, "index must be smaller than buffer size - 4"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -652,7 +652,7 @@ static Value bufferReadint16LE(DictuVM *vm, int argCount, Value *args) { int16_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 2"); + return newResultError(vm, "index must be smaller than buffer size - 2"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -674,7 +674,7 @@ static Value bufferReadint8(DictuVM *vm, int argCount, Value *args) { int8_t value; uint8_t *ptr = getReadPtr(buffer, index, sizeof(value)); if (ptr == NULL) - return newResultError(vm, "index must be smaller then buffer size - 1"); + return newResultError(vm, "index must be smaller than buffer size - 1"); memcpy(&value, ptr, sizeof(value)); swap((uint8_t *)&value, sizeof(value), buffer->bigEndian); return newResultSuccess(vm, NUMBER_VAL(value)); @@ -772,7 +772,7 @@ static Value bufferGet(DictuVM *vm, int argCount, Value *args) { } Buffer *buffer = AS_BUFFER(args[0]); if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); + return newResultError(vm, "index must be smaller than buffer size"); } return newResultSuccess(vm, NUMBER_VAL(buffer->bytes[(size_t)index])); @@ -801,7 +801,7 @@ static Value bufferSet(DictuVM *vm, int argCount, Value *args) { } Buffer *buffer = AS_BUFFER(args[0]); if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); + return newResultError(vm, "index must be smaller than buffer size"); } buffer->bytes[(size_t)index] = (uint8_t)value; @@ -833,7 +833,7 @@ static Value bufferWriteString(DictuVM *vm, int argCount, Value *args) { } Buffer *buffer = AS_BUFFER(args[0]); if (index >= buffer->size) { - return newResultError(vm, "index must be smaller then buffer size"); + return newResultError(vm, "index must be smaller than buffer size"); } if (buffer->size - index < str->length) { @@ -857,7 +857,7 @@ static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { double startParam = AS_NUMBER(args[1]); if (startParam >= buffer->size) { return newResultError(vm, - "start greater or equals then buffer length"); + "start greater or equals than buffer length"); } else { start = startParam; length = end - start; @@ -870,7 +870,7 @@ static Value bufferReadString(DictuVM *vm, int argCount, Value *args) { } double endParam = AS_NUMBER(args[2]); if (endParam > buffer->size) { - return newResultError(vm, "end greater then buffer length"); + return newResultError(vm, "end greater than buffer length"); } else { end = endParam; length = end - start; @@ -897,7 +897,7 @@ static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { double startParam = AS_NUMBER(args[1]); if (startParam >= buffer->size) { return newResultError(vm, - "start greater or equals then buffer length"); + "start greater or equals than buffer length"); } else { start = startParam; length = end - start; @@ -910,7 +910,7 @@ static Value bufferSubArray(DictuVM *vm, int argCount, Value *args) { } double endParam = AS_NUMBER(args[2]); if (endParam > buffer->size) { - return newResultError(vm, "end greater then buffer length"); + return newResultError(vm, "end greater than buffer length"); } else { end = endParam; length = end - start; @@ -1013,7 +1013,7 @@ static Value newBuffer(DictuVM *vm, int argCount, Value *args) { double capacity = AS_NUMBER(args[0]); if (capacity <= 0 || capacity >= BUFFER_SIZE_MAX) { return newResultError( - vm, "capacity must be greater than 0 and less then 2147483647"); + vm, "capacity must be greater than 0 and less than 2147483647"); } return newResultSuccess(vm, OBJ_VAL(newBufferObj(vm, capacity))); @@ -1032,7 +1032,7 @@ static Value newBufferFromString(DictuVM *vm, int argCount, Value *args) { ObjString *str = AS_STRING(args[0]); if (str->length <= 0) { - return newResultError(vm, "string length needs to be greater then 0"); + return newResultError(vm, "string length needs to be greater than 0"); } ObjAbstract *b = newBufferObj(vm, str->length); Buffer *buffer = (Buffer *)b->data; diff --git a/tests/buffer/get.du b/tests/buffer/get.du index 49aeb62c5..63ab3c6a6 100644 --- a/tests/buffer/get.du +++ b/tests/buffer/get.du @@ -22,7 +22,7 @@ class TestBufferGet < UnitTest { const b = Buffer.new(4).unwrap(); var res = b.get(4); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "index must be smaller then buffer size"); + this.assertEquals(res.unwrapError(), "index must be smaller than buffer size"); res = b.get(-1); this.assertEquals(res.success(), false); this.assertEquals(res.unwrapError(), "index must be greater than -1"); diff --git a/tests/buffer/resize.du b/tests/buffer/resize.du index 9ceff2af7..b27e3755d 100644 --- a/tests/buffer/resize.du +++ b/tests/buffer/resize.du @@ -25,10 +25,10 @@ class TestBufferResize < UnitTest { const b = Buffer.new(5).unwrap(); var res = b.resize(-1); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller then 2147483647"); + this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller than 2147483647"); res = b.resize(2147483647); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller then 2147483647"); + this.assertEquals(res.unwrapError(), "size must be greater than 0 and smaller than 2147483647"); } } diff --git a/tests/buffer/set.du b/tests/buffer/set.du index 9b2aafb7b..5b4e12a49 100644 --- a/tests/buffer/set.du +++ b/tests/buffer/set.du @@ -23,7 +23,7 @@ class TestBufferSet < UnitTest { const b = Buffer.new(4).unwrap(); var res = b.set(4, 0); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "index must be smaller then buffer size"); + this.assertEquals(res.unwrapError(), "index must be smaller than buffer size"); res = b.set(-1, 0); this.assertEquals(res.success(), false); this.assertEquals(res.unwrapError(), "index must be greater than -1"); diff --git a/tests/buffer/stringFuncs.du b/tests/buffer/stringFuncs.du index f19dc5e4f..6e156c146 100644 --- a/tests/buffer/stringFuncs.du +++ b/tests/buffer/stringFuncs.du @@ -35,13 +35,13 @@ class TestBufferStringFuncs < UnitTest { const b = Buffer.fromString("Dictu!").unwrap(); var res = b.readString(23); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "start greater or equals then buffer length"); + this.assertEquals(res.unwrapError(), "start greater or equals than buffer length"); res = b.readString(3,3); this.assertEquals(res.success(), false); this.assertEquals(res.unwrapError(), "string length is 0"); res = b.readString(3,34); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "end greater then buffer length"); + this.assertEquals(res.unwrapError(), "end greater than buffer length"); } } diff --git a/tests/buffer/subarray.du b/tests/buffer/subarray.du index 9320788f6..1ac61b649 100644 --- a/tests/buffer/subarray.du +++ b/tests/buffer/subarray.du @@ -32,10 +32,10 @@ class TestBufferSubArray < UnitTest { const b = Buffer.fromString("Dictu!").unwrap(); var res = b.subarray(25); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "start greater or equals then buffer length"); + this.assertEquals(res.unwrapError(), "start greater or equals than buffer length"); res = b.subarray(0, 25); this.assertEquals(res.success(), false); - this.assertEquals(res.unwrapError(), "end greater then buffer length"); + this.assertEquals(res.unwrapError(), "end greater than buffer length"); res = b.subarray(0, 0); this.assertEquals(res.success(), false); this.assertEquals(res.unwrapError(), "array length is 0"); From c800c815bb0b63bc2fcfa59fb0271cabeeab7931 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 29 Jan 2024 23:55:37 +0100 Subject: [PATCH 100/148] fix: use existing memory routines --- src/optionals/buffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 62b47c756..1bf039812 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -12,7 +12,7 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity); void freeBuffer(DictuVM *vm, ObjAbstract *abstract) { Buffer *buffer = (Buffer *)abstract->data; - free(buffer->bytes); + FREE_ARRAY(vm, uint8_t, buffer->bytes, buffer->size); FREE(vm, Buffer, abstract->data); } @@ -88,7 +88,7 @@ static Value bufferResize(DictuVM *vm, int argCount, Value *args) { vm, "size must be greater than 0 and smaller than 2147483647"); } Buffer *buffer = AS_BUFFER(args[0]); - buffer->bytes = realloc(buffer->bytes, capacity); + buffer->bytes = reallocate(vm, buffer->bytes, buffer->size, capacity); if (capacity > buffer->size) { // 0 init everything if we grew the buffer size_t added = capacity - buffer->size; @@ -933,7 +933,8 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { Buffer *buffer = ALLOCATE(vm, Buffer, 1); buffer->bigEndian = false; - buffer->bytes = calloc(1, capacity); + buffer->bytes = ALLOCATE(vm, uint8_t, capacity); + memset(buffer->bytes, 0, capacity); buffer->size = capacity; /** From 87df7a61444a5c9d4b5bfc3b6889b97e2f3fa02c Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 30 Jan 2024 00:00:46 +0100 Subject: [PATCH 101/148] refactor: remove grayFunc from buffer --- src/optionals/buffer.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/optionals/buffer.c b/src/optionals/buffer.c index 1bf039812..101569395 100644 --- a/src/optionals/buffer.c +++ b/src/optionals/buffer.c @@ -24,21 +24,12 @@ char *bufferToString(ObjAbstract *abstract) { return bufferString; } -void grayBuffer(DictuVM *vm, ObjAbstract *abstract) { - (void)vm; - Buffer *ffi = (Buffer *)abstract->data; - - if (ffi == NULL) - return; -} - uint8_t *swap(uint8_t *ptr, size_t len, bool bigEndian) { if (len < 2) return ptr; if (!bigEndian && !IS_BIG_ENDIAN) { return ptr; } else if (IS_BIG_ENDIAN && bigEndian) { - return ptr; } int start = 0; @@ -994,7 +985,6 @@ ObjAbstract *newBufferObj(DictuVM *vm, double capacity) { defineNative(vm, &abstract->values, "writeDoubleBE", bufferWritefloat64BE); abstract->data = buffer; - abstract->grayFunc = grayBuffer; pop(vm); return abstract; From 7c15a8ab082d194b2e2d98e24240c696e98a39df Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Mon, 29 Jan 2024 16:22:58 -0700 Subject: [PATCH 102/148] update prettyPrint implementation Signed-off-by: Brian Downs --- src/optionals/object/object.c | 12 +++++++++++- tests/object/import.du | 1 - tests/object/prettyPrint.du | 30 ------------------------------ 3 files changed, 11 insertions(+), 32 deletions(-) delete mode 100644 tests/object/prettyPrint.du diff --git a/src/optionals/object/object.c b/src/optionals/object/object.c index 17f5b5865..ff5553d39 100644 --- a/src/optionals/object/object.c +++ b/src/optionals/object/object.c @@ -65,7 +65,17 @@ static Value objectPrettyPrint(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } - return OBJ_VAL(stringify(vm, argCount, args)); + Value out = stringify(vm, argCount, args); + ObjResult *res = AS_RESULT(out); + if (res->status == ERR) { + runtimeError(vm, AS_CSTRING(res->value)); + return EMPTY_VAL; + } + + printValue(res->value); + printf("\n"); + + return NIL_VAL; } Value createObjectModule(DictuVM *vm) { diff --git a/tests/object/import.du b/tests/object/import.du index 30c20717d..3780daa58 100644 --- a/tests/object/import.du +++ b/tests/object/import.du @@ -6,4 +6,3 @@ import "createFrom.du"; import "hash.du"; -import "prettyPrint.du"; diff --git a/tests/object/prettyPrint.du b/tests/object/prettyPrint.du deleted file mode 100644 index 9f999459a..000000000 --- a/tests/object/prettyPrint.du +++ /dev/null @@ -1,30 +0,0 @@ -/** - * prettyPrint.du - * - * Testing the Object.prettyPrint method - */ -from UnitTest import UnitTest; - -import Object; - -class Test {} - -class TestObjectPrettyPrint < UnitTest { - testObjectPrettyPrint() { - this.assertEquals(Object.prettyPrint(1).unwrap(), "1"); - this.assertEquals(Object.prettyPrint("1").unwrap(), '"1"'); - this.assertEquals(Object.prettyPrint([1, 2, 3]).unwrap(), '[1, 2, 3]'); - this.assertEquals(Object.prettyPrint({"a": 1}).unwrap(), '{"a": 1}'); - this.assertEquals(Object.prettyPrint(nil).unwrap(), 'null'); - this.assertEquals(Object.prettyPrint(true).unwrap(), 'true'); - this.assertEquals(Object.prettyPrint(false).unwrap(), 'false'); - this.assertError(Object.prettyPrint(Test())); - } - - testObjectPrettyPrintWithIndent() { - this.assertEquals(Object.prettyPrint([1, 2, 3], 2).unwrap(), '[\n 1,\n 2,\n 3\n]'); - this.assertEquals(Object.prettyPrint({"a": 1}, 2).unwrap(), '{\n "a": 1\n}'); - } -} - -TestObjectPrettyPrint().run(); From 1ba4c06b3a7eea95196fd9029fd8d494f11a0ccc Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Tue, 30 Jan 2024 09:40:02 +0000 Subject: [PATCH 103/148] Skip kill test for now --- tests/process/kill.du | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/process/kill.du b/tests/process/kill.du index 2328522cb..c528e31e4 100644 --- a/tests/process/kill.du +++ b/tests/process/kill.du @@ -17,7 +17,8 @@ class TestProcessKill < UnitTest { this.assertEquals(res, "No such process"); } - testProcessKillNoSignal() { + // TODO: Look into this test + testProcessKillNoSignal_skipped() { Process.exec(["sleep", "100"]); const out = Process.run(["pgrep", "sleep"], true).unwrap(); From b99930acffa043cb680ec5e9d59aaa81cc0fbf29 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Tue, 30 Jan 2024 09:47:07 +0000 Subject: [PATCH 104/148] Update documentation for prettyPrint --- docs/docs/standard-lib/object.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/docs/standard-lib/object.md b/docs/docs/standard-lib/object.md index c1d754f97..cf3ced1f8 100644 --- a/docs/docs/standard-lib/object.md +++ b/docs/docs/standard-lib/object.md @@ -62,21 +62,21 @@ This method will return a string of the object's hash value. Object.hash("Dictu"); ``` -### Object.prettyPrint(Value, Number: indent -> Optional) -> Result\ +### Object.prettyPrint(Value, Number: indent -> Optional) -This method will return a string representation of the given value. +This method will output to stdout a string representation of the given value. **NOTE** Strings, dicts, lists, numbers, booleans, and nil are valid values for pretty printing at this time. ```cs -Object.prettyPrint([1, 2, 3]).unwrap(); +Object.prettyPrint([1, 2, 3]); // Output '[1, 2, 3]' ``` ```cs -Object.prettyPrint({"a": 1}, 4).unwrap(); +Object.prettyPrint({"a": 1}, 4); // Output ' From 7fe7c3910f459f019a4f4bc89adb065d8ad6d217 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 30 Jan 2024 19:59:52 -0700 Subject: [PATCH 105/148] add dict.toObj(Object) method Signed-off-by: Brian Downs --- docs/docs/collections/dictionaries.md | 20 ++++++++++++++-- src/vm/datatypes/dicts/dict-source.h | 17 ++++++++++++++ src/vm/datatypes/dicts/dict.du | 19 ++++++++++++++- tests/dicts/import.du | 1 + tests/dicts/toObj.du | 34 +++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 tests/dicts/toObj.du diff --git a/docs/docs/collections/dictionaries.md b/docs/docs/collections/dictionaries.md index 6a3d0a897..94a6f8844 100644 --- a/docs/docs/collections/dictionaries.md +++ b/docs/docs/collections/dictionaries.md @@ -146,7 +146,7 @@ myDict.forEach(def (key, value) => { }); ``` -### dict.merge(Dict) +### dict.merge(Dict) -> Dict To merge two dicts together we use `.merge`. This operation will take a shallow copy of the dict the `.merge` method was called on and add any items from the dictionary passed into the method. If there are keys that exist in both dictionaries @@ -159,4 +159,20 @@ const dictTwo = {"key3": 4,"key1":0}; const mergedDict = dictOne.merge(dictTwo); mergedDict; //{"key2": 3, "key": 1, "key3": 4, "key1": 0} -``` \ No newline at end of file +``` + +### dict.toObj(Dict, Object) -> Object + +Returns an object created from the given dict and class ref. Dictionary fields that aren't strings are converted to strings and set on the object. To retrieve those fields, use the `.getAttribute(String)` method. + +```cs +class A {} + +const dict = {"key": 1, "key1": 2, "key2": 3}; +const obj = dict.toObj(A()); + +obj; // +obj.key // 1 +obj.key1 // 2 +obj.key2 // 3 +``` diff --git a/src/vm/datatypes/dicts/dict-source.h b/src/vm/datatypes/dicts/dict-source.h index 0e6a6732c..06bb6931b 100644 --- a/src/vm/datatypes/dicts/dict-source.h +++ b/src/vm/datatypes/dicts/dict-source.h @@ -4,6 +4,10 @@ " *\n" \ " * We should always strive to write methods in C where possible.\n" \ " */\n" \ +"\n" \ +"import Object;\n" \ +"\n" \ +"\n" \ "def forEach(dict, func) {\n" \ " const dictKeys = dict.keys();\n" \ "\n" \ @@ -21,4 +25,17 @@ "\n" \ " return newDict;\n" \ "}\n" \ +"\n" \ +"def toObj(dict, obj) {\n" \ +" dict.forEach(def(k, v) => {\n" \ +" if (type(k) != 'string') {\n" \ +" const fieldName = k.toString();\n" \ +" obj.setAttribute(fieldName, v);\n" \ +" return;\n" \ +" }\n" \ +" obj.setAttribute(k, v);\n" \ +" });\n" \ +"\n" \ +" return obj;\n" \ +"}\n" \ diff --git a/src/vm/datatypes/dicts/dict.du b/src/vm/datatypes/dicts/dict.du index 8fc79237b..e700adccd 100644 --- a/src/vm/datatypes/dicts/dict.du +++ b/src/vm/datatypes/dicts/dict.du @@ -4,6 +4,10 @@ * * We should always strive to write methods in C where possible. */ + +import Object; + + def forEach(dict, func) { const dictKeys = dict.keys(); @@ -20,4 +24,17 @@ def merge(dict, anotherDict) { }); return newDict; -} \ No newline at end of file +} + +def toObj(dict, obj) { + dict.forEach(def(k, v) => { + if (type(k) != 'string') { + const fieldName = k.toString(); + obj.setAttribute(fieldName, v); + return; + } + obj.setAttribute(k, v); + }); + + return obj; +} diff --git a/tests/dicts/import.du b/tests/dicts/import.du index f755da741..671f5f690 100644 --- a/tests/dicts/import.du +++ b/tests/dicts/import.du @@ -15,3 +15,4 @@ import "toString.du"; import "toBool.du"; import "forEach.du"; import "merge.du"; +import "toObj.du"; diff --git a/tests/dicts/toObj.du b/tests/dicts/toObj.du new file mode 100644 index 000000000..ea60dae91 --- /dev/null +++ b/tests/dicts/toObj.du @@ -0,0 +1,34 @@ +/** +* toObj.du +* +* Testing the dict.toObj() method +* +* .toObj() returns an object created from the given dict and class ref. +*/ +from UnitTest import UnitTest; + + +class Test {} + +class TestDictToObj < UnitTest { + testDictToObj() { + const myDict = { + "key": 1, + "key1": true, + true: false, + false: true, + nil: 10, + 10: nil, + 10.5: 10.5 + }; + const obj = myDict.toObj(Test()); + this.assertNotNil(obj); + this.assertEquals(obj.key, 1); + this.assertEquals(obj.getAttribute("true"), false); + this.assertEquals(obj.getAttribute("false"), true); + this.assertEquals(obj.getAttribute("nil"), 10); + this.assertEquals(obj.getAttribute("10.5"), 10.5); + } +} + +TestDictToObj().run(); \ No newline at end of file From 6b9de28b889dd931912e0f3ab85a5e98b4072ac3 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Tue, 30 Jan 2024 20:04:22 -0700 Subject: [PATCH 106/148] remove unnecessary import Signed-off-by: Brian Downs --- src/vm/datatypes/dicts/dict.du | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/vm/datatypes/dicts/dict.du b/src/vm/datatypes/dicts/dict.du index e700adccd..c0068b91a 100644 --- a/src/vm/datatypes/dicts/dict.du +++ b/src/vm/datatypes/dicts/dict.du @@ -4,10 +4,6 @@ * * We should always strive to write methods in C where possible. */ - -import Object; - - def forEach(dict, func) { const dictKeys = dict.keys(); From a6fe6ce69f12ec830d25758ca9a6d42801f41d0c Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 31 Jan 2024 22:51:41 +0100 Subject: [PATCH 107/148] fix docs --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 294828177..0eb5e17bd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,7 +19,7 @@ import JSON; HTTP.get("https://api.coindesk.com/v1/bpi/currentprice.json").match( def (response) => { - const data = JSON.parse(response["content"]).unwrap(); + const data = JSON.parse(response.content).unwrap(); print("${} per BTC".format(data["bpi"]["USD"]["rate"])); // $10,577.70 per BTC }, def (error) => print(error) From 590fa5ade8cb3119e0b9821d619cbf17cecf4988 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 31 Jan 2024 22:58:40 +0100 Subject: [PATCH 108/148] more dict doc fixes --- docs/docs/collections/dictionaries.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/collections/dictionaries.md b/docs/docs/collections/dictionaries.md index 94a6f8844..c7efd68a6 100644 --- a/docs/docs/collections/dictionaries.md +++ b/docs/docs/collections/dictionaries.md @@ -38,14 +38,14 @@ Updating a value within a dictionary uses the same syntax, except you supply a v ```cs var myDict = {"key": 1, "key1": true}; -var myDict["key"] = false; // {"key": false, "key1": true} +myDict["key"] = false; // {"key": false, "key1": true} ``` Adding a value to a dictionary is the same as updating a value, however if the key does not exist it is created. ```cs var myDict = {"key": 1, "key1": true}; -var myDict["key2"] = nil; // {"key": false, "key1": true, "key3": nil} +myDict["key2"] = nil; // {"key": 1, "key1": true, "key2": nil} ``` ### dict.get(String, value: default -> Optional) -> Dict From cfeb49789f2e80699a6c18cd4dccd36ac2fcfd89 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 3 Feb 2024 02:35:40 +0100 Subject: [PATCH 109/148] refactor: use function ptrs instead of linking --- src/optionals/ffi/ffi.c | 122 +++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 40 deletions(-) diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 62683afda..17df27d59 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -1,27 +1,59 @@ #include "ffi.h" #include - typedef struct { - void* library; - char* path; + void *library; + char *path; int size; - char** names; + char **names; } FFIInstance; typedef struct _vm_external vm_external; typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); - -#define AS_FFI_INSTANCE(v) ((FFIInstance*)AS_ABSTRACT(v)->data) - +typedef int init_func_definition_t(void **function_ptrs); + +#define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) + +void *ffi_function_pointers[] = { + ©String, + &newList, + &newDict, + &newSet, + &newFile, + &newAbstract, + &newResult, + &newResultSuccess, + &newResultError, + &push, + &peek, + &runtimeError, + &pop, + &isFalsey, + &valuesEqual, + &initValueArray, + &writeValueArray, + &freeValueArray, + &dictSet, + &dictGet, + &dictDelete, + &setGet, + &setInsert, + &setDelete, + &valueToString, + &valueTypeToString, + &printValue, + &printValueError, + &compareStringLess, + &compareStringGreater +}; void freeFFI(DictuVM *vm, ObjAbstract *abstract) { - FFIInstance *instance = (FFIInstance*)abstract->data; + FFIInstance *instance = (FFIInstance *)abstract->data; free(instance->path); - if(instance->size > 0){ - for(int i = 0; i < instance->size; i++){ - if(instance->names[i] != NULL) + if (instance->size > 0) { + for (int i = 0; i < instance->size; i++) { + if (instance->names[i] != NULL) free(instance->names[i]); } free(instance->names); @@ -33,44 +65,45 @@ void freeFFI(DictuVM *vm, ObjAbstract *abstract) { char *ffiToString(ObjAbstract *abstract) { UNUSED(abstract); - char *ffiString = malloc(sizeof(char) * 11+3); - snprintf(ffiString, 11+3, ""); + char *ffiString = malloc(sizeof(char) * 11 + 3); + snprintf(ffiString, 11 + 3, ""); return ffiString; } void grayFFI(DictuVM *vm, ObjAbstract *abstract) { (void)vm; - FFIInstance *ffi = (FFIInstance*)abstract->data; - - if (ffi == NULL) return; + FFIInstance *ffi = (FFIInstance *)abstract->data; + if (ffi == NULL) + return; } static Value ffiInstanceInvoke(DictuVM *vm, int argCount, Value *args) { - if(argCount < 1){ - runtimeError(vm, "invoke() takes at least one argument (%d given)", argCount-1); + if (argCount < 1) { + runtimeError(vm, "invoke() takes at least one argument (%d given)", + argCount - 1); return EMPTY_VAL; } - FFIInstance* instance = AS_FFI_INSTANCE(args[0]); - ObjString* symbol = AS_STRING(args[1]); + FFIInstance *instance = AS_FFI_INSTANCE(args[0]); + ObjString *symbol = AS_STRING(args[1]); bool found = false; - for(int i = 0; i < instance->size; i++) { - if(instance->names[i]) { - if(strcmp(instance->names[i], symbol->chars) == 0){ + for (int i = 0; i < instance->size; i++) { + if (instance->names[i]) { + if (strcmp(instance->names[i], symbol->chars) == 0) { found = true; break; } } } - if(!found){ + if (!found) { runtimeError(vm, "symbol not found: %s", symbol->chars); return EMPTY_VAL; } - function_definition_t* ptr = dlsym(instance->library, symbol->chars); + function_definition_t *ptr = dlsym(instance->library, symbol->chars); Value res = EMPTY_VAL; - if(argCount == 1) + if (argCount == 1) res = ptr(vm, 0, NULL); else - res = ptr(vm, argCount-1, args+2); + res = ptr(vm, argCount - 1, args + 2); return res; } @@ -79,35 +112,43 @@ static Value load(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "load() takes 2 arguments (%d given)", argCount); return EMPTY_VAL; } - ObjString* path = AS_STRING(args[0]); + ObjString *path = AS_STRING(args[0]); void *library = dlopen(path->chars, RTLD_LAZY); - if(!library) { + if (!library) { runtimeError(vm, "Couldn't load shared object: %s", path->chars); return EMPTY_VAL; } - ObjList* symbols = AS_LIST(args[1]); + init_func_definition_t *init_func = + dlsym(library, "dictu_internal_ffi_init"); + // call init function to give ffi module the required pointers to the function of the vm. + if (!init_func || init_func((void**)&ffi_function_pointers) != 0) { + runtimeError(vm, "Couldn't initialize ffi api: %s", path->chars); + dlclose(library); + return EMPTY_VAL; + } + ObjList *symbols = AS_LIST(args[1]); ObjAbstract *abstract = newAbstract(vm, freeFFI, ffiToString); push(vm, OBJ_VAL(abstract)); FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); - instance->path = malloc(path->length+1); + instance->path = malloc(path->length + 1); instance->path[path->length] = '\0'; memcpy(instance->path, path->chars, path->length); instance->library = library; instance->size = symbols->values.count; - if(instance->size > 0) { - instance->names = malloc(sizeof(char*) * instance->size); - for(int i = 0; i< symbols->values.count; i+= 1){ + if (instance->size > 0) { + instance->names = malloc(sizeof(char *) * instance->size); + for (int i = 0; i < symbols->values.count; i += 1) { Value v = symbols->values.values[i]; - if(!IS_STRING(v)) { + if (!IS_STRING(v)) { instance->names[i] = NULL; } else { - ObjString* sym = AS_STRING(v); - if(dlsym(instance->library, sym->chars) == NULL){ + ObjString *sym = AS_STRING(v); + if (dlsym(instance->library, sym->chars) == NULL) { runtimeError(vm, "Couldn't load symbol: %s", sym->chars); return EMPTY_VAL; } - instance->names[i] = malloc(sym->length+1); + instance->names[i] = malloc(sym->length + 1); instance->names[i][sym->length] = '\0'; memcpy(instance->names[i], sym->chars, sym->length); } @@ -132,8 +173,9 @@ Value createFFIModule(DictuVM *vm) { push(vm, OBJ_VAL(module)); defineNative(vm, &module->values, "load", load); - defineNativeProperty(vm, &module->values, "suffix", OBJ_VAL( - copyString(vm, LIB_EXTENSION, LIB_EXTENSION_STRLEN))); + defineNativeProperty( + vm, &module->values, "suffix", + OBJ_VAL(copyString(vm, LIB_EXTENSION, LIB_EXTENSION_STRLEN))); pop(vm); pop(vm); From 232955bf5d056390f399a89d2307359074c391dc Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 3 Feb 2024 02:42:40 +0100 Subject: [PATCH 110/148] feat: add wip ffi example. --- examples/ffi-example/CMakeLists.txt | 4 + examples/ffi-example/ffi.du | 8 + examples/ffi-example/src/dictu-include.h | 619 +++++++++++++++++++++++ examples/ffi-example/src/lib.c | 13 + 4 files changed, 644 insertions(+) create mode 100644 examples/ffi-example/CMakeLists.txt create mode 100644 examples/ffi-example/ffi.du create mode 100644 examples/ffi-example/src/dictu-include.h create mode 100644 examples/ffi-example/src/lib.c diff --git a/examples/ffi-example/CMakeLists.txt b/examples/ffi-example/CMakeLists.txt new file mode 100644 index 000000000..589700d55 --- /dev/null +++ b/examples/ffi-example/CMakeLists.txt @@ -0,0 +1,4 @@ +PROJECT("ffi-test") +set(CMAKE_C_STANDARD 11) +add_library(ffi-test SHARED src/lib.c) + diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du new file mode 100644 index 000000000..d5d44e233 --- /dev/null +++ b/examples/ffi-example/ffi.du @@ -0,0 +1,8 @@ +import FFI; + +const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix), ["dictu_ffi_test", "dictu_ffi_test_str"]); +for(var i = 0; i < 25; i+=1) { + print(mod.invoke("dictu_ffi_test", 20, i*2)); + print(mod.invoke("dictu_ffi_test_str")); + // Weißenseer Weg 7 +} \ No newline at end of file diff --git a/examples/ffi-example/src/dictu-include.h b/examples/ffi-example/src/dictu-include.h new file mode 100644 index 000000000..3ab02da02 --- /dev/null +++ b/examples/ffi-example/src/dictu-include.h @@ -0,0 +1,619 @@ +#ifndef dictumod_include_h +#define dictumod_include_h + +#include +#include +#include +#include + +#define UNUSED(__x__) (void) __x__ + +#define MAX_ERROR_LEN 256 + +#define ERROR_RESULT \ +do { \ +char buf[MAX_ERROR_LEN]; \ +getStrerror(buf, errno); \ +return newResultError(vm, buf); \ +} while (false) + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifdef _WIN32 +#define DIR_SEPARATOR '\\' +#define DIR_ALT_SEPARATOR '/' +#define DIR_SEPARATOR_AS_STRING "\\" +#define DIR_SEPARATOR_STRLEN 1 +#define PATH_DELIMITER ';' +#define PATH_DELIMITER_AS_STRING ";" +#define PATH_DELIMITER_STRLEN 1 +#else +#define HAS_REALPATH +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_AS_STRING "/" +#define DIR_SEPARATOR_STRLEN 1 +#define PATH_DELIMITER ':' +#define PATH_DELIMITER_AS_STRING ":" +#define PATH_DELIMITER_STRLEN 1 +#endif + +#ifdef DIR_ALT_SEPARATOR +#define IS_DIR_SEPARATOR(c) ((c) == DIR_SEPARATOR || (c) == DIR_ALT_SEPARATOR) +#else +#define IS_DIR_SEPARATOR(c) (c == DIR_SEPARATOR) +#endif + +#define DEBUG_PRINT_CODE +#define DEBUG_TRACE_EXECUTION +#define DEBUG_TRACE_GC +#define DEBUG_TRACE_MEM + +#ifndef _MSC_VER +#define COMPUTED_GOTO +#endif + +#undef DEBUG_PRINT_CODE +#undef DEBUG_TRACE_EXECUTION +#undef DEBUG_TRACE_GC +#undef DEBUG_TRACE_MEM + +// #define DEBUG_STRESS_GC +// #define DEBUG_FINAL_MEM + +#define UINT8_COUNT (UINT8_MAX + 1) + +typedef struct sObj Obj; +typedef struct sObjString ObjString; +typedef struct sObjList ObjList; +typedef struct sObjDict ObjDict; +typedef struct sObjSet ObjSet; +typedef struct sObjFile ObjFile; +typedef struct sObjAbstract ObjAbstract; +typedef struct sObjResult ObjResult; + +// A mask that selects the sign bit. +#define SIGN_BIT ((uint64_t)1 << 63) + +// The bits that must be set to indicate a quiet NaN. +#define QNAN ((uint64_t)0x7ffc000000000000) + +// Tag values for the different singleton values. +#define TAG_NIL 1 +#define TAG_FALSE 2 +#define TAG_TRUE 3 +#define TAG_EMPTY 4 + +typedef uint64_t Value; + +#define IS_BOOL(v) (((v) | 1) == TRUE_VAL) +#define IS_NIL(v) ((v) == NIL_VAL) +#define IS_EMPTY(v) ((v) == EMPTY_VAL) +// If the NaN bits are set, it's not a number. +#define IS_NUMBER(v) (((v) & QNAN) != QNAN) +#define IS_OBJ(v) (((v) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) + +#define AS_BOOL(v) ((v) == TRUE_VAL) +#define AS_NUMBER(v) valueToNum(v) +#define AS_OBJ(v) ((Obj*)(uintptr_t)((v) & ~(SIGN_BIT | QNAN))) + +#define BOOL_VAL(boolean) ((boolean) ? TRUE_VAL : FALSE_VAL) +#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) +#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) +#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) +#define EMPTY_VAL ((Value)(uint64_t)(QNAN | TAG_EMPTY)) +#define NUMBER_VAL(num) numToValue(num) +// The triple casting is necessary here to satisfy some compilers: +// 1. (uintptr_t) Convert the pointer to a number of the right size. +// 2. (uint64_t) Pad it up to 64 bits in 32-bit builds. +// 3. Or in the bits to make a tagged Nan. +// 4. Cast to a typedef'd value. +#define OBJ_VAL(obj) \ + (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj)) + +// A union to let us reinterpret a double as raw bits and back. +typedef union { + uint64_t bits64; + uint32_t bits32[2]; + double num; +} DoubleUnion; + +static inline double valueToNum(Value value) { + DoubleUnion data; + data.bits64 = value; + return data.num; +} + +static inline Value numToValue(double num) { + DoubleUnion data; + data.num = num; + return data.bits64; +} + +typedef struct { + int capacity; + int count; + Value *values; +} ValueArray; + +typedef struct { + ObjString *key; + Value value; + uint32_t psl; +} Entry; + +typedef struct { + int count; + int capacity; + Entry *entries; +} Table; + + +#define OBJ_TYPE(value) (AS_OBJ(value)->type) + +#define AS_MODULE(value) ((ObjModule*)AS_OBJ(value)) +#define AS_BOUND_METHOD(value) ((ObjBoundMethod*)AS_OBJ(value)) +#define AS_CLASS(value) ((ObjClass*)AS_OBJ(value)) +#define AS_ENUM(value) ((ObjEnum*)AS_OBJ(value)) +#define AS_CLOSURE(value) ((ObjClosure*)AS_OBJ(value)) +#define AS_FUNCTION(value) ((ObjFunction*)AS_OBJ(value)) +#define AS_INSTANCE(value) ((ObjInstance*)AS_OBJ(value)) +#define AS_NATIVE(value) (((ObjNative*)AS_OBJ(value))->function) +#define AS_STRING(value) ((ObjString*)AS_OBJ(value)) +#define AS_CSTRING(value) (((ObjString*)AS_OBJ(value))->chars) +#define AS_LIST(value) ((ObjList*)AS_OBJ(value)) +#define AS_DICT(value) ((ObjDict*)AS_OBJ(value)) +#define AS_SET(value) ((ObjSet*)AS_OBJ(value)) +#define AS_FILE(value) ((ObjFile*)AS_OBJ(value)) +#define AS_ABSTRACT(value) ((ObjAbstract*)AS_OBJ(value)) +#define AS_RESULT(value) ((ObjResult*)AS_OBJ(value)) + +#define IS_MODULE(value) isObjType(value, OBJ_MODULE) +#define IS_BOUND_METHOD(value) isObjType(value, OBJ_BOUND_METHOD) +#define IS_CLASS(value) isObjType(value, OBJ_CLASS) +#define IS_DEFAULT_CLASS(value) isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_DEFAULT +#define IS_TRAIT(value) isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_TRAIT +#define IS_ENUM(value) isObjType(value, OBJ_ENUM) +#define IS_CLOSURE(value) isObjType(value, OBJ_CLOSURE) +#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION) +#define IS_INSTANCE(value) isObjType(value, OBJ_INSTANCE) +#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE) +#define IS_STRING(value) isObjType(value, OBJ_STRING) +#define IS_LIST(value) isObjType(value, OBJ_LIST) +#define IS_DICT(value) isObjType(value, OBJ_DICT) +#define IS_SET(value) isObjType(value, OBJ_SET) +#define IS_FILE(value) isObjType(value, OBJ_FILE) +#define IS_ABSTRACT(value) isObjType(value, OBJ_ABSTRACT) +#define IS_RESULT(value) isObjType(value, OBJ_RESULT) + +typedef enum { + OBJ_MODULE, + OBJ_BOUND_METHOD, + OBJ_CLASS, + OBJ_ENUM, + OBJ_CLOSURE, + OBJ_FUNCTION, + OBJ_INSTANCE, + OBJ_NATIVE, + OBJ_STRING, + OBJ_LIST, + OBJ_DICT, + OBJ_SET, + OBJ_FILE, + OBJ_ABSTRACT, + OBJ_RESULT, + OBJ_UPVALUE +} ObjType; + +typedef enum { + CLASS_DEFAULT, + CLASS_ABSTRACT, + CLASS_TRAIT +} ClassType; + +typedef enum { + ACCESS_PUBLIC, + ACCESS_PRIVATE +} AccessLevel; + +typedef enum { + TYPE_FUNCTION, + TYPE_ARROW_FUNCTION, + TYPE_INITIALIZER, + TYPE_METHOD, + TYPE_STATIC, + TYPE_ABSTRACT, + TYPE_TOP_LEVEL +} FunctionType; + +struct sObj { + ObjType type; + bool isDark; + struct sObj *next; +}; + +typedef struct sUpvalue { + Obj obj; + + // Pointer to the variable this upvalue is referencing. + Value *value; + + // If the upvalue is closed (i.e. the local variable it was pointing + // to has been popped off the stack) then the closed-over value is + // hoisted out of the stack into here. [value] is then be changed to + // point to this. + Value closed; + + // Open upvalues are stored in a linked list. This points to the next + // one in that list. + struct sUpvalue *next; +} ObjUpvalue; + +typedef struct { + Obj obj; + ObjString* name; + ObjString* path; + Table values; +} ObjModule; + +typedef struct { + int count; + int capacity; + uint8_t *code; + int *lines; + ValueArray constants; +} Chunk; + +typedef struct { + Obj obj; + int isVariadic; + int arity; + int arityOptional; + int upvalueCount; + Chunk chunk; + ObjString *name; + FunctionType type; + AccessLevel accessLevel; + ObjModule* module; + int propertyCount; + int *propertyNames; + int *propertyIndexes; + int privatePropertyCount; + int *privatePropertyNames; + int *privatePropertyIndexes; +} ObjFunction; + + +#define STACK_MAX (64 * UINT8_COUNT) +typedef struct { + Obj obj; + ObjFunction *function; + ObjUpvalue **upvalues; + int upvalueCount; +} ObjClosure; + +typedef struct { + ObjClosure *closure; + uint8_t *ip; + Value *slots; +} CallFrame; + +struct _vm { + Value stack[STACK_MAX]; + Value *stackTop; + bool repl; + CallFrame *frames; + int frameCount; + int frameCapacity; + ObjModule *lastModule; + Table modules; + Table globals; + Table constants; + Table strings; + Table numberMethods; + Table boolMethods; + Table nilMethods; + Table stringMethods; + Table listMethods; + Table dictMethods; + Table setMethods; + Table fileMethods; + Table classMethods; + Table instanceMethods; + Table resultMethods; + Table enumMethods; + ObjString *initString; + ObjString *annotationString; + ObjString *replVar; + ObjUpvalue *openUpvalues; + size_t bytesAllocated; + size_t nextGC; + Obj *objects; + int grayCount; + int grayCapacity; + Obj **grayStack; + int argc; + char **argv; +}; + +#define DICTU_MAJOR_VERSION "0" +#define DICTU_MINOR_VERSION "29" +#define DICTU_PATCH_VERSION "0" + +#define DICTU_STRING_VERSION "Dictu Version: " DICTU_MAJOR_VERSION "." DICTU_MINOR_VERSION "." DICTU_PATCH_VERSION "\n" + +typedef struct _vm DictuVM; + +typedef Value (*NativeFn)(DictuVM *vm, int argCount, Value *args); + +typedef struct { + Obj obj; + NativeFn function; +} ObjNative; + +struct sObjString { + Obj obj; + int length; + char *chars; + uint32_t hash; +}; + +struct sObjList { + Obj obj; + ValueArray values; +}; + +typedef struct { + Value key; + Value value; +} DictItem; + +struct sObjDict { + Obj obj; + int count; + int activeCount; + int capacityMask; + DictItem *entries; +}; + +typedef struct { + Value value; + bool deleted; +} SetItem; + +struct sObjSet { + Obj obj; + int count; + int capacityMask; + SetItem *entries; +}; + +struct sObjFile { + Obj obj; + FILE *file; + char *path; + char *openType; +}; + +typedef void (*AbstractFreeFn)(DictuVM *vm, ObjAbstract *abstract); +typedef void (*AbstractGrayFn)(DictuVM *vm, ObjAbstract *abstract); +typedef char* (*AbstractTypeFn)(ObjAbstract *abstract); + +struct sObjAbstract { + Obj obj; + Table values; + void *data; + AbstractFreeFn func; + AbstractGrayFn grayFunc; + AbstractTypeFn type; +}; + +typedef enum { + SUCCESS, + ERR +} ResultStatus; + +struct sObjResult { + Obj obj; + ResultStatus status; + Value value; +}; + + +typedef struct sObjClass { + Obj obj; + ObjString *name; + struct sObjClass *superclass; + Table publicMethods; + Table privateMethods; + Table abstractMethods; + Table variables; + Table constants; + ObjDict *classAnnotations; + ObjDict *methodAnnotations; + ObjDict *fieldAnnotations; + ClassType type; +} ObjClass; + +typedef struct sObjEnum { + Obj obj; + ObjString *name; + Table values; +} ObjEnum; + +typedef struct { + Obj obj; + ObjClass *klass; + Table privateAttributes; + Table publicAttributes; +} ObjInstance; + +typedef struct { + Obj obj; + Value receiver; + ObjClosure *method; +} ObjBoundMethod; + +typedef ObjString *copyString_t(DictuVM *vm, const char *chars, int length); + +typedef ObjList *newList_t(DictuVM *vm); + +typedef ObjDict *newDict_t(DictuVM *vm); + +typedef ObjSet *newSet_t(DictuVM *vm); + +typedef ObjFile *newFile_t(DictuVM *vm); + +typedef ObjAbstract *newAbstract_t(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type); + +typedef ObjResult *newResult_t(DictuVM *vm, ResultStatus status, Value value); + +typedef Value newResultSuccess_t(DictuVM *vm, Value value); + +typedef Value newResultError_t(DictuVM *vm, char *errorMsg); + +typedef void push_t(DictuVM *vm, Value value); + +typedef Value peek_t(DictuVM *vm, int distance); + +typedef void runtimeError_t(DictuVM *vm, const char *format, ...); + +typedef Value pop_t(DictuVM *vm); + +typedef bool isFalsey_t(Value value); + +typedef bool valuesEqual_t(Value a, Value b); + +typedef void initValueArray_t(ValueArray *array); + +typedef void writeValueArray_t(DictuVM *vm, ValueArray *array, Value value); + +typedef void freeValueArray_t(DictuVM *vm, ValueArray *array); + +typedef bool dictSet_t(DictuVM *vm, ObjDict *dict, Value key, Value value); + +typedef bool dictGet_t(ObjDict *dict, Value key, Value *value); + +typedef bool dictDelete_t(DictuVM *vm, ObjDict *dict, Value key); + +typedef bool setGet_t(ObjSet *set, Value value); + +typedef bool setInsert_t(DictuVM *vm, ObjSet *set, Value value); + +typedef bool setDelete_t(DictuVM *vm, ObjSet *set, Value value); + +typedef char *valueToString_t(Value value); + +typedef char *valueTypeToString_t(DictuVM *vm, Value value, int *length); + +typedef void printValue_t(Value value); + +typedef void printValueError_t(Value value); + +typedef bool compareStringLess_t(Value a, Value b); + +typedef bool compareStringGreater_t(Value a, Value b); + + +copyString_t* copyString = NULL; + +newList_t* newList = NULL; + +newDict_t* newDict = NULL; + +newSet_t* newSet = NULL; + +newFile_t* newFile = NULL; + +newAbstract_t* newAbstract = NULL; + +newResult_t* newResult = NULL; + +newResultSuccess_t* newResultSuccess = NULL; + +newResultError_t* newResultError = NULL; + +push_t* push = NULL; + +peek_t* peek = NULL; + +runtimeError_t* runtimeError = NULL; + +pop_t* pop = NULL; + +isFalsey_t* isFalsey = NULL; + +valuesEqual_t* valuesEqual = NULL; + +initValueArray_t* initValueArray = NULL; + +writeValueArray_t* writeValueArray = NULL; + +freeValueArray_t* freeValueArray = NULL; + +dictSet_t* dictSet = NULL; + +dictGet_t* dictGet = NULL; + +dictDelete_t* dictDelete = NULL; + +setGet_t* setGet = NULL; + +setInsert_t* setInsert = NULL; + +setDelete_t* setDelete = NULL; + +valueToString_t* valueToString = NULL; + +valueTypeToString_t* valueTypeToString = NULL; + +printValue_t* printValue = NULL; + +printValueError_t* printValueError = NULL; + +compareStringLess_t* compareStringLess = NULL; + +compareStringGreater_t* compareStringGreater = NULL; + +int dictu_internal_ffi_init(void** function_ptrs) { + if(copyString != NULL){ + // we already initialized. + return 1; + } + size_t count = 0; + + copyString = (copyString_t*) function_ptrs[count++]; + newList = (newList_t*) function_ptrs[count++]; + newDict = (newDict_t*) function_ptrs[count++]; + newSet = (newSet_t*) function_ptrs[count++]; + newFile = (newFile_t*) function_ptrs[count++]; + newAbstract = (newAbstract_t*) function_ptrs[count++]; + newResult = (newResult_t*) function_ptrs[count++]; + newResultSuccess = (newResultSuccess_t*) function_ptrs[count++]; + newResultError = (newResultError_t*) function_ptrs[count++]; + push = (push_t*) function_ptrs[count++]; + peek = (peek_t*) function_ptrs[count++]; + runtimeError = (runtimeError_t*) function_ptrs[count++]; + pop = (pop_t*) function_ptrs[count++]; + isFalsey = (isFalsey_t*) function_ptrs[count++]; + valuesEqual = (valuesEqual_t*) function_ptrs[count++]; + initValueArray = (initValueArray_t*) function_ptrs[count++]; + writeValueArray = (writeValueArray_t*) function_ptrs[count++]; + freeValueArray = (freeValueArray_t*) function_ptrs[count++]; + dictSet = (dictSet_t*) function_ptrs[count++]; + dictGet = (dictGet_t*) function_ptrs[count++]; + dictDelete = (dictDelete_t*) function_ptrs[count++]; + setGet = (setGet_t*) function_ptrs[count++]; + setInsert = (setInsert_t*) function_ptrs[count++]; + setDelete = (setDelete_t*) function_ptrs[count++]; + valueToString = (valueToString_t*) function_ptrs[count++]; + valueTypeToString = (valueTypeToString_t*) function_ptrs[count++]; + printValue = (printValue_t*) function_ptrs[count++]; + printValueError = (printValueError_t*) function_ptrs[count++]; + compareStringLess = (compareStringLess_t*) function_ptrs[count++]; + compareStringGreater = (compareStringGreater_t*) function_ptrs[count++]; + return 0; +} + +#endif \ No newline at end of file diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c new file mode 100644 index 000000000..c5f1a0734 --- /dev/null +++ b/examples/ffi-example/src/lib.c @@ -0,0 +1,13 @@ +#include "dictu-include.h" + +Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { + if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ + return NIL_VAL; + } + double a = AS_NUMBER(args[0]); + double b = AS_NUMBER(args[1]); + return NUMBER_VAL(a+b); +} +Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { + return OBJ_VAL(copyString(vm, "Hello world", 11)); +} \ No newline at end of file From fa9d498d902af3e0053aa4ba01e2324c6f701100 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 3 Feb 2024 02:51:22 +0100 Subject: [PATCH 111/148] fix: oops --- examples/ffi-example/ffi.du | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index d5d44e233..0fbf56f1b 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -4,5 +4,4 @@ const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix), ["dictu_ffi_tes for(var i = 0; i < 25; i+=1) { print(mod.invoke("dictu_ffi_test", 20, i*2)); print(mod.invoke("dictu_ffi_test_str")); - // Weißenseer Weg 7 } \ No newline at end of file From ee1b82f55c23c51c30ab3a9fb542484992c6a67f Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sun, 4 Feb 2024 21:44:47 +0100 Subject: [PATCH 112/148] feat: natively define functions rather then to use a distinct invoke function --- examples/ffi-example/ffi.du | 4 +- examples/ffi-example/src/dictu-include.h | 1 + src/optionals/ffi/ffi.c | 66 ++++-------------------- src/vm/object.c | 13 +++++ src/vm/object.h | 2 + src/vm/vm.c | 15 ++++++ 6 files changed, 43 insertions(+), 58 deletions(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index 0fbf56f1b..166bae12e 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -2,6 +2,6 @@ import FFI; const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix), ["dictu_ffi_test", "dictu_ffi_test_str"]); for(var i = 0; i < 25; i+=1) { - print(mod.invoke("dictu_ffi_test", 20, i*2)); - print(mod.invoke("dictu_ffi_test_str")); + print(mod.dictu_ffi_test(1, i*2)); + print(mod.dictu_ffi_test_str()); } \ No newline at end of file diff --git a/examples/ffi-example/src/dictu-include.h b/examples/ffi-example/src/dictu-include.h index 3ab02da02..2c583598a 100644 --- a/examples/ffi-example/src/dictu-include.h +++ b/examples/ffi-example/src/dictu-include.h @@ -407,6 +407,7 @@ struct sObjAbstract { AbstractFreeFn func; AbstractGrayFn grayFunc; AbstractTypeFn type; + bool excludeSelf; }; typedef enum { diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 17df27d59..42886e495 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -4,8 +4,6 @@ typedef struct { void *library; char *path; - int size; - char **names; } FFIInstance; typedef struct _vm_external vm_external; @@ -13,7 +11,7 @@ typedef struct _vm_external vm_external; typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); typedef int init_func_definition_t(void **function_ptrs); -#define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) +// #define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) void *ffi_function_pointers[] = { ©String, @@ -51,13 +49,6 @@ void *ffi_function_pointers[] = { void freeFFI(DictuVM *vm, ObjAbstract *abstract) { FFIInstance *instance = (FFIInstance *)abstract->data; free(instance->path); - if (instance->size > 0) { - for (int i = 0; i < instance->size; i++) { - if (instance->names[i] != NULL) - free(instance->names[i]); - } - free(instance->names); - } dlclose(instance->library); FREE(vm, FFIInstance, abstract->data); } @@ -77,35 +68,6 @@ void grayFFI(DictuVM *vm, ObjAbstract *abstract) { if (ffi == NULL) return; } -static Value ffiInstanceInvoke(DictuVM *vm, int argCount, Value *args) { - if (argCount < 1) { - runtimeError(vm, "invoke() takes at least one argument (%d given)", - argCount - 1); - return EMPTY_VAL; - } - FFIInstance *instance = AS_FFI_INSTANCE(args[0]); - ObjString *symbol = AS_STRING(args[1]); - bool found = false; - for (int i = 0; i < instance->size; i++) { - if (instance->names[i]) { - if (strcmp(instance->names[i], symbol->chars) == 0) { - found = true; - break; - } - } - } - if (!found) { - runtimeError(vm, "symbol not found: %s", symbol->chars); - return EMPTY_VAL; - } - function_definition_t *ptr = dlsym(instance->library, symbol->chars); - Value res = EMPTY_VAL; - if (argCount == 1) - res = ptr(vm, 0, NULL); - else - res = ptr(vm, argCount - 1, args + 2); - return res; -} static Value load(DictuVM *vm, int argCount, Value *args) { if (argCount != 2) { @@ -127,7 +89,7 @@ static Value load(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } ObjList *symbols = AS_LIST(args[1]); - ObjAbstract *abstract = newAbstract(vm, freeFFI, ffiToString); + ObjAbstract *abstract = newAbstractExcludeSelf(vm, freeFFI, ffiToString); push(vm, OBJ_VAL(abstract)); FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); instance->path = malloc(path->length + 1); @@ -135,29 +97,21 @@ static Value load(DictuVM *vm, int argCount, Value *args) { memcpy(instance->path, path->chars, path->length); instance->library = library; - instance->size = symbols->values.count; - if (instance->size > 0) { - instance->names = malloc(sizeof(char *) * instance->size); + if (symbols->values.count) { for (int i = 0; i < symbols->values.count; i += 1) { Value v = symbols->values.values[i]; - if (!IS_STRING(v)) { - instance->names[i] = NULL; - } else { + if (IS_STRING(v)) { ObjString *sym = AS_STRING(v); - if (dlsym(instance->library, sym->chars) == NULL) { - runtimeError(vm, "Couldn't load symbol: %s", sym->chars); + void* funcptr = dlsym(instance->library, sym->chars); + if(!funcptr) { + runtimeError(vm, "Couldn't find symbol: %s in %s", sym->chars, path->chars); + dlclose(library); return EMPTY_VAL; } - instance->names[i] = malloc(sym->length + 1); - instance->names[i][sym->length] = '\0'; - memcpy(instance->names[i], sym->chars, sym->length); + defineNative(vm, &abstract->values, sym->chars, funcptr); } } - } else { - instance->names = NULL; - } - - defineNative(vm, &abstract->values, "invoke", ffiInstanceInvoke); + } abstract->data = instance; abstract->grayFunc = grayFFI; diff --git a/src/vm/object.c b/src/vm/object.c index 68cda4ce3..413b29b8e 100644 --- a/src/vm/object.c +++ b/src/vm/object.c @@ -191,6 +191,19 @@ ObjAbstract *newAbstract(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type) abstract->func = func; abstract->type = type; abstract->grayFunc = NULL; + abstract->excludeSelf = false; + initTable(&abstract->values); + + return abstract; +} + +ObjAbstract *newAbstractExcludeSelf(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type) { + ObjAbstract *abstract = ALLOCATE_OBJ(vm, ObjAbstract, OBJ_ABSTRACT); + abstract->data = NULL; + abstract->func = func; + abstract->type = type; + abstract->grayFunc = NULL; + abstract->excludeSelf = true; initTable(&abstract->values); return abstract; diff --git a/src/vm/object.h b/src/vm/object.h index e86ee1372..69ff5cc00 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -181,6 +181,7 @@ struct sObjAbstract { AbstractFreeFn func; AbstractGrayFn grayFunc; AbstractTypeFn type; + bool excludeSelf; }; typedef enum { @@ -281,6 +282,7 @@ ObjSet *newSet(DictuVM *vm); ObjFile *newFile(DictuVM *vm); ObjAbstract *newAbstract(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type); +ObjAbstract *newAbstractExcludeSelf(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type); ObjResult *newResult(DictuVM *vm, ResultStatus status, Value value); diff --git a/src/vm/vm.c b/src/vm/vm.c index cef7c3c35..4571bcb16 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -365,6 +365,19 @@ static bool callNativeMethod(DictuVM *vm, Value method, int argCount) { return true; } +static bool callNativeMethodExcludeSelf(DictuVM *vm, Value method, int argCount) { + NativeFn native = AS_NATIVE(method); + + Value result = native(vm, argCount, vm->stackTop - (argCount-1) - 1); + + if (IS_EMPTY(result)) + return false; + + vm->stackTop -= argCount + 1; + push(vm, result); + return true; +} + static bool invokeFromClass(DictuVM *vm, ObjClass *klass, ObjString *name, int argCount, bool unpack) { HANDLE_UNPACK @@ -645,6 +658,8 @@ static bool invoke(DictuVM *vm, ObjString *name, int argCount, bool unpack) { Value value; if (tableGet(&abstract->values, name, &value)) { + if(abstract->excludeSelf) + return callNativeMethodExcludeSelf(vm, value, argCount); return callNativeMethod(vm, value, argCount); } From 70a802a1f0f4a9ad32174f2957bd2b17453656e5 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 5 Feb 2024 19:07:44 +0100 Subject: [PATCH 113/148] refactor: only define mod functions within the module --- examples/ffi-example/ffi.du | 2 +- examples/ffi-example/src/dictu-include.h | 322 ++++++++++++----------- examples/ffi-example/src/lib.c | 6 + src/optionals/ffi/ffi.c | 50 ++-- src/optionals/ffi/ffi.h | 4 + 5 files changed, 208 insertions(+), 176 deletions(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index 166bae12e..f87974cd3 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -1,6 +1,6 @@ import FFI; -const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix), ["dictu_ffi_test", "dictu_ffi_test_str"]); +const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); for(var i = 0; i < 25; i+=1) { print(mod.dictu_ffi_test(1, i*2)); print(mod.dictu_ffi_test_str()); diff --git a/examples/ffi-example/src/dictu-include.h b/examples/ffi-example/src/dictu-include.h index 2c583598a..4111054f9 100644 --- a/examples/ffi-example/src/dictu-include.h +++ b/examples/ffi-example/src/dictu-include.h @@ -1,21 +1,28 @@ #ifndef dictumod_include_h #define dictumod_include_h +#ifdef __cplusplus +extern "C" { +#endif #include #include #include #include -#define UNUSED(__x__) (void) __x__ +// This is used ti determine if we can safely load the function pointers without +// UB. +#define FFI_MOD_API_VERSION 1 + +#define UNUSED(__x__) (void)__x__ #define MAX_ERROR_LEN 256 -#define ERROR_RESULT \ -do { \ -char buf[MAX_ERROR_LEN]; \ -getStrerror(buf, errno); \ -return newResultError(vm, buf); \ -} while (false) +#define ERROR_RESULT \ + do { \ + char buf[MAX_ERROR_LEN]; \ + getStrerror(buf, errno); \ + return newResultError(vm, buf); \ + } while (false) #ifndef PATH_MAX #define PATH_MAX 4096 @@ -68,7 +75,7 @@ typedef struct sObj Obj; typedef struct sObjString ObjString; typedef struct sObjList ObjList; typedef struct sObjDict ObjDict; -typedef struct sObjSet ObjSet; +typedef struct sObjSet ObjSet; typedef struct sObjFile ObjFile; typedef struct sObjAbstract ObjAbstract; typedef struct sObjResult ObjResult; @@ -80,37 +87,36 @@ typedef struct sObjResult ObjResult; #define QNAN ((uint64_t)0x7ffc000000000000) // Tag values for the different singleton values. -#define TAG_NIL 1 -#define TAG_FALSE 2 -#define TAG_TRUE 3 -#define TAG_EMPTY 4 +#define TAG_NIL 1 +#define TAG_FALSE 2 +#define TAG_TRUE 3 +#define TAG_EMPTY 4 typedef uint64_t Value; -#define IS_BOOL(v) (((v) | 1) == TRUE_VAL) -#define IS_NIL(v) ((v) == NIL_VAL) -#define IS_EMPTY(v) ((v) == EMPTY_VAL) +#define IS_BOOL(v) (((v) | 1) == TRUE_VAL) +#define IS_NIL(v) ((v) == NIL_VAL) +#define IS_EMPTY(v) ((v) == EMPTY_VAL) // If the NaN bits are set, it's not a number. -#define IS_NUMBER(v) (((v) & QNAN) != QNAN) -#define IS_OBJ(v) (((v) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) - -#define AS_BOOL(v) ((v) == TRUE_VAL) -#define AS_NUMBER(v) valueToNum(v) -#define AS_OBJ(v) ((Obj*)(uintptr_t)((v) & ~(SIGN_BIT | QNAN))) - -#define BOOL_VAL(boolean) ((boolean) ? TRUE_VAL : FALSE_VAL) -#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) -#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) -#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) -#define EMPTY_VAL ((Value)(uint64_t)(QNAN | TAG_EMPTY)) -#define NUMBER_VAL(num) numToValue(num) +#define IS_NUMBER(v) (((v)&QNAN) != QNAN) +#define IS_OBJ(v) (((v) & (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT)) + +#define AS_BOOL(v) ((v) == TRUE_VAL) +#define AS_NUMBER(v) valueToNum(v) +#define AS_OBJ(v) ((Obj *)(uintptr_t)((v) & ~(SIGN_BIT | QNAN))) + +#define BOOL_VAL(boolean) ((boolean) ? TRUE_VAL : FALSE_VAL) +#define FALSE_VAL ((Value)(uint64_t)(QNAN | TAG_FALSE)) +#define TRUE_VAL ((Value)(uint64_t)(QNAN | TAG_TRUE)) +#define NIL_VAL ((Value)(uint64_t)(QNAN | TAG_NIL)) +#define EMPTY_VAL ((Value)(uint64_t)(QNAN | TAG_EMPTY)) +#define NUMBER_VAL(num) numToValue(num) // The triple casting is necessary here to satisfy some compilers: // 1. (uintptr_t) Convert the pointer to a number of the right size. // 2. (uint64_t) Pad it up to 64 bits in 32-bit builds. // 3. Or in the bits to make a tagged Nan. // 4. Cast to a typedef'd value. -#define OBJ_VAL(obj) \ - (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj)) +#define OBJ_VAL(obj) (Value)(SIGN_BIT | QNAN | (uint64_t)(uintptr_t)(obj)) // A union to let us reinterpret a double as raw bits and back. typedef union { @@ -149,43 +155,44 @@ typedef struct { Entry *entries; } Table; - -#define OBJ_TYPE(value) (AS_OBJ(value)->type) - -#define AS_MODULE(value) ((ObjModule*)AS_OBJ(value)) -#define AS_BOUND_METHOD(value) ((ObjBoundMethod*)AS_OBJ(value)) -#define AS_CLASS(value) ((ObjClass*)AS_OBJ(value)) -#define AS_ENUM(value) ((ObjEnum*)AS_OBJ(value)) -#define AS_CLOSURE(value) ((ObjClosure*)AS_OBJ(value)) -#define AS_FUNCTION(value) ((ObjFunction*)AS_OBJ(value)) -#define AS_INSTANCE(value) ((ObjInstance*)AS_OBJ(value)) -#define AS_NATIVE(value) (((ObjNative*)AS_OBJ(value))->function) -#define AS_STRING(value) ((ObjString*)AS_OBJ(value)) -#define AS_CSTRING(value) (((ObjString*)AS_OBJ(value))->chars) -#define AS_LIST(value) ((ObjList*)AS_OBJ(value)) -#define AS_DICT(value) ((ObjDict*)AS_OBJ(value)) -#define AS_SET(value) ((ObjSet*)AS_OBJ(value)) -#define AS_FILE(value) ((ObjFile*)AS_OBJ(value)) -#define AS_ABSTRACT(value) ((ObjAbstract*)AS_OBJ(value)) -#define AS_RESULT(value) ((ObjResult*)AS_OBJ(value)) - -#define IS_MODULE(value) isObjType(value, OBJ_MODULE) -#define IS_BOUND_METHOD(value) isObjType(value, OBJ_BOUND_METHOD) -#define IS_CLASS(value) isObjType(value, OBJ_CLASS) -#define IS_DEFAULT_CLASS(value) isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_DEFAULT -#define IS_TRAIT(value) isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_TRAIT -#define IS_ENUM(value) isObjType(value, OBJ_ENUM) -#define IS_CLOSURE(value) isObjType(value, OBJ_CLOSURE) -#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION) -#define IS_INSTANCE(value) isObjType(value, OBJ_INSTANCE) -#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE) -#define IS_STRING(value) isObjType(value, OBJ_STRING) -#define IS_LIST(value) isObjType(value, OBJ_LIST) -#define IS_DICT(value) isObjType(value, OBJ_DICT) -#define IS_SET(value) isObjType(value, OBJ_SET) -#define IS_FILE(value) isObjType(value, OBJ_FILE) -#define IS_ABSTRACT(value) isObjType(value, OBJ_ABSTRACT) -#define IS_RESULT(value) isObjType(value, OBJ_RESULT) +#define OBJ_TYPE(value) (AS_OBJ(value)->type) + +#define AS_MODULE(value) ((ObjModule *)AS_OBJ(value)) +#define AS_BOUND_METHOD(value) ((ObjBoundMethod *)AS_OBJ(value)) +#define AS_CLASS(value) ((ObjClass *)AS_OBJ(value)) +#define AS_ENUM(value) ((ObjEnum *)AS_OBJ(value)) +#define AS_CLOSURE(value) ((ObjClosure *)AS_OBJ(value)) +#define AS_FUNCTION(value) ((ObjFunction *)AS_OBJ(value)) +#define AS_INSTANCE(value) ((ObjInstance *)AS_OBJ(value)) +#define AS_NATIVE(value) (((ObjNative *)AS_OBJ(value))->function) +#define AS_STRING(value) ((ObjString *)AS_OBJ(value)) +#define AS_CSTRING(value) (((ObjString *)AS_OBJ(value))->chars) +#define AS_LIST(value) ((ObjList *)AS_OBJ(value)) +#define AS_DICT(value) ((ObjDict *)AS_OBJ(value)) +#define AS_SET(value) ((ObjSet *)AS_OBJ(value)) +#define AS_FILE(value) ((ObjFile *)AS_OBJ(value)) +#define AS_ABSTRACT(value) ((ObjAbstract *)AS_OBJ(value)) +#define AS_RESULT(value) ((ObjResult *)AS_OBJ(value)) + +#define IS_MODULE(value) isObjType(value, OBJ_MODULE) +#define IS_BOUND_METHOD(value) isObjType(value, OBJ_BOUND_METHOD) +#define IS_CLASS(value) isObjType(value, OBJ_CLASS) +#define IS_DEFAULT_CLASS(value) \ + isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_DEFAULT +#define IS_TRAIT(value) \ + isObjType(value, OBJ_CLASS) && AS_CLASS(value)->type == CLASS_TRAIT +#define IS_ENUM(value) isObjType(value, OBJ_ENUM) +#define IS_CLOSURE(value) isObjType(value, OBJ_CLOSURE) +#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION) +#define IS_INSTANCE(value) isObjType(value, OBJ_INSTANCE) +#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE) +#define IS_STRING(value) isObjType(value, OBJ_STRING) +#define IS_LIST(value) isObjType(value, OBJ_LIST) +#define IS_DICT(value) isObjType(value, OBJ_DICT) +#define IS_SET(value) isObjType(value, OBJ_SET) +#define IS_FILE(value) isObjType(value, OBJ_FILE) +#define IS_ABSTRACT(value) isObjType(value, OBJ_ABSTRACT) +#define IS_RESULT(value) isObjType(value, OBJ_RESULT) typedef enum { OBJ_MODULE, @@ -206,16 +213,9 @@ typedef enum { OBJ_UPVALUE } ObjType; -typedef enum { - CLASS_DEFAULT, - CLASS_ABSTRACT, - CLASS_TRAIT -} ClassType; +typedef enum { CLASS_DEFAULT, CLASS_ABSTRACT, CLASS_TRAIT } ClassType; -typedef enum { - ACCESS_PUBLIC, - ACCESS_PRIVATE -} AccessLevel; +typedef enum { ACCESS_PUBLIC, ACCESS_PRIVATE } AccessLevel; typedef enum { TYPE_FUNCTION, @@ -252,8 +252,8 @@ typedef struct sUpvalue { typedef struct { Obj obj; - ObjString* name; - ObjString* path; + ObjString *name; + ObjString *path; Table values; } ObjModule; @@ -275,7 +275,7 @@ typedef struct { ObjString *name; FunctionType type; AccessLevel accessLevel; - ObjModule* module; + ObjModule *module; int propertyCount; int *propertyNames; int *propertyIndexes; @@ -284,7 +284,6 @@ typedef struct { int *privatePropertyIndexes; } ObjFunction; - #define STACK_MAX (64 * UINT8_COUNT) typedef struct { Obj obj; @@ -341,7 +340,9 @@ struct _vm { #define DICTU_MINOR_VERSION "29" #define DICTU_PATCH_VERSION "0" -#define DICTU_STRING_VERSION "Dictu Version: " DICTU_MAJOR_VERSION "." DICTU_MINOR_VERSION "." DICTU_PATCH_VERSION "\n" +#define DICTU_STRING_VERSION \ + "Dictu Version: " DICTU_MAJOR_VERSION "." DICTU_MINOR_VERSION \ + "." DICTU_PATCH_VERSION "\n" typedef struct _vm DictuVM; @@ -398,7 +399,7 @@ struct sObjFile { typedef void (*AbstractFreeFn)(DictuVM *vm, ObjAbstract *abstract); typedef void (*AbstractGrayFn)(DictuVM *vm, ObjAbstract *abstract); -typedef char* (*AbstractTypeFn)(ObjAbstract *abstract); +typedef char *(*AbstractTypeFn)(ObjAbstract *abstract); struct sObjAbstract { Obj obj; @@ -410,10 +411,7 @@ struct sObjAbstract { bool excludeSelf; }; -typedef enum { - SUCCESS, - ERR -} ResultStatus; +typedef enum { SUCCESS, ERR } ResultStatus; struct sObjResult { Obj obj; @@ -421,7 +419,6 @@ struct sObjResult { Value value; }; - typedef struct sObjClass { Obj obj; ObjString *name; @@ -466,7 +463,8 @@ typedef ObjSet *newSet_t(DictuVM *vm); typedef ObjFile *newFile_t(DictuVM *vm); -typedef ObjAbstract *newAbstract_t(DictuVM *vm, AbstractFreeFn func, AbstractTypeFn type); +typedef ObjAbstract *newAbstract_t(DictuVM *vm, AbstractFreeFn func, + AbstractTypeFn type); typedef ObjResult *newResult_t(DictuVM *vm, ResultStatus status, Value value); @@ -516,105 +514,127 @@ typedef bool compareStringLess_t(Value a, Value b); typedef bool compareStringGreater_t(Value a, Value b); +typedef void defineNative_t(DictuVM *vm, Table *table, const char *name, + NativeFn function); + +typedef void defineNativeProperty_t(DictuVM *vm, Table *table, const char *name, + Value value); + +copyString_t *copyString = NULL; + +newList_t *newList = NULL; -copyString_t* copyString = NULL; +newDict_t *newDict = NULL; -newList_t* newList = NULL; +newSet_t *newSet = NULL; -newDict_t* newDict = NULL; +newFile_t *newFile = NULL; -newSet_t* newSet = NULL; +newAbstract_t *newAbstract = NULL; -newFile_t* newFile = NULL; +newResult_t *newResult = NULL; -newAbstract_t* newAbstract = NULL; +newResultSuccess_t *newResultSuccess = NULL; -newResult_t* newResult = NULL; +newResultError_t *newResultError = NULL; -newResultSuccess_t* newResultSuccess = NULL; +push_t *push = NULL; -newResultError_t* newResultError = NULL; +peek_t *peek = NULL; -push_t* push = NULL; +runtimeError_t *runtimeError = NULL; -peek_t* peek = NULL; +pop_t *pop = NULL; -runtimeError_t* runtimeError = NULL; +isFalsey_t *isFalsey = NULL; -pop_t* pop = NULL; +valuesEqual_t *valuesEqual = NULL; -isFalsey_t* isFalsey = NULL; +initValueArray_t *initValueArray = NULL; -valuesEqual_t* valuesEqual = NULL; +writeValueArray_t *writeValueArray = NULL; -initValueArray_t* initValueArray = NULL; +freeValueArray_t *freeValueArray = NULL; -writeValueArray_t* writeValueArray = NULL; +dictSet_t *dictSet = NULL; -freeValueArray_t* freeValueArray = NULL; +dictGet_t *dictGet = NULL; -dictSet_t* dictSet = NULL; +dictDelete_t *dictDelete = NULL; -dictGet_t* dictGet = NULL; +setGet_t *setGet = NULL; -dictDelete_t* dictDelete = NULL; +setInsert_t *setInsert = NULL; -setGet_t* setGet = NULL; +setDelete_t *setDelete = NULL; -setInsert_t* setInsert = NULL; +valueToString_t *valueToString = NULL; -setDelete_t* setDelete = NULL; +valueTypeToString_t *valueTypeToString = NULL; -valueToString_t* valueToString = NULL; +printValue_t *printValue = NULL; -valueTypeToString_t* valueTypeToString = NULL; +printValueError_t *printValueError = NULL; -printValue_t* printValue = NULL; +compareStringLess_t *compareStringLess = NULL; -printValueError_t* printValueError = NULL; +compareStringGreater_t *compareStringGreater = NULL; -compareStringLess_t* compareStringLess = NULL; +defineNative_t *defineNative = NULL; -compareStringGreater_t* compareStringGreater = NULL; +defineNativeProperty_t *defineNativeProperty = NULL; -int dictu_internal_ffi_init(void** function_ptrs) { - if(copyString != NULL){ +// This needs to be implemented by the user and register all functions +int dictu_ffi_init(DictuVM *vm, Table *method_table); + +int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm, + Table *methodTable, int vm_ffi_version) { + if (copyString != NULL) { // we already initialized. return 1; } + if (vm_ffi_version > FFI_MOD_API_VERSION) + return 2; size_t count = 0; - copyString = (copyString_t*) function_ptrs[count++]; - newList = (newList_t*) function_ptrs[count++]; - newDict = (newDict_t*) function_ptrs[count++]; - newSet = (newSet_t*) function_ptrs[count++]; - newFile = (newFile_t*) function_ptrs[count++]; - newAbstract = (newAbstract_t*) function_ptrs[count++]; - newResult = (newResult_t*) function_ptrs[count++]; - newResultSuccess = (newResultSuccess_t*) function_ptrs[count++]; - newResultError = (newResultError_t*) function_ptrs[count++]; - push = (push_t*) function_ptrs[count++]; - peek = (peek_t*) function_ptrs[count++]; - runtimeError = (runtimeError_t*) function_ptrs[count++]; - pop = (pop_t*) function_ptrs[count++]; - isFalsey = (isFalsey_t*) function_ptrs[count++]; - valuesEqual = (valuesEqual_t*) function_ptrs[count++]; - initValueArray = (initValueArray_t*) function_ptrs[count++]; - writeValueArray = (writeValueArray_t*) function_ptrs[count++]; - freeValueArray = (freeValueArray_t*) function_ptrs[count++]; - dictSet = (dictSet_t*) function_ptrs[count++]; - dictGet = (dictGet_t*) function_ptrs[count++]; - dictDelete = (dictDelete_t*) function_ptrs[count++]; - setGet = (setGet_t*) function_ptrs[count++]; - setInsert = (setInsert_t*) function_ptrs[count++]; - setDelete = (setDelete_t*) function_ptrs[count++]; - valueToString = (valueToString_t*) function_ptrs[count++]; - valueTypeToString = (valueTypeToString_t*) function_ptrs[count++]; - printValue = (printValue_t*) function_ptrs[count++]; - printValueError = (printValueError_t*) function_ptrs[count++]; - compareStringLess = (compareStringLess_t*) function_ptrs[count++]; - compareStringGreater = (compareStringGreater_t*) function_ptrs[count++]; + copyString = (copyString_t *)function_ptrs[count++]; + newList = (newList_t *)function_ptrs[count++]; + newDict = (newDict_t *)function_ptrs[count++]; + newSet = (newSet_t *)function_ptrs[count++]; + newFile = (newFile_t *)function_ptrs[count++]; + newAbstract = (newAbstract_t *)function_ptrs[count++]; + newResult = (newResult_t *)function_ptrs[count++]; + newResultSuccess = (newResultSuccess_t *)function_ptrs[count++]; + newResultError = (newResultError_t *)function_ptrs[count++]; + push = (push_t *)function_ptrs[count++]; + peek = (peek_t *)function_ptrs[count++]; + runtimeError = (runtimeError_t *)function_ptrs[count++]; + pop = (pop_t *)function_ptrs[count++]; + isFalsey = (isFalsey_t *)function_ptrs[count++]; + valuesEqual = (valuesEqual_t *)function_ptrs[count++]; + initValueArray = (initValueArray_t *)function_ptrs[count++]; + writeValueArray = (writeValueArray_t *)function_ptrs[count++]; + freeValueArray = (freeValueArray_t *)function_ptrs[count++]; + dictSet = (dictSet_t *)function_ptrs[count++]; + dictGet = (dictGet_t *)function_ptrs[count++]; + dictDelete = (dictDelete_t *)function_ptrs[count++]; + setGet = (setGet_t *)function_ptrs[count++]; + setInsert = (setInsert_t *)function_ptrs[count++]; + setDelete = (setDelete_t *)function_ptrs[count++]; + valueToString = (valueToString_t *)function_ptrs[count++]; + valueTypeToString = (valueTypeToString_t *)function_ptrs[count++]; + printValue = (printValue_t *)function_ptrs[count++]; + printValueError = (printValueError_t *)function_ptrs[count++]; + compareStringLess = (compareStringLess_t *)function_ptrs[count++]; + compareStringGreater = (compareStringGreater_t *)function_ptrs[count++]; + defineNative = (defineNative_t *)function_ptrs[count++]; + defineNativeProperty = (defineNativeProperty_t *)function_ptrs[count++]; + int initResult = dictu_ffi_init(vm, methodTable); + if (initResult > 0) + return 3 + initResult; return 0; } - +#ifdef __cplusplus +} +#endif #endif \ No newline at end of file diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c index c5f1a0734..465ec3326 100644 --- a/examples/ffi-example/src/lib.c +++ b/examples/ffi-example/src/lib.c @@ -10,4 +10,10 @@ Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { } Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(copyString(vm, "Hello world", 11)); +} + +int dictu_ffi_init(DictuVM *vm, Table *method_table) { + defineNative(vm, method_table, "dictu_ffi_test", dictu_ffi_test); + defineNative(vm, method_table, "dictu_ffi_test_str", dictu_ffi_test_str); + return 0; } \ No newline at end of file diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 42886e495..675d5b2a4 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -9,7 +9,7 @@ typedef struct { typedef struct _vm_external vm_external; typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); -typedef int init_func_definition_t(void **function_ptrs); +typedef int init_func_definition_t(void **function_ptrs, DictuVM* vm, Table* table, int vm_ffi_version); // #define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) @@ -43,7 +43,9 @@ void *ffi_function_pointers[] = { &printValue, &printValueError, &compareStringLess, - &compareStringGreater + &compareStringGreater, + &defineNative, + &defineNativeProperty }; void freeFFI(DictuVM *vm, ObjAbstract *abstract) { @@ -70,8 +72,8 @@ void grayFFI(DictuVM *vm, ObjAbstract *abstract) { } static Value load(DictuVM *vm, int argCount, Value *args) { - if (argCount != 2) { - runtimeError(vm, "load() takes 2 arguments (%d given)", argCount); + if (argCount != 1) { + runtimeError(vm, "load() takes one argument (%d given)", argCount); return EMPTY_VAL; } ObjString *path = AS_STRING(args[0]); @@ -80,38 +82,38 @@ static Value load(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "Couldn't load shared object: %s", path->chars); return EMPTY_VAL; } - init_func_definition_t *init_func = + ObjAbstract *abstract = newAbstractExcludeSelf(vm, freeFFI, ffiToString); + push(vm, OBJ_VAL(abstract)); + init_func_definition_t *init_func = dlsym(library, "dictu_internal_ffi_init"); // call init function to give ffi module the required pointers to the function of the vm. - if (!init_func || init_func((void**)&ffi_function_pointers) != 0) { + if (!init_func) { runtimeError(vm, "Couldn't initialize ffi api: %s", path->chars); dlclose(library); return EMPTY_VAL; } - ObjList *symbols = AS_LIST(args[1]); - ObjAbstract *abstract = newAbstractExcludeSelf(vm, freeFFI, ffiToString); - push(vm, OBJ_VAL(abstract)); + int initResult = init_func((void**)&ffi_function_pointers, vm, &abstract->values, DICTU_FFI_API_VERSION); + if(initResult == 1){ + runtimeError(vm, "FFI mod already initialized: %s", path->chars); + dlclose(library); + return EMPTY_VAL; + } + if(initResult == 2){ + runtimeError(vm, "FFI api version is newer then mod version: %s, required FFI version: %d", path->chars, DICTU_FFI_API_VERSION); + dlclose(library); + return EMPTY_VAL; + } + if(initResult > 3){ + runtimeError(vm, "Mod init function returned a error: %s, error code: %d", path->chars, initResult-3); + dlclose(library); + return EMPTY_VAL; + } FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); instance->path = malloc(path->length + 1); instance->path[path->length] = '\0'; memcpy(instance->path, path->chars, path->length); instance->library = library; - if (symbols->values.count) { - for (int i = 0; i < symbols->values.count; i += 1) { - Value v = symbols->values.values[i]; - if (IS_STRING(v)) { - ObjString *sym = AS_STRING(v); - void* funcptr = dlsym(instance->library, sym->chars); - if(!funcptr) { - runtimeError(vm, "Couldn't find symbol: %s in %s", sym->chars, path->chars); - dlclose(library); - return EMPTY_VAL; - } - defineNative(vm, &abstract->values, sym->chars, funcptr); - } - } - } abstract->data = instance; abstract->grayFunc = grayFFI; diff --git a/src/optionals/ffi/ffi.h b/src/optionals/ffi/ffi.h index ba0824cde..ef865537a 100644 --- a/src/optionals/ffi/ffi.h +++ b/src/optionals/ffi/ffi.h @@ -17,6 +17,10 @@ #define LIB_EXTENSION_STRLEN 3 #endif +// This is used to determine if we can safely load the function pointers without UB, +// if this is greater then the version from the mod we error in the internal mod load function. +#define DICTU_FFI_API_VERSION 1 + Value createFFIModule(DictuVM *vm); From 7c1ff5edc54dc9345090f4edc6f6ff2b8f2c61af Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 5 Feb 2024 19:10:19 +0100 Subject: [PATCH 114/148] fix: windows dll export --- examples/ffi-example/src/dictu-include.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/ffi-example/src/dictu-include.h b/examples/ffi-example/src/dictu-include.h index 4111054f9..dfd8e55ba 100644 --- a/examples/ffi-example/src/dictu-include.h +++ b/examples/ffi-example/src/dictu-include.h @@ -587,6 +587,9 @@ defineNativeProperty_t *defineNativeProperty = NULL; // This needs to be implemented by the user and register all functions int dictu_ffi_init(DictuVM *vm, Table *method_table); +#ifdef _WIN32 +__declspec(dllexport) +#endif int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm, Table *methodTable, int vm_ffi_version) { if (copyString != NULL) { From 20d622bdeaa3410ec9b38d5cd8fe5f9ec82a2d04 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Mon, 5 Feb 2024 19:33:50 +0100 Subject: [PATCH 115/148] feat: support properties in abstract --- examples/ffi-example/ffi.du | 3 ++- examples/ffi-example/src/lib.c | 3 +++ src/vm/vm.c | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index f87974cd3..d5eb447a9 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -4,4 +4,5 @@ const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); for(var i = 0; i < 25; i+=1) { print(mod.dictu_ffi_test(1, i*2)); print(mod.dictu_ffi_test_str()); -} \ No newline at end of file +} +print(mod.test); \ No newline at end of file diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c index 465ec3326..19cf4a248 100644 --- a/examples/ffi-example/src/lib.c +++ b/examples/ffi-example/src/lib.c @@ -15,5 +15,8 @@ Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { int dictu_ffi_init(DictuVM *vm, Table *method_table) { defineNative(vm, method_table, "dictu_ffi_test", dictu_ffi_test); defineNative(vm, method_table, "dictu_ffi_test_str", dictu_ffi_test_str); + defineNativeProperty( + vm, method_table, "test", + OBJ_VAL(copyString(vm, "Dictu!", 6))); return 0; } \ No newline at end of file diff --git a/src/vm/vm.c b/src/vm/vm.c index 4571bcb16..ae3263ff6 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -1172,6 +1172,18 @@ static DictuInterpretResult run(DictuVM *vm) { RUNTIME_ERROR("'%s' module has no attribute: '%s'.", module->name->chars, name->chars); } + case OBJ_ABSTRACT: { + ObjAbstract *abstract = AS_ABSTRACT(receiver); + ObjString *name = READ_STRING(); + Value value; + if (tableGet(&abstract->values, name, &value)) { + pop(vm); // Abstract. + push(vm, value); + DISPATCH(); + } + RUNTIME_ERROR("'no attribute: '%s'.",name->chars); + } + case OBJ_CLASS: { ObjClass *klass = AS_CLASS(receiver); // Used to keep a reference to the class for the runtime error below From 5378fee568dafba0e9dd6efb0e91400a74545496 Mon Sep 17 00:00:00 2001 From: Liz3 Date: Tue, 6 Feb 2024 21:57:15 +0100 Subject: [PATCH 116/148] chore: add ffi-example build to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 95ff94de5..1a7503c26 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ test1.du .vscode /.env /vcpkg_installed -/Release \ No newline at end of file +/Release +examples/ffi-example/build \ No newline at end of file From 6e934b1f35c5eb7ea357db01122ce62bc6662d1d Mon Sep 17 00:00:00 2001 From: Liz3 Date: Tue, 6 Feb 2024 22:27:08 +0100 Subject: [PATCH 117/148] feat: windows support --- examples/ffi-example/ffi.du | 8 ++++++- src/optionals/ffi/ffi.c | 46 +++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index d5eb447a9..a3ae77eee 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -1,6 +1,12 @@ import FFI; +import System; -const mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); +var mod = nil; +if(System.platform == "windows") { + mod = FFI.load("./build/Release/ffi-test{}".format(FFI.suffix)); +} else { + mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); +} for(var i = 0; i < 25; i+=1) { print(mod.dictu_ffi_test(1, i*2)); print(mod.dictu_ffi_test_str()); diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 675d5b2a4..43d3f412a 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -1,8 +1,16 @@ #include "ffi.h" +#ifdef _WIN32 +#include +#else #include +#endif typedef struct { + #ifdef _WIN32 + HMODULE library; + #else void *library; + #endif char *path; } FFIInstance; @@ -51,7 +59,11 @@ void *ffi_function_pointers[] = { void freeFFI(DictuVM *vm, ObjAbstract *abstract) { FFIInstance *instance = (FFIInstance *)abstract->data; free(instance->path); + #ifdef _WIN32 + FreeLibrary(instance->library); + #else dlclose(instance->library); + #endif FREE(vm, FFIInstance, abstract->data); } @@ -77,35 +89,59 @@ static Value load(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } ObjString *path = AS_STRING(args[0]); + #ifdef _WIN32 + HMODULE library = LoadLibrary(path->chars); + #else void *library = dlopen(path->chars, RTLD_LAZY); + #endif if (!library) { runtimeError(vm, "Couldn't load shared object: %s", path->chars); return EMPTY_VAL; } ObjAbstract *abstract = newAbstractExcludeSelf(vm, freeFFI, ffiToString); push(vm, OBJ_VAL(abstract)); - init_func_definition_t *init_func = + #ifdef _WIN32 + FARPROC init_func = GetProcAddress(library, "dictu_internal_ffi_init"); + #else + init_func_definition_t *init_func = dlsym(library, "dictu_internal_ffi_init"); + #endif // call init function to give ffi module the required pointers to the function of the vm. if (!init_func) { runtimeError(vm, "Couldn't initialize ffi api: %s", path->chars); - dlclose(library); + #ifdef _WIN32 + FreeLibrary(library); + #else + dlclose(library); + #endif return EMPTY_VAL; } int initResult = init_func((void**)&ffi_function_pointers, vm, &abstract->values, DICTU_FFI_API_VERSION); if(initResult == 1){ runtimeError(vm, "FFI mod already initialized: %s", path->chars); - dlclose(library); + #ifdef _WIN32 + FreeLibrary(library); + #else + dlclose(library); + #endif return EMPTY_VAL; } if(initResult == 2){ runtimeError(vm, "FFI api version is newer then mod version: %s, required FFI version: %d", path->chars, DICTU_FFI_API_VERSION); - dlclose(library); + #ifdef _WIN32 + FreeLibrary(library); + #else + dlclose(library); + #endif return EMPTY_VAL; } if(initResult > 3){ runtimeError(vm, "Mod init function returned a error: %s, error code: %d", path->chars, initResult-3); - dlclose(library); + #ifdef _WIN32 + FreeLibrary(library); + #else + dlclose(library); + #endif return EMPTY_VAL; } FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); From 36443d86fafc5f58d62c1d085c772b946ce4b9fc Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 6 Feb 2024 22:29:28 +0100 Subject: [PATCH 118/148] style: formatting --- src/optionals/ffi/ffi.c | 154 +++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 43d3f412a..2a30166ac 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -6,64 +6,63 @@ #endif typedef struct { - #ifdef _WIN32 +#ifdef _WIN32 HMODULE library; - #else +#else void *library; - #endif +#endif char *path; } FFIInstance; typedef struct _vm_external vm_external; typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); -typedef int init_func_definition_t(void **function_ptrs, DictuVM* vm, Table* table, int vm_ffi_version); +typedef int init_func_definition_t(void **function_ptrs, DictuVM *vm, + Table *table, int vm_ffi_version); // #define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) -void *ffi_function_pointers[] = { - ©String, - &newList, - &newDict, - &newSet, - &newFile, - &newAbstract, - &newResult, - &newResultSuccess, - &newResultError, - &push, - &peek, - &runtimeError, - &pop, - &isFalsey, - &valuesEqual, - &initValueArray, - &writeValueArray, - &freeValueArray, - &dictSet, - &dictGet, - &dictDelete, - &setGet, - &setInsert, - &setDelete, - &valueToString, - &valueTypeToString, - &printValue, - &printValueError, - &compareStringLess, - &compareStringGreater, - &defineNative, - &defineNativeProperty -}; +void *ffi_function_pointers[] = {©String, + &newList, + &newDict, + &newSet, + &newFile, + &newAbstract, + &newResult, + &newResultSuccess, + &newResultError, + &push, + &peek, + &runtimeError, + &pop, + &isFalsey, + &valuesEqual, + &initValueArray, + &writeValueArray, + &freeValueArray, + &dictSet, + &dictGet, + &dictDelete, + &setGet, + &setInsert, + &setDelete, + &valueToString, + &valueTypeToString, + &printValue, + &printValueError, + &compareStringLess, + &compareStringGreater, + &defineNative, + &defineNativeProperty}; void freeFFI(DictuVM *vm, ObjAbstract *abstract) { FFIInstance *instance = (FFIInstance *)abstract->data; free(instance->path); - #ifdef _WIN32 +#ifdef _WIN32 FreeLibrary(instance->library); - #else +#else dlclose(instance->library); - #endif +#endif FREE(vm, FFIInstance, abstract->data); } @@ -89,59 +88,66 @@ static Value load(DictuVM *vm, int argCount, Value *args) { return EMPTY_VAL; } ObjString *path = AS_STRING(args[0]); - #ifdef _WIN32 +#ifdef _WIN32 HMODULE library = LoadLibrary(path->chars); - #else +#else void *library = dlopen(path->chars, RTLD_LAZY); - #endif +#endif if (!library) { runtimeError(vm, "Couldn't load shared object: %s", path->chars); return EMPTY_VAL; } ObjAbstract *abstract = newAbstractExcludeSelf(vm, freeFFI, ffiToString); push(vm, OBJ_VAL(abstract)); - #ifdef _WIN32 +#ifdef _WIN32 FARPROC init_func = GetProcAddress(library, "dictu_internal_ffi_init"); - #else +#else init_func_definition_t *init_func = dlsym(library, "dictu_internal_ffi_init"); - #endif - // call init function to give ffi module the required pointers to the function of the vm. +#endif + // call init function to give ffi module the required pointers to the + // function of the vm. if (!init_func) { runtimeError(vm, "Couldn't initialize ffi api: %s", path->chars); - #ifdef _WIN32 - FreeLibrary(library); - #else - dlclose(library); - #endif +#ifdef _WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif return EMPTY_VAL; } - int initResult = init_func((void**)&ffi_function_pointers, vm, &abstract->values, DICTU_FFI_API_VERSION); - if(initResult == 1){ + int initResult = init_func((void **)&ffi_function_pointers, vm, + &abstract->values, DICTU_FFI_API_VERSION); + if (initResult == 1) { runtimeError(vm, "FFI mod already initialized: %s", path->chars); - #ifdef _WIN32 - FreeLibrary(library); - #else - dlclose(library); - #endif +#ifdef _WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif return EMPTY_VAL; } - if(initResult == 2){ - runtimeError(vm, "FFI api version is newer then mod version: %s, required FFI version: %d", path->chars, DICTU_FFI_API_VERSION); - #ifdef _WIN32 - FreeLibrary(library); - #else - dlclose(library); - #endif + if (initResult == 2) { + runtimeError(vm, + "FFI api version is newer then mod version: %s, required " + "FFI version: %d", + path->chars, DICTU_FFI_API_VERSION); +#ifdef _WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif return EMPTY_VAL; } - if(initResult > 3){ - runtimeError(vm, "Mod init function returned a error: %s, error code: %d", path->chars, initResult-3); - #ifdef _WIN32 - FreeLibrary(library); - #else - dlclose(library); - #endif + if (initResult > 3) { + runtimeError(vm, + "Mod init function returned a error: %s, error code: %d", + path->chars, initResult - 3); +#ifdef _WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif return EMPTY_VAL; } FFIInstance *instance = ALLOCATE(vm, FFIInstance, 1); From 65bd1a356207446de522323e36923c40342e507a Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Wed, 7 Feb 2024 21:03:26 +0000 Subject: [PATCH 119/148] Make Err result a falsey value and add docs --- docs/docs/variables.md | 37 +++++++++++++++++++++++++++++++++++++ src/vm/vm.c | 1 + 2 files changed, 38 insertions(+) diff --git a/docs/docs/variables.md b/docs/docs/variables.md index 6eb98bbea..867700cc1 100644 --- a/docs/docs/variables.md +++ b/docs/docs/variables.md @@ -27,6 +27,43 @@ nav_order: 3 | Nil | `nil` | Used to signify no value (much like null in other languages) | | Result | `Success`, `Error` | See [Error Handling section.](/docs/error-handling) | +## Truthy / Falsey + +Truthy / Falsey are terms that describe a value that will evaluate to either true or false. This, however, is not the same +as the value equalling the boolean value of true or false. + +The table below describes falsey types for built-in data types, any other value would evaluate to truthy. + +| Type | Example | Note | +| --- |-----------------------------------------------|-----------------------------| +| String | `''`, `""` | A string of 0 length. | +| Number | `0` | The value `0`. | +| Boolean | `false` | The value `false`. | +| List | `[]` | A list of 0 length. | +| Dictionary | `{}` | A dictionary with 0 length. | +| Set | `set()` | A set with 0 length. | +| Nil | `nil` | The value `nil` | +| Result | `Error` | A result in Error state. | + +### Example + +This means we can use these values in a conditional check without the need for an explicit value check + +```cs +const someList = [1, 2, 3].filter(def (x) => x > 3); + +if (someList) { + // The list has values within it + ... +} + +const someResult = ...; // Some action that returns a Result + +if (not someResult) { + print("Error!"); +} +``` + ## Declaring a variable ```cs diff --git a/src/vm/vm.c b/src/vm/vm.c index cef7c3c35..37074814a 100644 --- a/src/vm/vm.c +++ b/src/vm/vm.c @@ -806,6 +806,7 @@ bool isFalsey(Value value) { (IS_STRING(value) && AS_CSTRING(value)[0] == '\0') || (IS_LIST(value) && AS_LIST(value)->values.count == 0) || (IS_DICT(value) && AS_DICT(value)->count == 0) || + (IS_RESULT(value) && AS_RESULT(value)->status == ERR) || (IS_SET(value) && AS_SET(value)->count == 0); } From 329689f95601d1ccc24e2d13c4365d73ff4ec07f Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 10 Feb 2024 02:34:41 +0100 Subject: [PATCH 120/148] feat: docs and test for macos --- docs/docs/standard-lib/ffi.md | 130 +++++++++++++++++++++++++++++ docs/docs/standard-lib/hashlib.md | 2 +- docs/docs/standard-lib/http.md | 2 +- docs/docs/standard-lib/inspect.md | 2 +- docs/docs/standard-lib/io.md | 2 +- docs/docs/standard-lib/json.md | 2 +- docs/docs/standard-lib/log.md | 2 +- docs/docs/standard-lib/math.md | 2 +- docs/docs/standard-lib/net.md | 2 +- docs/docs/standard-lib/object.md | 2 +- docs/docs/standard-lib/path.md | 2 +- docs/docs/standard-lib/process.md | 2 +- docs/docs/standard-lib/queue.md | 2 +- docs/docs/standard-lib/random.md | 2 +- docs/docs/standard-lib/socket.md | 2 +- docs/docs/standard-lib/sqlite.md | 2 +- docs/docs/standard-lib/stack.md | 2 +- docs/docs/standard-lib/system.md | 2 +- docs/docs/standard-lib/term.md | 2 +- docs/docs/standard-lib/unittest.md | 2 +- docs/docs/standard-lib/uuid.md | 2 +- examples/ffi-example/src/lib.c | 6 +- tests/ffi/ffi.du | 50 +++++++++++ tests/ffi/import.du | 6 ++ tests/ffi/libs/test-lib.dylib | Bin 0 -> 18528 bytes tests/runTests.du | 1 + 26 files changed, 210 insertions(+), 23 deletions(-) create mode 100644 docs/docs/standard-lib/ffi.md create mode 100644 tests/ffi/ffi.du create mode 100644 tests/ffi/import.du create mode 100755 tests/ffi/libs/test-lib.dylib diff --git a/docs/docs/standard-lib/ffi.md b/docs/docs/standard-lib/ffi.md new file mode 100644 index 000000000..bfe8bf586 --- /dev/null +++ b/docs/docs/standard-lib/ffi.md @@ -0,0 +1,130 @@ +--- +layout: default +title: FFI +nav_order: 7 +parent: Standard Library +--- +# FFI +{: .no_toc } + +## Table of contents +{: .no_toc .text-delta } + +1. TOC +{:toc} + +--- +## FFI +To make use of the FFI module an import is required. + +```js +import FFI; +``` + +### Creating a module +Creating a FFI module requires building a dynamically shared library(.dll/.dylib/.so). + +To build a module theres only a single header needed [dictu-include.h](). +The header contains definitions, function declerations and function pointers(set at runtime automatically) for anything needed to interact with the DictuVM. +Further it contains the following function decleration: +```c +int dictu_ffi_init(DictuVM *vm, Table *method_table); +``` +You will need to write a function definition(implementation) for it. +The functions return value determines success or failure, `0` is success and anything > `0` is failure, +Dictu's vm will throw a runtime error with the given code if the function returns a non 0 value. + +Upon loading the module(shared library) in dictu, the vm will load and invoke this function. +**NOTE: do not use vm functions before the init function is called since functions wont be available yet!** + +Within the function you can then define properties and functions which will then be available from dictu. +The functions must follow this signature, the types are defined in the `dictu-include.h` header: +```c +Value ffi_function(DictuVM *vm, int argCount, Value *args); +``` + +[Full example in C using cmake]() + +#### Functions +Given the following c code: +```c +Value dictu_ffi_function(DictuVM *vm, int argCount, Value *args) { + return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28)); +} +//... +int dictu_ffi_init(DictuVM *vm, Table *method_table) { + // ... + defineNative(vm, method_table, "getString", dictu_ffi_function); + // ... +} +``` +In dictu you can do +```cs +import FFI; + +const mod = FFI.load("/path/to/library.so"); +const str = mod.getString(); // "Hello From Dictu FFI module!" +``` + +#### Properties +Given the following c code: +```c +//... +int dictu_ffi_init(DictuVM *vm, Table *method_table) { + // ... + defineNativeProperty( + vm, method_table, "propName", + OBJ_VAL(copyString(vm, "Dictu!", 6))); + // ... +} +``` +In dictu you can do +```cs +import FFI; + +const mod = FFI.load("/path/to/library.so"); +const str = mod.propName; // Dictu! +``` + +Here a entire example from the [ffi-example](): +```c +#include "dictu-include.h" + +Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { + if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ + return NIL_VAL; + } + double a = AS_NUMBER(args[0]); + double b = AS_NUMBER(args[1]); + return NUMBER_VAL(a+b); +} +Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { + return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28)); +} + +int dictu_ffi_init(DictuVM *vm, Table *method_table) { + defineNative(vm, method_table, "dictuFFITestAdd", dictu_ffi_test); + defineNative(vm, method_table, "dictuFFITestStr", dictu_ffi_test_str); + defineNativeProperty( + vm, method_table, "test", + OBJ_VAL(copyString(vm, "Dictu!", 6))); + return 0; +} +``` + +```cs +import FFI; +const mod = FFI.load("/path/to/library.so"); +print(mod.test); // Dictu! +print(mod.dictuFFITestStr()); // "Hello From Dictu FFI module!" +print(mod.dictuFFITestAdd(22, 22)); // 44 +print(mod.dictuFFITestAdd(22)); // nil +``` + +### FFI.load(String) -> FFIInstance +Load a module, the Shared library **MUST** include the `dictu-include.h` header and have `dictu_ffi_init` defined otherwise it might lead to UB. +```cs +const mod = FFI.load("/path/to/library.so"); +print(mod); // +// mod will contain all defined functions and properties by the module. +``` diff --git a/docs/docs/standard-lib/hashlib.md b/docs/docs/standard-lib/hashlib.md index a0ee80cfa..5759fedd1 100644 --- a/docs/docs/standard-lib/hashlib.md +++ b/docs/docs/standard-lib/hashlib.md @@ -1,7 +1,7 @@ --- layout: default title: Hashlib -nav_order: 7 +nav_order: 8 parent: Standard Library --- diff --git a/docs/docs/standard-lib/http.md b/docs/docs/standard-lib/http.md index 89a809a43..a742109b7 100644 --- a/docs/docs/standard-lib/http.md +++ b/docs/docs/standard-lib/http.md @@ -1,7 +1,7 @@ --- layout: default title: HTTP -nav_order: 8 +nav_order: 9 parent: Standard Library --- diff --git a/docs/docs/standard-lib/inspect.md b/docs/docs/standard-lib/inspect.md index 32664ef60..c57f4a61e 100644 --- a/docs/docs/standard-lib/inspect.md +++ b/docs/docs/standard-lib/inspect.md @@ -1,7 +1,7 @@ --- layout: default title: Inspect -nav_order: 9 +nav_order: 10 parent: Standard Library --- diff --git a/docs/docs/standard-lib/io.md b/docs/docs/standard-lib/io.md index 51a2c79f3..c0c0f3f58 100644 --- a/docs/docs/standard-lib/io.md +++ b/docs/docs/standard-lib/io.md @@ -1,7 +1,7 @@ --- layout: default title: IO -nav_order: 10 +nav_order: 11 parent: Standard Library --- diff --git a/docs/docs/standard-lib/json.md b/docs/docs/standard-lib/json.md index cc2a73e57..4a76e8681 100644 --- a/docs/docs/standard-lib/json.md +++ b/docs/docs/standard-lib/json.md @@ -1,7 +1,7 @@ --- layout: default title: JSON -nav_order: 11 +nav_order: 12 parent: Standard Library --- diff --git a/docs/docs/standard-lib/log.md b/docs/docs/standard-lib/log.md index 8f3e91a48..9c23fe4a5 100644 --- a/docs/docs/standard-lib/log.md +++ b/docs/docs/standard-lib/log.md @@ -1,7 +1,7 @@ --- layout: default title: Log -nav_order: 12 +nav_order: 13 parent: Standard Library --- diff --git a/docs/docs/standard-lib/math.md b/docs/docs/standard-lib/math.md index 36266e769..81baa7ee6 100644 --- a/docs/docs/standard-lib/math.md +++ b/docs/docs/standard-lib/math.md @@ -1,7 +1,7 @@ --- layout: default title: Math -nav_order: 13 +nav_order: 14 parent: Standard Library --- diff --git a/docs/docs/standard-lib/net.md b/docs/docs/standard-lib/net.md index 6ecbf240c..ec6f1a1f4 100644 --- a/docs/docs/standard-lib/net.md +++ b/docs/docs/standard-lib/net.md @@ -1,7 +1,7 @@ --- layout: default title: Net -nav_order: 14 +nav_order: 15 parent: Standard Library --- diff --git a/docs/docs/standard-lib/object.md b/docs/docs/standard-lib/object.md index faa6f3869..2c3522ff4 100644 --- a/docs/docs/standard-lib/object.md +++ b/docs/docs/standard-lib/object.md @@ -1,7 +1,7 @@ --- layout: default title: Object -nav_order: 15 +nav_order: 16 parent: Standard Library --- diff --git a/docs/docs/standard-lib/path.md b/docs/docs/standard-lib/path.md index 6b4af35d9..d17ccae90 100644 --- a/docs/docs/standard-lib/path.md +++ b/docs/docs/standard-lib/path.md @@ -1,7 +1,7 @@ --- layout: default title: Path -nav_order: 16 +nav_order: 17 parent: Standard Library --- diff --git a/docs/docs/standard-lib/process.md b/docs/docs/standard-lib/process.md index 35431043d..69e99ef20 100644 --- a/docs/docs/standard-lib/process.md +++ b/docs/docs/standard-lib/process.md @@ -1,7 +1,7 @@ --- layout: default title: Process -nav_order: 17 +nav_order: 18 parent: Standard Library --- diff --git a/docs/docs/standard-lib/queue.md b/docs/docs/standard-lib/queue.md index 60e617bb9..b724391dc 100644 --- a/docs/docs/standard-lib/queue.md +++ b/docs/docs/standard-lib/queue.md @@ -1,7 +1,7 @@ --- layout: default title: Queue -nav_order: 18 +nav_order: 19 parent: Standard Library --- diff --git a/docs/docs/standard-lib/random.md b/docs/docs/standard-lib/random.md index d5c266175..8f237dcab 100644 --- a/docs/docs/standard-lib/random.md +++ b/docs/docs/standard-lib/random.md @@ -1,7 +1,7 @@ --- layout: default title: Random -nav_order: 19 +nav_order: 20 parent: Standard Library --- diff --git a/docs/docs/standard-lib/socket.md b/docs/docs/standard-lib/socket.md index bf84425f6..888dda578 100644 --- a/docs/docs/standard-lib/socket.md +++ b/docs/docs/standard-lib/socket.md @@ -1,7 +1,7 @@ --- layout: default title: Socket -nav_order: 20 +nav_order: 21 parent: Standard Library --- diff --git a/docs/docs/standard-lib/sqlite.md b/docs/docs/standard-lib/sqlite.md index cc217fbdf..4ad279808 100644 --- a/docs/docs/standard-lib/sqlite.md +++ b/docs/docs/standard-lib/sqlite.md @@ -1,7 +1,7 @@ --- layout: default title: Sqlite -nav_order: 21 +nav_order: 22 parent: Standard Library --- diff --git a/docs/docs/standard-lib/stack.md b/docs/docs/standard-lib/stack.md index 5299b4c2c..022a906f4 100644 --- a/docs/docs/standard-lib/stack.md +++ b/docs/docs/standard-lib/stack.md @@ -1,7 +1,7 @@ --- layout: default title: Stack -nav_order: 22 +nav_order: 23 parent: Standard Library --- diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index 7f5f23e5e..08da7200f 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -1,7 +1,7 @@ --- layout: default title: System -nav_order: 23 +nav_order: 24 parent: Standard Library --- diff --git a/docs/docs/standard-lib/term.md b/docs/docs/standard-lib/term.md index 19331a0c7..0b2cb43c9 100644 --- a/docs/docs/standard-lib/term.md +++ b/docs/docs/standard-lib/term.md @@ -1,7 +1,7 @@ --- layout: default title: Term -nav_order: 24 +nav_order: 25 parent: Standard Library --- diff --git a/docs/docs/standard-lib/unittest.md b/docs/docs/standard-lib/unittest.md index 9a6021b79..84a937134 100644 --- a/docs/docs/standard-lib/unittest.md +++ b/docs/docs/standard-lib/unittest.md @@ -1,7 +1,7 @@ --- layout: default title: UnitTest -nav_order: 25 +nav_order: 26 parent: Standard Library --- diff --git a/docs/docs/standard-lib/uuid.md b/docs/docs/standard-lib/uuid.md index 8bbf2eee2..3cc5d120a 100644 --- a/docs/docs/standard-lib/uuid.md +++ b/docs/docs/standard-lib/uuid.md @@ -1,7 +1,7 @@ --- layout: default title: UUID -nav_order: 26 +nav_order: 27 parent: Standard Library --- diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c index 19cf4a248..f4b117dde 100644 --- a/examples/ffi-example/src/lib.c +++ b/examples/ffi-example/src/lib.c @@ -9,12 +9,12 @@ Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(a+b); } Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { - return OBJ_VAL(copyString(vm, "Hello world", 11)); + return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28)); } int dictu_ffi_init(DictuVM *vm, Table *method_table) { - defineNative(vm, method_table, "dictu_ffi_test", dictu_ffi_test); - defineNative(vm, method_table, "dictu_ffi_test_str", dictu_ffi_test_str); + defineNative(vm, method_table, "dictuFFITestAdd", dictu_ffi_test); + defineNative(vm, method_table, "dictuFFITestStr", dictu_ffi_test_str); defineNativeProperty( vm, method_table, "test", OBJ_VAL(copyString(vm, "Dictu!", 6))); diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du new file mode 100644 index 000000000..4b8744e12 --- /dev/null +++ b/tests/ffi/ffi.du @@ -0,0 +1,50 @@ +/** + * ffi.du + * + * Testing the ffi api + + Used c code start: + +#include "dictu-include.h" + +Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { + if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ + return NIL_VAL; + } + double a = AS_NUMBER(args[0]); + double b = AS_NUMBER(args[1]); + return NUMBER_VAL(a+b); +} +Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { + return OBJ_VAL(copyString(vm, "Hello world", 11)); +} + +int dictu_ffi_init(DictuVM *vm, Table *method_table) { + defineNative(vm, method_table, "dictu_ffi_test", dictu_ffi_test); + defineNative(vm, method_table, "dictu_ffi_test_str", dictu_ffi_test_str); + defineNativeProperty( + vm, method_table, "test", + OBJ_VAL(copyString(vm, "Dictu!", 6))); + return 0; +} +Used c code end +*/ + + +from UnitTest import UnitTest; +import FFI; +import Path; + +class TestFFIModule < UnitTest { + testFFIModule() { + const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}".format(FFI.suffix)); + const mod = FFI.load(path); + this.assertEquals(mod.test, "Dictu!"); + for(var i = 0; i < 40; i+=2) { + this.assertEquals(mod.dictuFFITestAdd(i, i), i+i); + } + this.assertEquals(mod.dictuFFITestStr(), "Hello From Dictu FFI module!"); + } +} + +TestFFIModule().run(); \ No newline at end of file diff --git a/tests/ffi/import.du b/tests/ffi/import.du new file mode 100644 index 000000000..1d66e02fe --- /dev/null +++ b/tests/ffi/import.du @@ -0,0 +1,6 @@ +/** + * import.du + * + * General import file for the FFI module tests + */ +import "ffi.du"; \ No newline at end of file diff --git a/tests/ffi/libs/test-lib.dylib b/tests/ffi/libs/test-lib.dylib new file mode 100755 index 0000000000000000000000000000000000000000..2635039899f52e05843747935f17e84bcbda523f GIT binary patch literal 18528 zcmeHPZEO_B8GiTnjLoM(aaux&eUv70D8!^RjUyGZ{sLPe)WuHaHf@%}UMH8_7khVs z!_XKgs%cter;g;Hs&U#V*eIx0+8`sfs#Oz8+f+3aQPfn?K_z-g8pR=h?vRe_^UluU zv(s*+{;X!CnVn~znRjNM*?ITZyMMaz!OcZP8X?U?E=L~Ii4N0JZlXJoYr&dkds9cd zXqsIZvmr@bf@aPzC6Z~ztvzuG@R)0_;z5Tqco9g9JxaTW)HC-xZ$g(6{8Mf#8S3Iouqpg9jHY8K;pUCqd*xwU26!%dAXg){9H zG!@RT@Z3@6w6mRJTZ@5rATOWOUh``VlLUFg1(8{<|ies5P2h`vbFE8ai@?;qyaAaO155QJy#dG1s_(cO3& zO(@W~5RX=5PTYs{=a9M2|B^m~K|D{r@7e9sm9;-Px@PsyPQBTd`vTg0$c`pUFwqiG z7ust#^)=v}8-xlH?wHsI+u}888*6brG^$C&Y~DWSwqz`Bh3>7F5}=o}ZniU3@7TKs zb;i7JPIn?RHnw0r#RtTsN=gBxfKosypcGIFCDs`sUX^+IP-W)oZIu0c6`e*n+*p}rWXm-ADE;Y| zR*VomfUv8IYU@XeC{2z-7aWk+-~^X@_;yQYK&-UBX6 z1~T(uyIOPMN?f@4F5F@lZkY>ry9;-R3wNgrx5|aP%Z0nggRh-c7p}#Hd&GtNstfn13-@&w?prRL--WYWxPS{6a^ZHla0wSK>B8-&?C_z-Ggodi zvdf4DQ{{9zU5-1eId}G)ywjp>F)ibJjkwN=U*pMleR$Fw&-FBp!cPoL=;o!o&i+Cl z%}vt4@FDmM_zd+mIW`*=4web#?j z^btO1zmZL|-+--jxwE%)DeOys#B*S6{i`}Q4g3bahHYOdb*GHo|JR=Xx4Ov4>CYg?-;-<@i;eck=P^viZ=b^raQe9>?dgZT5vn@*iF( zyKmd`W!n7r*(Ww@MSRH|9^(u8!e?IS%YS%%1ezi4yn^i!>>-|YFjY!9fiWJjvx6y} za;Z`ycSSdHRPC=s#O)w!EzSdbpS6buI*;+$H18j0kiwXJ13CM1IAKfJg#NdK~seBp2+pokLGdy{5~{W!C=I<*^Y#KBJ$a{d2@>| z6zNI?tyR>;vCwE}N33&QSJy1u7PpCGph*l{#h+E|k5NJktqTO*n%AuYqf`AZ!$K2+DsjEC&Swb`-cPKzuxlTLe4_fqtbAGd6pztxJxs2oB2z1$p%`fUrl<9Pksqe)r2+e;ZScKU#(Ay_ZO`bqF5T}q3Y`0E>HYP$8xk(4LKp2Y%`-3K9(XAhA zY_x(_+@i;}SaI^Vp?D%;(hC}StnNVA+UAc3p0Vg*oDaROd8toKpTYXEMX?J^_cebo zVb$5TKS|fL*k*q)W+myL=shC(^^0;?lzpO{5aqZi$9gqSlWj+AdezgG=GAeQFgmH!^Yri9UyC@+h}PC-X! zf*%5k%UGxX7 z+qSGCJyTkMu4`dyH%)n>bX>O+;dmfqIr}-Q$FPof^k-Oqdd0ij4#bNG|D0b%PJ{MX z*<0EfZ6#kCq<>(>CCC>yIrw9VrzPflgx8ePhQo7wKI4?cpO=^Sogen{e|#QhQ{8DmY28&N?zg3NfST;GclFOvVCI4N=Ae;H>P!+xKE3eqKH z#(NA#MAwiRKWQ)`nnq?^Z7?FrAv0cTFv4qyxf%Nm0mWJvmr1-_^6MpDEwLf-28sDU z4V;=JUTz3Tk4W4qaht?DB<_%SO5!ewFH4+|xLM*Ji8~}dBJsGygA$KO{3D6SBt9ZaG4eKNa#GiaK9K zQDF}tDv22fSA>N}oP&kWlx?5%j^>=ZD12to-82IQUuWWi-ttrogs{B|}#)gM9#k3J>mV!`SVYEzS2>W-}j4sdk_EhSI;#cS$q7y@zs}`cDAnV z`{}vV+dbW%8q8Oo+VJ9+jvYIhtKWa4ZYo=~?&8~TTC2YIg71$j?%(moFTb(yU`KL% S#s1P)cGh11^WRp!O7t&&kpx=+ literal 0 HcmV?d00001 diff --git a/tests/runTests.du b/tests/runTests.du index 9c1636152..d6da7d06e 100644 --- a/tests/runTests.du +++ b/tests/runTests.du @@ -54,6 +54,7 @@ import "hashlib/import.du"; import "object/import.du"; import "term/import.du"; import "buffer/import.du"; +import "ffi/import.du"; // If we got here no runtime errors were thrown, therefore all tests passed. print("All tests passed successfully!"); From 4247fa092d2ff8ab9abe1a2a4cef3793f94e2f0e Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sat, 10 Feb 2024 02:37:58 +0100 Subject: [PATCH 121/148] chore: add linux binary --- tests/ffi/libs/test-lib.so | Bin 0 -> 16352 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 tests/ffi/libs/test-lib.so diff --git a/tests/ffi/libs/test-lib.so b/tests/ffi/libs/test-lib.so new file mode 100755 index 0000000000000000000000000000000000000000..ea67d078a90f6dd8b8647d8bb5c73c4fec535165 GIT binary patch literal 16352 zcmeHOeQ;FO6~EaK2n0z$umMyS1dXUm_)<_QyO0eJ8)8ZVgSO7H$-a=)WH;^y5>!MZ zmNjCbQ%BmNj&!Utow4HBnMOyQ09K)DCywZ396!=2>QWtz){kv<*q(FmIh(te;JmSa zbUL#)^K$O}o!>e4-t*quckkP?clhgST}4HLOR@N&7;XvSCB@(pW+1jil)?XV#dOIX zHLN(Ng3=T>@Q$h|apmb%?&Fd4X1*$rHsFTKU8 zZSiDiTrPmoE=_i6vSZm#{jn@nZsZuz)d6%cf~;1sU}@S7kew-KlO0PQZsYrj(D&)D zf$Zws%CRYHs6Uq6-;co#|a_p_H8=vriVVB1S&BR4x9)2!gJ6!s={~KU4u>O z-s@e5W?ebgJ@&39(KmjQOSmc)2r(PE$SZ>b=Y&qC!0`h(rou4|j_Gim564V6X2Ed* z9CP5f5RQxC_`}5eUU)F}tIE1W#f}ZNGoB8wA9!!pHCwk&erRV|LrEl4|MHBJ?{D3A z+qlL1Zd<;2{hmcXdwk-)c~2&vDt+Lp!97zyjW3OswLdp{>ZaBO2iHs-*!qrdVMA5Z z;}f?Yf4lsud;6PLY@ByR<;FwLk9qcq^5i#9EWi1syQkMTc9y-rEKt0oYuo;3uMef~ zeJEZwXI5M0is;+@Fr+gUoTGaL?K;3@01X|+-)&&n#M{S>6{FNb8)IaaeE>{^s5W?& zhVPGOp##J#eEE0@;SU@99fW5Ld@|f$lf-zjpi=qa>w7me(Z6Nz-ywXvftQe<1YQ78 zo>xL_rGAIJ3gGd-2u<|gX5cRq-f7@%vrj5mnbb%E!omsSjJj_@huq{su3i!}vd-j`(gbqQm(0Ps%{~Pgl8u&5dSNebeh39oM)N%Y(UPOoSuYix|aWh@dd>ys|2l;L`h`{QmHGz;Fvp0p~2|L!bW@URcVmAew+ij&ASrcg45)8D4Bf<9Y zRv@CgmYV`CZ8rs4gW-1367B42OvJ*GO(J67QU|V4)`VN6Y_z4Q4MQIQ`0;j@Jg;<93(W9Bfb8 zasSQ9V7mxM!in|R_QhhsE^$jNoUpZaYs}W0As8o)5#=h9HFmq5utnUK2#D2@xE)I% zKq}c^QU61^kc{1)C5{v!_Ww;nIuPQCTuu0I8UX;CY;NdXb(5Hc;ZpdrU&D`T z_(dAtui>~p;4+}$G!&^C)Nt&ZOIpKcG6-@=!*PwlC8Oc+5iwkrt19}&^$C|!4L^rL zkQEw!u7+1?_#_Q?YdEfbxKwF4uA#V8YxoQXK`zm7I)zf})o@&Qaj`UfJcA$`G<>#( zZ_seKfO2J{hEL0(LbPf4EDi6}aK5%sy+y-mX)CR^YdEiAQL$6QY3n5UyEUAa8WP{D z;b%)k{d-u$$7uKg4W~zi)E?CEa*f}s;cgA@)9~{&{HTVH)9`)`$F(+>0S(9XI+sBW zrzMF}d6mF9(XB3lQVp+Cl)`@p5%_2M`Tw@MKQ6U;O2YGmuy*t%T-koB`-RdY(mK2N zF92ufyaNBrXLzB8?Kae%9Lz$Qa~RwB(Q>jMn%1smhXAm4l{|xDX(llRT;K0euE%Bv z%V%sy<0B-2zen;H-;3hnQ&wuoI`qkM>rkfHDtgg+?NnkiIGBS<7+Yy}u(f;!EY{f` z$G?5q8c>Vm!gW^nvT<0oQtv0uvU-+zppl)Df!@W&==k!;w}``HZ`97~)9l za2@A|{!VTJ?mF-RfpJ@@+tVSdXVe_Ls;rbhGr!O3@u#6S^m%!Of2h?e-v-FKOvt)q zvLq!+(r=#1WOE~hK>;We^`)VAAl}Zj;sdWRXHOC<) z^Dlz|^~kV{>y;;9KinzZw;wOsHm(=%jgxzzZN22r;6$N^jJ2zw2<$;l{xe}|tEeBH zqz;3}_h6T1r7E0I?{iMw@0_~LId!FTs@FO7)k_>l;6~?OUvlpCT<2b=I`{gCbLv9p z)WNxqgY|}U>RRX2C!AA{!=lLHrCsFQ>;2BXUgF$qzjLo&I;S=}r>=5N{Q^D~9maL4 zbFUvb_xg=<>ch^dJDgKvu*{bcST_J4oP$>CO)K?M`a~w1P5Hm*zWocat+WR!eZ?P@ z^x}tZ{zrN$c>+JtyKg_?N?rr@;6qr?AWw*I@33Ybwxp44EIpjKNK(4{;CcNWwB&e8 zJ`m9Aqc!XmMs?A@t{)~LS$!A%5J}`2lcf$iIlS+O8 zqff)5;}O^#Sv@c;f94t7A6UBet*2xX#IX)$ z)dSBse8Bch=|!KZ*Q{Mr;>wi|Rwg|qCjrhUW^=^rb>hGr98)EjjLwZN{mf`JI`0`q z2hTwofb7{#wAbYXtezV($ByLIOu1DOo~=SDM4%9XLIesCC`91@Cjyq;-X3+=#-bf= zd@Y}J*Ve9fcSJ+Uc6+9JAq+qhy!7>jLV0a?NiC$sOd($$!<37r7hmNC36D&1{L^gq zryyS)%4Tt=J>|1(_7RZlK)wL7>g#Ow1jr9Sj)KkWTv#vRcUt@osA%h2QM9F^X!`gu zrMm&24P0DTbb{Y%kYYkb?S#r}%FAvk-7c0-yK3&j+46N9a%$l4LBAIAd=o0}ajiUS zv}+}JQa(Zehe7Yv^|wm3?Bj00Q=pgMg|U6{UrUgI{vUzk>aVid=XHD6(>eby0R9%} zYjph`%D)@16L6d|?fu=wu0JXcniWbR0)+?^B2b7xAp(U66e3WFKp_H!2sn=b=X-E| z2Yx?>1#?KS@OSI;sXbo7xdao=1z1GM1)O8Rc_o~~0b2@LI7fiPQV5EiBl?IKC?=5@!o@{!1mHT-3Rlsbn1p^i%20 z$2UlPis1W=wfNHsmw=0&;>UOdDwua^=5KZre!#1keBb?o@G1lUHQ~Jm{#(L34g4{} z8w~tO!uJ|@AK`8Te;IH$9A^0t0GyZCt28|RPoX(d9`P8651wPQ%mN(!RC|?%{mdnN ziGj~2{Gfp^C48rWuOQqq@Or{G8u$%_rwu$x_-+HgmGJEbeh1+L2A%>O<74KDY~arU?iQz)SBRf6_-_+FWZ)kXZsvD?OL(8bALCNvH}ml^zaHnc z!Qjs!yv@Mp65em%iwHOKyK4c*c$)e9*8%PprvT5)^I$zK zDyg_BTA%C?kz_|xR3;G%%!Cd@7IY{c4YUO#AEw)YPY!BMhTB7zg+oFT+JcZ_?+JB9z?qWp-d}1q+p%~!8p&$}Ko_&ygJ?jtPDtbT z$bowj_7yE^4zz{9mRrgq5R_T^(t_*YIM@+xfnKBF3;uaz z2g+G9WXyXY+8uTzG19&JJuqD7<60R$4rDQZ&xh*^z3_94F-Sekvp>`C`It}3e{RZ; zJ@~31%Kgh9w4s(3*7)5C7Pd3{{}JeL@4)uFzhF5;esDj6uGpUU8I6D;h3$F2!jktV zK#_%p!%guMsNr6L?RkH|vWb{He&(@k13m6NxXt?ymK=X`{5*hLpn|^Hp7%RB$#EnD zbN+Xd{R-0a{)r{`kA2|p08RTIz%VAfzss!?X}!q%NTA5Vap3knP|@w(WXF>GXFjQO z-Rv>!8;HR21P_=Tus!>G(6HxqH%s0pGv6HlZ^)kGFWkf=xtf|RaISj!9W)SQdtR@z ztkKC(H~W9eu;1-g1}saB4vlb#=YWn|X1YvrzboP2ubO;rvpfd2<(fUe9~gu@Pb|z+ zt>HG~Z-4@?9qym^G5mXE{@pRZPhdMfkMDvlPLb{T_bk2m!33rH4D)9{e+Q0k&-vE4@ln$@XU$zhVjTHB^v7bcO}n zoA)2P(h&c literal 0 HcmV?d00001 From 9b8b4b3eb0eedea327bc29fcbcc54b57b18a2edf Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sat, 10 Feb 2024 02:41:35 +0100 Subject: [PATCH 122/148] feat: windows shared object --- tests/ffi/libs/test-lib.dll | Bin 0 -> 10240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/ffi/libs/test-lib.dll diff --git a/tests/ffi/libs/test-lib.dll b/tests/ffi/libs/test-lib.dll new file mode 100644 index 0000000000000000000000000000000000000000..004a28159feea5a3a2d1a6c14868c57694a6e55d GIT binary patch literal 10240 zcmeHNe{@t;e!r7sLVge@xEY#7(FY7B)Fw>4ClW=z7q=w!`8Kvu=cka;2FPG+WW z-az1hhEC!#c{_@G^hozu4;#BZcDp^rZL0y>-HC$|1T+RJQO>F9db&Oc#|Cs+P~7R~ z`|cZ(u+aUZ_4L&4J?Fmf@9(|$d%y2{@4Te>{@pB_F_wd#PBS(LNX@A~f6v3j*bTQH zxPkpc{;>svCik%gt)2de5SBxmWN(+y?hOV*im*`<dG8XKlL*wGOyT^}IRoQx$a!(35cBN)2g!i)xoU^^@2h};fRj|pO< z>t&LNt5K++Cj~-Kq!>}GbiLb%m}*YO?wX?he`B#vv!bphHLqzukHh6hMRllY(NNQh zA!SLE+L9-#uNvgM4$%^PgC0ZYE$fHRTjscJf~Ypwgp@c)+sxSIM^i^#(%QJRj{6SmZeXtV5Slx5bWKHTtQGHJ-)`t+)2W@uf z3!aoKcFFWe@gU{ZG_I(c+=-&w(&@AqH+x|3PMG&#SW$IhDJQ{PO~b3MVxaeOv=peD zqXN(-j+O&m#Zf!ZdXClrb#l}Rw2q@9&^tNW0`v}!t_Qk|qisN|INAxclA~duw{x@` zXt|E=?4cFK%?mlTi&HmqYB#6ma%vB!iaE8HQw5xQfm1o0+Q+Hi-a>2NNktwbT;x=e zQ|CD~%&D`S8sXHhI5ozpaZZhM>OD?roH_x@tv)#k${n}9$z>NwrXInNuYuu8k7A2H z_#9iLp2YU#qvSxEw(ce2AXQT2N_K|(!}-X8E9nCLb2q?u;V|tcS;_hsNDD`jC&p3A zxxP_ldF+fyDW}KW*rz6?fF}^;nwDi|Y{IM^M}f1vL}ulwCUu11X{vwCeM!sHdRm?? zMPlnYDaI8Wa%Q_taIMqRQ$6oi&p8fjGJN$WExi;t?NT;l{bRctY);Yw`!OC^^m9c7ik<+_`U@EAOGcMy{{|V<1;~S3 z?jgAk@wREM?a^=T@lZuRv8WYDC( zDXQ6Swdf2gxGVj3+FS)!dWHF`z6;1I z?e*VM;+q|OVC9C4PTJarVf)gGIhM|jI^|bko-P zS7ttu>o`SHHAP$5joom%9`Zayb#^MB^+JmRtG*|y=kSt5%^KeO}wbhe= zO77_=Fm=OTSSzY$`Fmg<{wgN)O7+0|6@Pv^uobDOBF3arWO8$9+WND6@YF^W*~a3u z^#mw2DOM4_i{puAfzv%iHzLoQi^ZXFL399jG!~1FA#pznIvPAJ0^yh%O0+Z#p{_L2 z6fj#+{LKi+N+L1k4JoPxw6J0vC%?cO!=kxqYZ(Tbss=~##x>4^L3;6A2oRq{(bqtq zzCiC#!n_=K>I#HE?L$mOjOE$1UvVT0W8nm&v9!N~QD0J7Ac<bA8Q*%P1=qS&Y&AcYRV zR$uG)bSFwNg3b7Dm7o4c@U&OCceD1lx+(%|tnHo%Q;8@$IxHb`7X=_Toc`GIsCfw#kc-s-L=ptK z0^oJC8BdcQaZF)9oHFfGJoG$3i5?nkzMrv<<>n2@uxPi~UbGts4uEC?*>CJzPQP2C zp20#C&yMA;(rByu_E#-0f4fACy;>?}zioNhl`AG@_qY?Y-w@*^wx$(tE2Zk)v)wC( zg=&4f>=pnlo*E94OLnHbS455VN(P>u1Tcwh@}w z&Vv-Q4X8s?cj(0YdrX$sq}vGec<=+#Qa;i zZRu6EgV(Wr6$wmZPnC^gN78ZFGSHw7H9Af;sH3i(lR-raxOSfR2c@P4^@uv@IP6N) zn;Hv8ECa5c=e{WgqwySDW8vHIlcQcj;Pc|Gw%O4K#8}amuOMEFCs(E|;vusK1nXg} zE}3g$N_kydZWdD()P)JmGw-`}8ArUZ#U}1I;nGEs7A?;YMM@e}^K1CI>WU4U8sg>y zKqqE__acx%y4*A*#LretZoiGDjfpg| zj((g@yVb_9y0%kPo7=R@7r7@p-X#p7TR0BytUGVse%lhx5e?X5z>HpvVJ8?c$AG^y z^o9-ik^x^Z;IjtI_;KINzt?48&n=wBZ_OU63K^Kuf56~p=>IMhr9dDgtdc`rLW93u zi3+P$HPJ`VXh2#(zJ0_5uT_dDE}w4(y+)ClZUjvQ@@vfn$KZ_Sq(yxJt=MjS_q@vY zxWM_72E0nli{tMwzc@zEqHE7nGv;?OGtUKFFVBF*2Beu~z6Ik~Hd~MCGqMPsE+St* z!#$8?^HFAQ{U{T1L3 z0QCl07&85vuB|IbyfEZn2h8wncKa0@&g<4EFitvt`X+1p8c>G)Wi`aJ+uJ)fVQvc; z!yT7Z*007jzupCu2{U=Px#Iil3|^D2XP?Q_^=fADT68_GHvb_LTP4;BVWu&9@QDW97FQ>ywpsTa!y4$3BC1 zKcDw>UMtsg&fsx95xi~_#_8tYxijDSD8#d*bSk7IH&9UY&tCG*GzFEu)nYDV(cro%2Q)Un1 z`gR1J@|Id97Q7riLz{4q%dO68nWOv7V+E^o!(@xACyPMu2k8H7*meT{3Hmz*{rA9s zK21*aFQ&=!=jF0_%Pef3Ja@b#{FOHHi{-LkL+2DO=Vw3@)aS4|tHor=WfrW#f;CvG z3&Wo?1Fj7L3~FcXv#9NEX31TkKI&~$4Y$Yt+QAO z{FPJ}hfP*9;&XsmO@l0#boKEt)-p4*+*lZ<_|W{QWgw^clMVpF&X;jH=}^}|pGBWU z-(8Hm79f5ucK9pkG^z9j0{pn~_;D$hgWiA#G7x@+u`%RZru8Gw!UCviXX{-!kN1E_ zd6{VgbhZl_Y9{=$-!t-<$5Zc#gr#F@_2 z^w36@GEaLb*x}z4l_gKmE6brR9IJX+*XyA+8u`PkBF+}2K6^7_DJ zrflf0*&0!#u2u}-imdVnB*NIAm>T>Mnl4v%`!~v7d278l5Qwmy*-gl2zW6n6gj|F> zb~(ZJqGRu>@)CPfd6FR1m8CB6M&ZuoZuW>jLA<4pn@KTe}aE$ z@CgnYI6)K6;!fz~06t;hy8+8_E<3>|=td_Uf>8tC1$Z3y?OyOt02bqKM-&r+_#LU^ zEr6GC4}S_e_)W?F4E+V*_&urLVfF#1yA0h?_P~}P-A@Q7NOugv3DRBRX6O^FL2m>8 zztc?mZx4j7XXg00!+>GG20tGcG7&PmGw!%Xaj0F{-4zfvOL7Fou&%7C(q1M=!S;~P zAKX+|wzhRuMNOFyQE*&(12|yn%C<_8vX$Q`Dya2FB2w4Jz*Yecf|0tis2sdA(%va` zc_S5F{&qPO33VtH?V+way^*fU%~fRrjuw9hPSL}|kDYj|7ud%QUo z>UOY<;P8|E%2tC0N0$CHicutAi|pTwGiZ|(xgwk{Zq(0BEZZ$@mI6Y6o^@s3NKGemcT{>eGjRhka}%#k33v}6 s8Q-hzo!onIFZ)sPkIDy}1LDBQfHp8WaB+Y=pZEN=P5;3CzaN4B1Ob4}3;+NC literal 0 HcmV?d00001 From 7d474318fa9c41b8262c41d61e2a00c841eed9b5 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 10 Feb 2024 02:54:03 +0100 Subject: [PATCH 123/148] fix: pretty sure this needs to be x86_64 --- tests/ffi/libs/test-lib.dylib | Bin 18528 -> 18240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ffi/libs/test-lib.dylib b/tests/ffi/libs/test-lib.dylib index 2635039899f52e05843747935f17e84bcbda523f..111e0ba7e9062d32c48277bbffb8f3904daa1aba 100755 GIT binary patch delta 1987 zcmaKtUr19?7{JfncGXC|itQy0S5{yzIm%MZwu(!~#GVp-X!y_{kSM}!^oQ0>u4b3Z zmUbVahrpMp9)w^JYA@48S_w@EG!VKkV?_uRK`w_pGHmzS9nH{!g>srtGf*YUYzT>gMTQHRQVWs(hOOXf zJ_c=sWnRN_M+{4EusFqlwHTIdGgxB1U@o5u8SE*DGxRu>I;pgpMg^9oVfGtaXw{iz zeW21Pm5%CE*vMV?se}8d^a7Q3=29W=oLsp$kJeLZ6_x&h+q3=#2-yp=Q~+n`9F@MH z(nlLp0dD5qjWN(`RC$YE5*eTbVH%4s-Ja-quC|{DkQrARAg-h!u4q_h zdkniNu&d#q{WF9VECkC$&|ZZX#hzHp=Lrv%orOxr`v{hJSQZZ!`2~G{60gEY2gD&P z!$iTx=b%0TPg)-n042YQrAg3@;|a1Zgwm^c(;Un{NDK=xX9QN>;E4|9tXPx$NfHRf zK+?hukhlvmO~qsSc$5}!9fQaJcbaFo{#^xhj+Crb8mJ;lV=yfwFe34(gm8e!WU`B< zcnh?bxk`O&Ah=o*uQw&JWv+r>SmwI;SiF&pfU&wC^rdsPw?JmNoVeR?kVeL6>yCt& zPZ0n`CB&X~xFnuvt^qOWAZI4|e}V_V+3YJapW)oC(444&0uCgzfAHoEc+laADyLj+ zPO>|qK~io_ehTuVxuGUG^QpO&KBj6*DPm9sWHafFd+x_Owd=@=MsAYg2Gi~J^`c&6 z>ABS7Ll=GLygqaVK=`ejwd@(`jg>rOB8h{qXp)LF+&8w6p>M delta 2267 zcmai#eN07(_Jk(i-d93>JLaZ5=wqGh^7je-P?Gp1moWy>bwjA}Rub<>Z|w z3Pu1P#tB&yNkg#GguLWZ9^vA?r82~7?v_v8H1JI%A^~) z*l{bo!73PR7lZ9)uv(o-=|7Ce8HP_W*fR|FY&s^HU*hxWpvew0SQCQ<8SIeBq^va8 zqJ?4jI)imEST`ucy$4eB`J$2s5J}i!B54;VB)r@D-MwJmZK@PDLLR-}Jl@~0aHMyB zI39?poz+pS7xE+@nA3P#H~6R;2YI*`>ju^iS}&43y)_~(7C>Df#Q}tTQx!7$3cVnD zWgt~^NnTu?Bi)>2sWc`%uv4F;7oToXNzwv>&XRT`x}*&kFbfl11UDBds;`v4!Jz0;eFM%_JN;3Om(oN-t6O3#1P<+spgF1TLdP*>QBMLJJKTM;&lB6eqX-J@r<_9BP z2Gf1%J~0K9J*MX}4wy?Ws`i?>^t)pV>5jRsLO#M9$J~dU+PTDg))>lxt(GDQmMCb0d38_K~x zTWQGGO?jy@yy6=utFAEA{W#bW<(kuun{u}K>W-PRV|>E@4!?8d&+JKz)rDF#(whTy z7$n&MoP~x<1AYm6y@3Iv*&}*5$i_GOUMWK~)$mHNvAH=|O2fGS#SWC9=V+sRv zzdTmczy0+8@#5chS2fmc?>l)Raj~=cj)>+u_u%n|hK9yeU-!zcpA~oM?8Wm Date: Sat, 10 Feb 2024 03:14:49 +0100 Subject: [PATCH 124/148] style: correctly indent file --- tests/ffi/ffi.du | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du index 4b8744e12..be6eda226 100644 --- a/tests/ffi/ffi.du +++ b/tests/ffi/ffi.du @@ -3,7 +3,7 @@ * * Testing the ffi api - Used c code start: +Used c code start: #include "dictu-include.h" @@ -36,15 +36,15 @@ import FFI; import Path; class TestFFIModule < UnitTest { - testFFIModule() { - const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}".format(FFI.suffix)); - const mod = FFI.load(path); - this.assertEquals(mod.test, "Dictu!"); - for(var i = 0; i < 40; i+=2) { - this.assertEquals(mod.dictuFFITestAdd(i, i), i+i); + testFFIModule() { + const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}".format(FFI.suffix)); + const mod = FFI.load(path); + this.assertEquals(mod.test, "Dictu!"); + for(var i = 0; i < 40; i+=2) { + this.assertEquals(mod.dictuFFITestAdd(i, i), i+i); + } + this.assertEquals(mod.dictuFFITestStr(), "Hello From Dictu FFI module!"); } - this.assertEquals(mod.dictuFFITestStr(), "Hello From Dictu FFI module!"); - } } TestFFIModule().run(); \ No newline at end of file From a1421070a7bfd7216569a34d8f211e2478bd5749 Mon Sep 17 00:00:00 2001 From: Liz3 Date: Mon, 12 Feb 2024 20:46:43 +0100 Subject: [PATCH 125/148] fix: add suffix to docs --- docs/docs/standard-lib/ffi.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/docs/standard-lib/ffi.md b/docs/docs/standard-lib/ffi.md index bfe8bf586..f14e429d1 100644 --- a/docs/docs/standard-lib/ffi.md +++ b/docs/docs/standard-lib/ffi.md @@ -112,6 +112,12 @@ int dictu_ffi_init(DictuVM *vm, Table *method_table) { } ``` +### Constants + +| Constant | Description | +| --------------- | ------------------------------------------------------------------------------------------------- | +| FFI.suffix | The system specific shared library suffix with the period(`.`): .dll/.so/.dylib. | + ```cs import FFI; const mod = FFI.load("/path/to/library.so"); From c767959d4d500eb602ba6a5e2d441232e3e00de0 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 17 Feb 2024 00:41:48 +0100 Subject: [PATCH 126/148] style: fix indentation --- examples/ffi-example/ffi.du | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index a3ae77eee..664f61e86 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -2,13 +2,15 @@ import FFI; import System; var mod = nil; + if(System.platform == "windows") { - mod = FFI.load("./build/Release/ffi-test{}".format(FFI.suffix)); + mod = FFI.load("./build/Release/ffi-test{}".format(FFI.suffix)); } else { - mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); + mod = FFI.load("./build/libffi-test{}".format(FFI.suffix)); } + for(var i = 0; i < 25; i+=1) { - print(mod.dictu_ffi_test(1, i*2)); - print(mod.dictu_ffi_test_str()); + print(mod.dictu_ffi_test(1, i*2)); + print(mod.dictu_ffi_test_str()); } print(mod.test); \ No newline at end of file From c916d228de230768eabab9fba2b7fef18adeb0ba Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 17 Feb 2024 00:43:12 +0100 Subject: [PATCH 127/148] fix: remove unused macro --- src/optionals/ffi/ffi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 2a30166ac..87cf98a4b 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -20,7 +20,6 @@ typedef Value function_definition_t(DictuVM *vm, int argCount, Value *args); typedef int init_func_definition_t(void **function_ptrs, DictuVM *vm, Table *table, int vm_ffi_version); -// #define AS_FFI_INSTANCE(v) ((FFIInstance *)AS_ABSTRACT(v)->data) void *ffi_function_pointers[] = {©String, &newList, From 7a6551e1be1c13d177909806893a0f8b0e2371db Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Sat, 17 Feb 2024 00:46:54 +0100 Subject: [PATCH 128/148] style: add missing new lines --- .gitignore | 2 +- examples/ffi-example/ffi.du | 2 +- examples/ffi-example/src/dictu-include.h | 2 +- examples/ffi-example/src/lib.c | 2 +- src/optionals/ffi/ffi.c | 2 +- tests/ffi/ffi.du | 2 +- tests/ffi/import.du | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 1a7503c26..91b5177df 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,4 @@ test1.du /.env /vcpkg_installed /Release -examples/ffi-example/build \ No newline at end of file +examples/ffi-example/build diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index 664f61e86..27fdd50a1 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -13,4 +13,4 @@ for(var i = 0; i < 25; i+=1) { print(mod.dictu_ffi_test(1, i*2)); print(mod.dictu_ffi_test_str()); } -print(mod.test); \ No newline at end of file +print(mod.test); diff --git a/examples/ffi-example/src/dictu-include.h b/examples/ffi-example/src/dictu-include.h index dfd8e55ba..b2e313f7d 100644 --- a/examples/ffi-example/src/dictu-include.h +++ b/examples/ffi-example/src/dictu-include.h @@ -640,4 +640,4 @@ int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm, #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c index f4b117dde..1f523a9c6 100644 --- a/examples/ffi-example/src/lib.c +++ b/examples/ffi-example/src/lib.c @@ -19,4 +19,4 @@ int dictu_ffi_init(DictuVM *vm, Table *method_table) { vm, method_table, "test", OBJ_VAL(copyString(vm, "Dictu!", 6))); return 0; -} \ No newline at end of file +} diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 87cf98a4b..1782a70fc 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -177,4 +177,4 @@ Value createFFIModule(DictuVM *vm) { pop(vm); return OBJ_VAL(module); -} \ No newline at end of file +} diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du index be6eda226..480d9fd59 100644 --- a/tests/ffi/ffi.du +++ b/tests/ffi/ffi.du @@ -47,4 +47,4 @@ class TestFFIModule < UnitTest { } } -TestFFIModule().run(); \ No newline at end of file +TestFFIModule().run(); diff --git a/tests/ffi/import.du b/tests/ffi/import.du index 1d66e02fe..37aebb329 100644 --- a/tests/ffi/import.du +++ b/tests/ffi/import.du @@ -3,4 +3,4 @@ * * General import file for the FFI module tests */ -import "ffi.du"; \ No newline at end of file +import "ffi.du"; From 9bc2a46bd71863dad789f3fb41e84bd8173b712a Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Tue, 20 Feb 2024 09:43:34 +0000 Subject: [PATCH 129/148] Ignore the libs directory for checkTests --- ops/checkTests.du | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ops/checkTests.du b/ops/checkTests.du index d7f102a31..d9288ec38 100644 --- a/ops/checkTests.du +++ b/ops/checkTests.du @@ -23,6 +23,9 @@ const ignored = { 'range.du', 'select.du', ], + 'ffi': [ + 'libs', + ], '*': [ 'import.du', ] From a39b86c268d7745ea35338a0eda3aeb96a476790 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 20 Feb 2024 19:17:16 +0100 Subject: [PATCH 130/148] fix: ffi followup: fixes the docs and moves the header into "include" --- docs/docs/standard-lib/ffi.md | 23 +++++++++++-------- examples/ffi-example/CMakeLists.txt | 2 ++ examples/ffi-example/src/lib.c | 2 +- .../include/dictu_ffi_include.h | 6 ++--- 4 files changed, 19 insertions(+), 14 deletions(-) rename examples/ffi-example/src/dictu-include.h => src/include/dictu_ffi_include.h (99%) diff --git a/docs/docs/standard-lib/ffi.md b/docs/docs/standard-lib/ffi.md index f14e429d1..d9cc94b91 100644 --- a/docs/docs/standard-lib/ffi.md +++ b/docs/docs/standard-lib/ffi.md @@ -24,7 +24,7 @@ import FFI; ### Creating a module Creating a FFI module requires building a dynamically shared library(.dll/.dylib/.so). -To build a module theres only a single header needed [dictu-include.h](). +To build a module theres only a single header needed [dictu_ffi_include.h](https://github.com/dictu-lang/Dictu/blob/develop/src/include/dictu_ffi_include.h). The header contains definitions, function declerations and function pointers(set at runtime automatically) for anything needed to interact with the DictuVM. Further it contains the following function decleration: ```c @@ -38,7 +38,7 @@ Upon loading the module(shared library) in dictu, the vm will load and invoke th **NOTE: do not use vm functions before the init function is called since functions wont be available yet!** Within the function you can then define properties and functions which will then be available from dictu. -The functions must follow this signature, the types are defined in the `dictu-include.h` header: +The functions must follow this signature, the types are defined in the `dictu_ffi_include.h` header: ```c Value ffi_function(DictuVM *vm, int argCount, Value *args); ``` @@ -48,6 +48,8 @@ Value ffi_function(DictuVM *vm, int argCount, Value *args); #### Functions Given the following c code: ```c +#include +//... Value dictu_ffi_function(DictuVM *vm, int argCount, Value *args) { return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28)); } @@ -56,13 +58,14 @@ int dictu_ffi_init(DictuVM *vm, Table *method_table) { // ... defineNative(vm, method_table, "getString", dictu_ffi_function); // ... + return 0; } ``` In dictu you can do ```cs import FFI; -const mod = FFI.load("/path/to/library.so"); +const mod = FFI.load("/path/to/library{}".format(FFI.suffix)); const str = mod.getString(); // "Hello From Dictu FFI module!" ``` @@ -73,7 +76,7 @@ Given the following c code: int dictu_ffi_init(DictuVM *vm, Table *method_table) { // ... defineNativeProperty( - vm, method_table, "propName", + vm, method_table, "foo", OBJ_VAL(copyString(vm, "Dictu!", 6))); // ... } @@ -82,13 +85,13 @@ In dictu you can do ```cs import FFI; -const mod = FFI.load("/path/to/library.so"); -const str = mod.propName; // Dictu! +const mod = FFI.load("/path/to/library{}".format(FFI.suffix)); +const str = mod.foo; // Dictu! ``` Here a entire example from the [ffi-example](): ```c -#include "dictu-include.h" +#include Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ @@ -120,7 +123,7 @@ int dictu_ffi_init(DictuVM *vm, Table *method_table) { ```cs import FFI; -const mod = FFI.load("/path/to/library.so"); +const mod = FFI.load("/path/to/library{}".format(FFI.suffix)); print(mod.test); // Dictu! print(mod.dictuFFITestStr()); // "Hello From Dictu FFI module!" print(mod.dictuFFITestAdd(22, 22)); // 44 @@ -128,9 +131,9 @@ print(mod.dictuFFITestAdd(22)); // nil ``` ### FFI.load(String) -> FFIInstance -Load a module, the Shared library **MUST** include the `dictu-include.h` header and have `dictu_ffi_init` defined otherwise it might lead to UB. +Load a module, the Shared library **MUST** include the `dictu_ffi_include.h` header and have `dictu_ffi_init` defined otherwise it might lead to UB. ```cs -const mod = FFI.load("/path/to/library.so"); +const mod = FFI.load("/path/to/shared-object"); print(mod); // // mod will contain all defined functions and properties by the module. ``` diff --git a/examples/ffi-example/CMakeLists.txt b/examples/ffi-example/CMakeLists.txt index 589700d55..7e3e48445 100644 --- a/examples/ffi-example/CMakeLists.txt +++ b/examples/ffi-example/CMakeLists.txt @@ -1,4 +1,6 @@ +cmake_minimum_required(VERSION 3.16.3) PROJECT("ffi-test") set(CMAKE_C_STANDARD 11) add_library(ffi-test SHARED src/lib.c) +target_include_directories(ffi-test PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src/include") \ No newline at end of file diff --git a/examples/ffi-example/src/lib.c b/examples/ffi-example/src/lib.c index 1f523a9c6..7144927a9 100644 --- a/examples/ffi-example/src/lib.c +++ b/examples/ffi-example/src/lib.c @@ -1,4 +1,4 @@ -#include "dictu-include.h" +#include Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ diff --git a/examples/ffi-example/src/dictu-include.h b/src/include/dictu_ffi_include.h similarity index 99% rename from examples/ffi-example/src/dictu-include.h rename to src/include/dictu_ffi_include.h index b2e313f7d..d21af07eb 100644 --- a/examples/ffi-example/src/dictu-include.h +++ b/src/include/dictu_ffi_include.h @@ -1,5 +1,5 @@ -#ifndef dictumod_include_h -#define dictumod_include_h +#ifndef dictu_ffi_include_h +#define dictu_ffi_include_h #ifdef __cplusplus extern "C" { @@ -596,7 +596,7 @@ int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm, // we already initialized. return 1; } - if (vm_ffi_version > FFI_MOD_API_VERSION) + if (FFI_MOD_API_VERSION > vm_ffi_version) return 2; size_t count = 0; From c768a93b70672b2739b880630d74c756d2bff826 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Tue, 20 Feb 2024 19:58:40 +0100 Subject: [PATCH 131/148] fix: update header --- examples/ffi-example/ffi.du | 4 ++-- src/include/dictu_ffi_include.h | 1 + tests/ffi/ffi.du | 9 +++++---- tests/ffi/libs/test-lib.dylib | Bin 18240 -> 18240 bytes 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/ffi-example/ffi.du b/examples/ffi-example/ffi.du index 27fdd50a1..8a964dd31 100644 --- a/examples/ffi-example/ffi.du +++ b/examples/ffi-example/ffi.du @@ -10,7 +10,7 @@ if(System.platform == "windows") { } for(var i = 0; i < 25; i+=1) { - print(mod.dictu_ffi_test(1, i*2)); - print(mod.dictu_ffi_test_str()); + print(mod.dictuFFITestAdd(1, i*2)); + print(mod.dictuFFITestStr()); } print(mod.test); diff --git a/src/include/dictu_ffi_include.h b/src/include/dictu_ffi_include.h index d21af07eb..c71d48913 100644 --- a/src/include/dictu_ffi_include.h +++ b/src/include/dictu_ffi_include.h @@ -299,6 +299,7 @@ typedef struct { } CallFrame; struct _vm { + void* _compilerStub; Value stack[STACK_MAX]; Value *stackTop; bool repl; diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du index 480d9fd59..d5af15dd4 100644 --- a/tests/ffi/ffi.du +++ b/tests/ffi/ffi.du @@ -5,7 +5,7 @@ Used c code start: -#include "dictu-include.h" +#include Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { if(argCount != 2 || !IS_NUMBER(args[0]) || !IS_NUMBER(args[1])){ @@ -16,17 +16,18 @@ Value dictu_ffi_test(DictuVM *vm, int argCount, Value *args) { return NUMBER_VAL(a+b); } Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) { - return OBJ_VAL(copyString(vm, "Hello world", 11)); + return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28)); } int dictu_ffi_init(DictuVM *vm, Table *method_table) { - defineNative(vm, method_table, "dictu_ffi_test", dictu_ffi_test); - defineNative(vm, method_table, "dictu_ffi_test_str", dictu_ffi_test_str); + defineNative(vm, method_table, "dictuFFITestAdd", dictu_ffi_test); + defineNative(vm, method_table, "dictuFFITestStr", dictu_ffi_test_str); defineNativeProperty( vm, method_table, "test", OBJ_VAL(copyString(vm, "Dictu!", 6))); return 0; } + Used c code end */ diff --git a/tests/ffi/libs/test-lib.dylib b/tests/ffi/libs/test-lib.dylib index 111e0ba7e9062d32c48277bbffb8f3904daa1aba..84887d6be51b7e867e098ba80eed35f78f17d9d7 100755 GIT binary patch delta 356 zcmX@m$9SNRae@eA#YRzeCSwZ*1_lWrW&~mwa40HBEXmN%$xKR1%hWANEiTbZsRZ(% z@{^}CO%#|pPd%-i(cK&nSY{C4(bn*pejmZj@x;%m`3=BI!Mq0bxnH*|q z!k9l42$oAYchaRLA}=UQ|C delta 398 zcmX@m$9SNRae@frf{mi;OwkDp3=9%L%m~CVpdVVCT2!o`lUZe~A5fH^m6}{qtnZSU zTvDo^T9KGrkds=hpO%)X3+3o1m1gFo0F@_!1WQtjOY~AIfxOB2OcMq4UE3mL`E9PO ze4+OGkhhHAW&!3Grjr#cbvbxh7#Nys?=Vh|v@~HVW}94SDZ>;Cq1+*qA%v2KP^=K@ zJu6t{O$c=uLal{R(;-wNgvy3cp%BU*LTN%MVF>k?1#H-J2z3!c?S@cGAyhwvs)SI< z5Xu)qnL{W=2*nMdzA}T&ybq@MPBJqvcy!mk@aQgm@WN!Wt*st=8ozuCFsL`@* Date: Tue, 20 Feb 2024 20:03:01 +0100 Subject: [PATCH 132/148] fix: update binary --- tests/ffi/libs/test-lib.dll | Bin 10240 -> 10240 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ffi/libs/test-lib.dll b/tests/ffi/libs/test-lib.dll index 004a28159feea5a3a2d1a6c14868c57694a6e55d..e1f14b941919635185c0d354631cc415fc5b4335 100644 GIT binary patch delta 32 lcmZn&Xb9NA!N~me+m+4SjGLJmYd7y_2^9kK#l>F=007$X4Tt~$ delta 32 lcmZn&Xb9NA!N~mM^0Cd_jGLJm>o)Ia2^9kK#l>F=007m!4J`lw From d59434d8fcc262a0c85fd64a331691b483e277af Mon Sep 17 00:00:00 2001 From: Liz3 Date: Tue, 20 Feb 2024 20:06:57 +0100 Subject: [PATCH 133/148] fix: update binary --- tests/ffi/libs/test-lib.so | Bin 16352 -> 16352 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ffi/libs/test-lib.so b/tests/ffi/libs/test-lib.so index ea67d078a90f6dd8b8647d8bb5c73c4fec535165..cce02b91b9d78cf94dc80395fd148111624e3b29 100755 GIT binary patch delta 41 zcmV+^0M`HDf8c+x=mHeY24rI03ao|9*t&DMjbAayf2&oq`~uhx0sw!r))5LW$_x|s delta 41 zcmV+^0M`HDf8c+x=mHc@e7I9EA?u`KB$P;Mz-Jw6p6n8{`~uhx0s(%r))5LWpV1N{ From 647a8d35efb211dfdc617d71105d2c726ba580e2 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Wed, 28 Aug 2024 20:20:46 +0200 Subject: [PATCH 134/148] fix: add reallocate and memory macros to ffi --- src/include/dictu_ffi_include.h | 70 ++++++++++++++++++++++++--------- src/optionals/ffi/ffi.c | 3 +- src/optionals/ffi/ffi.h | 2 +- 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/include/dictu_ffi_include.h b/src/include/dictu_ffi_include.h index c71d48913..abefa1441 100644 --- a/src/include/dictu_ffi_include.h +++ b/src/include/dictu_ffi_include.h @@ -11,7 +11,7 @@ extern "C" { // This is used ti determine if we can safely load the function pointers without // UB. -#define FFI_MOD_API_VERSION 1 +#define FFI_MOD_API_VERSION 2 #define UNUSED(__x__) (void)__x__ @@ -155,6 +155,25 @@ typedef struct { Entry *entries; } Table; +typedef enum { + OBJ_MODULE, + OBJ_BOUND_METHOD, + OBJ_CLASS, + OBJ_ENUM, + OBJ_CLOSURE, + OBJ_FUNCTION, + OBJ_INSTANCE, + OBJ_NATIVE, + OBJ_STRING, + OBJ_LIST, + OBJ_DICT, + OBJ_SET, + OBJ_FILE, + OBJ_ABSTRACT, + OBJ_RESULT, + OBJ_UPVALUE +} ObjType; + #define OBJ_TYPE(value) (AS_OBJ(value)->type) #define AS_MODULE(value) ((ObjModule *)AS_OBJ(value)) @@ -194,24 +213,7 @@ typedef struct { #define IS_ABSTRACT(value) isObjType(value, OBJ_ABSTRACT) #define IS_RESULT(value) isObjType(value, OBJ_RESULT) -typedef enum { - OBJ_MODULE, - OBJ_BOUND_METHOD, - OBJ_CLASS, - OBJ_ENUM, - OBJ_CLOSURE, - OBJ_FUNCTION, - OBJ_INSTANCE, - OBJ_NATIVE, - OBJ_STRING, - OBJ_LIST, - OBJ_DICT, - OBJ_SET, - OBJ_FILE, - OBJ_ABSTRACT, - OBJ_RESULT, - OBJ_UPVALUE -} ObjType; + typedef enum { CLASS_DEFAULT, CLASS_ABSTRACT, CLASS_TRAIT } ClassType; @@ -232,6 +234,9 @@ struct sObj { bool isDark; struct sObj *next; }; +static inline bool isObjType(Value value, ObjType type) { + return IS_OBJ(value) && AS_OBJ(value)->type == type; +} typedef struct sUpvalue { Obj obj; @@ -454,6 +459,31 @@ typedef struct { ObjClosure *method; } ObjBoundMethod; +#define ALLOCATE(vm, type, count) \ + (type*)reallocate(vm, NULL, 0, sizeof(type) * (count)) + +#define FREE(vm, type, pointer) \ + reallocate(vm, pointer, sizeof(type), 0) + +#define GROW_CAPACITY(capacity) \ + ((capacity) < 8 ? 8 : (capacity) * 2) + +#define SHRINK_CAPACITY(capacity) \ + ((capacity) < 16 ? 8 : (capacity) / 2) + +#define GROW_ARRAY(vm, previous, type, oldCount, count) \ + (type*)reallocate(vm, previous, sizeof(type) * (oldCount), \ + sizeof(type) * (count)) + +#define SHRINK_ARRAY(vm, previous, type, oldCount, count) \ + (type*)reallocate(vm, previous, sizeof(type) * (oldCount), \ + sizeof(type) * (count)) + +#define FREE_ARRAY(vm, type, pointer, oldCount) \ + reallocate(vm, pointer, sizeof(type) * (oldCount), 0) + +typedef void *reallocate_t(DictuVM *vm, void *previous, size_t oldSize, size_t newSize); + typedef ObjString *copyString_t(DictuVM *vm, const char *chars, int length); typedef ObjList *newList_t(DictuVM *vm); @@ -520,6 +550,7 @@ typedef void defineNative_t(DictuVM *vm, Table *table, const char *name, typedef void defineNativeProperty_t(DictuVM *vm, Table *table, const char *name, Value value); +reallocate_t * reallocate = NULL; copyString_t *copyString = NULL; @@ -633,6 +664,7 @@ int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm, compareStringGreater = (compareStringGreater_t *)function_ptrs[count++]; defineNative = (defineNative_t *)function_ptrs[count++]; defineNativeProperty = (defineNativeProperty_t *)function_ptrs[count++]; + reallocate = (reallocate_t *)function_ptrs[count++]; int initResult = dictu_ffi_init(vm, methodTable); if (initResult > 0) return 3 + initResult; diff --git a/src/optionals/ffi/ffi.c b/src/optionals/ffi/ffi.c index 1782a70fc..90adec19e 100644 --- a/src/optionals/ffi/ffi.c +++ b/src/optionals/ffi/ffi.c @@ -52,7 +52,8 @@ void *ffi_function_pointers[] = {©String, &compareStringLess, &compareStringGreater, &defineNative, - &defineNativeProperty}; + &defineNativeProperty, + &reallocate}; void freeFFI(DictuVM *vm, ObjAbstract *abstract) { FFIInstance *instance = (FFIInstance *)abstract->data; diff --git a/src/optionals/ffi/ffi.h b/src/optionals/ffi/ffi.h index ef865537a..245ebcb6f 100644 --- a/src/optionals/ffi/ffi.h +++ b/src/optionals/ffi/ffi.h @@ -19,7 +19,7 @@ // This is used to determine if we can safely load the function pointers without UB, // if this is greater then the version from the mod we error in the internal mod load function. -#define DICTU_FFI_API_VERSION 1 +#define DICTU_FFI_API_VERSION 2 Value createFFIModule(DictuVM *vm); From 2a77283a9754ad59e4c98a0f9f1aa74dd73c9d20 Mon Sep 17 00:00:00 2001 From: Liz3 Date: Sat, 7 Sep 2024 21:40:19 +0200 Subject: [PATCH 135/148] fix: bump macos dylib for FFI tests --- .gitignore | 1 + tests/ffi/libs/test-lib.dylib | Bin 18240 -> 5904 bytes 2 files changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 91b5177df..67cd90909 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ test1.du /vcpkg_installed /Release examples/ffi-example/build +build_x64/ \ No newline at end of file diff --git a/tests/ffi/libs/test-lib.dylib b/tests/ffi/libs/test-lib.dylib index 84887d6be51b7e867e098ba80eed35f78f17d9d7..13c2cbc6dab0bd97e75f683f9a30635551447a8e 100755 GIT binary patch literal 5904 zcmeI0e{3AZ702K1U4j$i*afT@2<;hYMOqqC5+JIC@I|q+7ACS{Cs+z}eevzp+n(=^ zy*&~q5_M}rd~)0x1jq;pS)vtgrAQX35+_1nk~T6_YK@@Sikd1#kmjFARw^~2N@Kon z=IwcXfRGS>dZd~Ce&)xUnK!%dZuf8hyLjz7A|paX%aKdI^Il9oDp)ZWK-Iez}H}g}eEMMP_ zYTeK*?Ewci%s|N1whNg(ZYF8FnN${a<@QF!UZ?bDF1H~~>cV~-LALEJ@%DJACGb~p z4K=ak?Q@39Rl+{AJw4fs;FsE~2nL{I;By`ms#Yd=T^6!!w={2ixN%E!aHcWUOmgg{ zYYlD=PHZP^s|vgcxvs3f!OJE5?t9YiZr{oKKg4xivKJ+~skD)(Pi-9qkKZ7?2|NIY zvQOFO)D1-6WnD{j1rzh_(TW^S+|K#yq+2nF=egzIm6aPG`tgTHFP*8l`0D<PSb8p7c@PlX-?BlMZdYCsH#;H{~xuARh#*UhH4Kp4OK-|#D!=wCcTZKUu~9G#9U7;H_+IsLDh8eC_jkm8*5#o2U!cvkxs;&wkb6 zzDhlttS7_W%hvO8Y3x_6r!?{x{nyOG{np^U7JP7d#u|zn)`3s`+pWRvxRYnN3V376 zs?MC|;@wNt9a9ibO+9|f>VLJAKOs+vO{%sV~w;49x_~~b4x*69eNBJp>=~rWpRLZq!pPRw#nMB%VRJ{faif(bz z=uA7eIzH`cL(y5VX~-bcNx2zkTf%prbZ9G1g?^9EAj3Ru9~X1Hcuci3kuErK&r9^u zKa6}+BAs`7>0jtN9z(AYF2=YR=3D|B_SM_x9uH&|UB-;J## zFypUGK505=Ho0ks4w)@34*ywmyOS@ZeHt}+xyLYSmMvc3;v6q+w%*XTFQaW57Nd^y zbGm3|b9BjsqxG8Us#(Z)Q!#=KsiC|fCxLsj3&%u*zJfw#T`cz;Q;z zaqmaibF-1=Odh91XVGzr`%I&cnU&+b8tKhB?E(EVii73Z+Uc2SzVV4dB2A;H8^Dm2 zU0GV2q?1O;VqsWtd0Q9@)9?$i|BmRi{Z*KK; zblB)rcXu^&4XIRzlKF!04}>d(9}vDG+$c=nf;GVeD^xd4Ew`k??Ykzv4rTna8BCigx3rIU${g*$|2g_FYPgbTv0!uy3u_@Hp7@C(9| z!lT0D!ehb{!bgOsgii`j3;$hsukc601Hv)l4{r;RD+q0iYgL>>RVk|3$#76vM5QQa z^DlrrTT1ier363iN)#3%Scp}`D`OQCrS9|L&n|n$R8R~(bG94AGaC{joMR=!;_suc(QW~;VGoWLXP8=jbD)R c-*A<{WUDw)ia~}*Kw+E;%%Dxtcof?9aJA;Sr9;xW zetq^`0ns1wg2Nbz&t|4T%>Pq92`66rlTU4b`1|kOKK0U1@9%rD ze%ZVoeHqkXuQ&~f&B|7q8kdtdfeTIs43v+chC1+?jNRS%>mKr5gX&v_G7WE5zGDs*WET=^Y3EWpU1L4ie(>?Des1I+pz> zzMhSh{9`Qpn^^W|vFy{a>|`wK$Fg=T+aJsBjAcI^%U&7FzQ<>A!!!7YSoW8S9cx*W zezUa$hq-Q^pBOt&=~H}hdJ{cHFeDeBoJ%r>It~MkHpaR)lT~N0iDM~(L0&0n^=*FfaapwS>0^HGlSG) zO=6y@J6^)@vpC1fXAFbkjsSt5QL&JiUD!eSzMrbs$fh zecA`ljik39XIk+bY?%o(TRAuLh^YU>Qik7G-TyoG52d?agQqC_37BU;g$8dU+&!dR zfPR^S=PajCC};Y-axv5E4%hrlUtfQwSkC(e=UU2h4>|^MOS&hY@4y2!kNEa9DYt9Y z9b}$`OZ3UVE__!$iznCc-aFgTg0BR3l?~iE#`_J*s*wTaZ<#BXRRT8qePA(cdKt$I zm-Ji5475$Ol(^e-ay7@JtM)q8Dy4C0f1JCEm7M2bOMGAdn#!nHH>7A;`L>T4#sRNf zalG0nnJJo8y)&wvMw_JeH_^;~hnsI3Hg5itM+vv&)~KjdIs(GOM7VTr({~NGghiBc z1)H%NHjOp*It8cZ(1Uk7HOdX3Ipo{)J%bX?h+A^@=W6aF4&8&7LeCp1I;o~##`>{E zwF^vlf3Dy=J)V~vr3*&2FIT8KqqKz4r`5P=)y}H+q-y6?JEz(+<3_^tys}5nCI=F7}e&<6N7X-RW-li=L+;x3LgVIeQ3B$ zpU=~;jSCrmo6D4=Lj_t6?!h|`K6j$bb|f7maJkO?MUM1RJNn^Buz4)EUull(siK0o+Osg(_Q{+|Ghn}RZpt}vfd{{EbIMAh;in*a3 Date: Sat, 7 Sep 2024 21:48:11 +0200 Subject: [PATCH 136/148] did the workers change to arm? --- tests/ffi/libs/test-lib.dylib | Bin 5904 -> 18512 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/ffi/libs/test-lib.dylib b/tests/ffi/libs/test-lib.dylib index 13c2cbc6dab0bd97e75f683f9a30635551447a8e..082eceff59ea38fcb832acc7a6d93fedcfc37e4f 100755 GIT binary patch literal 18512 zcmeHPYiwLc6+ZWo)DCWvLJW>b(3&=F0%>ZRRG88IP5e){U%0wc#5v5UUMczopoHO@a z`+6aO_=#rZd3@iQId|rpxo7=n?r(0q_xCCQ1u)IWya;oj2JjRtCJL5fu1BkB1_SLu zLCr0Uxeyr7Lz*(W63H~v*1j|YtjhiA4>&f12M|_gy94Nu^+MC^NTuyad>51D{u(zp zhE}$_*!3~THY?p>zZ*sUg60olT<(|AQg}bNCl(=kP1izqyka_sen{KDj*e*3P=T{0#X5~fK)&#AQg}bNCl(=kP1izqyqo<3QU@>6|V183KLt^!c>n|n0f>Hs{w}c^NrFtz!@K8 zw@>vvg!TsP=Pyi}Z{~}ddFfCE?70dMG;U)5P*YD#Xv&F-JB&hpK9umD<4|QK)_3>| z3$WdCD|5FI*Whr~%q=DEA%|PeTrF{p4!452Rm24x?r!EjM_iM`-N)P)h--GZ_00K+ zYjL;$bFIX+I^1UFzD(Sg9PTU3eU-S44)--+I8YOdqaFZPe2wtvz-b^??Qmqrd6 zj{Qy7{s7vS%-FB@8YS9Kyh@s@t$9$`&f&h%SZ&>w)55pz@Z__oZn%V3bN}VOU*GvU zo&^QZ3Z9p*L;r_3j|mMi02oST`$&RhLxdD z0d&4dXM3vWXN4&Z`e|M>^I5#UzgKfK1JrD)=jY;CEmky|@HN?qn6EL?kuv!Wz1$N8{P$C)_qbz^bwnaJ{_nD9sPq{B7TSBG&d zL2b6JP};Jga+8%x!6F^{vP8#{A=|>$(tZ8vWH-0?`HGqWgcq9!mAz+sVNA}@^Iy)mK^eT}!P9h$PnuJBS z96qPfidtz49&WbM5Ng9>SH^_zD4<%Mk+`)bl#cARU?c7qoK|$miN|L}c}=VWAGaeE z%~*ch4t2v7CDjy)rmSxGEA}439y$z&GB3)UC`UwD6y@2hq6Ta`VZ*CxTc)FfBs!_; zFo;%|?|%%J6~c!9TivprfWulM3D0OKzq0`Nww6ilhGW<%>kOx^sujX>+=2TC!&)Yuj>Ig- z*{`r)Q9NKslxML7jn({{MsiMQt??9YAKbvcBcj)N>ZK-luV2u+lUC40gF0@ycxDh@ z)l-2znNSppNcPd71sw@k9fn^jowj9p6dzL}@PQJyy5PK;gyWhG7qt{VJge`eZGmCE z%Z{YIBi`1J>>JWwRt$0A@i@XY!#T)w_n+`M3QSKh#TWfeC=i;6af*Vs3D>hHAI}E z21lydrV~bHu^aq|5o=0PlrobTrOf1Pl=8IMLz2RliN7&!pfYW5pfWKUxWZvm=!P|i zCR0R-nHa>-8?77nCUY( z&2>Iid@6*ge^+USYsF88(3W~WqH;8rx$V=<$-bxeZeQ`pq09HL{^_w(m47+*)+0L_ zatpgQYo`vKJl&ocez&uz|L($tC)BO&^QQNo+5hBIe|Y_yEzhn#{-5jzp5Obu9k<*+ z-FM&P(fTz*cJadTb4%a*zTdxV`ufotxcpisb>#<7uKoS?;hG=+y6RL#^;=60g8j}9 PYYr^i`O3sy(*XYfmQ|Rj literal 5904 zcmeI0e{3AZ702K1U4j$i*afT@2<;hYMOqqC5+JIC@I|q+7ACS{Cs+z}eevzp+n(=^ zy*&~q5_M}rd~)0x1jq;pS)vtgrAQX35+_1nk~T6_YK@@Sikd1#kmjFARw^~2N@Kon z=IwcXfRGS>dZd~Ce&)xUnK!%dZuf8hyLjz7A|paX%aKdI^Il9oDp)ZWK-Iez}H}g}eEMMP_ zYTeK*?Ewci%s|N1whNg(ZYF8FnN${a<@QF!UZ?bDF1H~~>cV~-LALEJ@%DJACGb~p z4K=ak?Q@39Rl+{AJw4fs;FsE~2nL{I;By`ms#Yd=T^6!!w={2ixN%E!aHcWUOmgg{ zYYlD=PHZP^s|vgcxvs3f!OJE5?t9YiZr{oKKg4xivKJ+~skD)(Pi-9qkKZ7?2|NIY zvQOFO)D1-6WnD{j1rzh_(TW^S+|K#yq+2nF=egzIm6aPG`tgTHFP*8l`0D<PSb8p7c@PlX-?BlMZdYCsH#;H{~xuARh#*UhH4Kp4OK-|#D!=wCcTZKUu~9G#9U7;H_+IsLDh8eC_jkm8*5#o2U!cvkxs;&wkb6 zzDhlttS7_W%hvO8Y3x_6r!?{x{nyOG{np^U7JP7d#u|zn)`3s`+pWRvxRYnN3V376 zs?MC|;@wNt9a9ibO+9|f>VLJAKOs+vO{%sV~w;49x_~~b4x*69eNBJp>=~rWpRLZq!pPRw#nMB%VRJ{faif(bz z=uA7eIzH`cL(y5VX~-bcNx2zkTf%prbZ9G1g?^9EAj3Ru9~X1Hcuci3kuErK&r9^u zKa6}+BAs`7>0jtN9z(AYF2=YR=3D|B_SM_x9uH&|UB-;J## zFypUGK505=Ho0ks4w)@34*ywmyOS@ZeHt}+xyLYSmMvc3;v6q+w%*XTFQaW57Nd^y zbGm3|b9BjsqxG8Us#(Z)Q!#=KsiC|fCxLsj3&%u*zJfw#T`cz;Q;z zaqmaibF-1=Odh91XVGzr`%I&cnU&+b8tKhB?E(EVii73Z+Uc2SzVV4dB2A;H8^Dm2 zU0GV2q?1O;VqsWtd0Q9@)9?$i|BmRi{Z*KK; zblB)rcXu^&4XIRzlKF!04}>d(9}vDG+$c=nf;GVeD^xd4Ew`k??Ykzv4rTna8BCigx3rIU${g*$|2g_FYPgbTv0!uy3u_@Hp7@C(9| z!lT0D!ehb{!bgOsgii`j3;$hsukc601Hv)l4{r;RD+q0iYgL>>RVk|3$#76vM5QQa z^DlrrTT1ier363iN)#3%Scp}`D`OQCrS9|L&n|n$R8R~(bG94AGaC{joMR=!;_suc(QW~;VGoWLXP8=jbD)R c-*A<{WUDw)ia~ Date: Sun, 8 Sep 2024 22:26:05 -0700 Subject: [PATCH 137/148] allow negative index for insert Signed-off-by: Brian Downs --- src/vm/datatypes/lists/lists.c | 4 ++++ tests/lists/insert.du | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/vm/datatypes/lists/lists.c b/src/vm/datatypes/lists/lists.c index 464d561e2..e67e16644 100644 --- a/src/vm/datatypes/lists/lists.c +++ b/src/vm/datatypes/lists/lists.c @@ -84,10 +84,14 @@ static Value insertListItem(DictuVM *vm, int argCount, Value *args) { Value insertValue = args[1]; int index = AS_NUMBER(args[2]); + if (index < 0) { + index = list->values.count + index+1; + } if (index < 0 || index > list->values.count) { runtimeError(vm, "Index passed to insert() is out of bounds for the list given"); return EMPTY_VAL; } + printf("XXX - index: %d\n", index); if (list->values.capacity < list->values.count + 1) { int oldCapacity = list->values.capacity; diff --git a/tests/lists/insert.du b/tests/lists/insert.du index c8e7d090a..492848717 100644 --- a/tests/lists/insert.du +++ b/tests/lists/insert.du @@ -23,6 +23,9 @@ class TestListInsert < UnitTest { x.insert(0, 0); this.assertEquals(x, [0, 1, 2, 3, 4, 5, 6, 7]); + + x.insert(8, -1); + this.assertEquals(x, [0, 1, 2, 3, 4, 5, 6, 7, 8]); } } From ecebf26f2d4c8235ac85a066877bf727e75992ad Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 8 Sep 2024 22:39:02 -0700 Subject: [PATCH 138/148] allow negative index for pop Signed-off-by: Brian Downs --- src/vm/datatypes/lists/lists.c | 7 ++++--- tests/lists/pop.du | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vm/datatypes/lists/lists.c b/src/vm/datatypes/lists/lists.c index e67e16644..e44a3fdb0 100644 --- a/src/vm/datatypes/lists/lists.c +++ b/src/vm/datatypes/lists/lists.c @@ -91,7 +91,6 @@ static Value insertListItem(DictuVM *vm, int argCount, Value *args) { runtimeError(vm, "Index passed to insert() is out of bounds for the list given"); return EMPTY_VAL; } - printf("XXX - index: %d\n", index); if (list->values.capacity < list->values.count + 1) { int oldCapacity = list->values.capacity; @@ -133,9 +132,11 @@ static Value popListItem(DictuVM *vm, int argCount, Value *args) { } int index = AS_NUMBER(args[1]); - + if (index < 0) { + index = list->values.count + index; + } if (index < 0 || index > list->values.count) { - runtimeError(vm, "Index passed to pop() is out of bounds for the list given"); + runtimeError(vm, "Index passed to insert() is out of bounds for the list given"); return EMPTY_VAL; } diff --git a/tests/lists/pop.du b/tests/lists/pop.du index 04e73c3ad..5d34d3369 100644 --- a/tests/lists/pop.du +++ b/tests/lists/pop.du @@ -23,6 +23,14 @@ class TestListPop < UnitTest { y = x.pop(0); this.assertEquals(y, 1); this.assertEquals(x, [2, 3, 4]); + + y = x.pop(-2); + this.assertEquals(y, 3); + this.assertEquals(x, [2, 4]); + + y = x.pop(-2); + this.assertEquals(y, 2); + this.assertEquals(x, [4]); } } From 7cc6cb817aa9c2f6e0cedb4255379e8db1207bb4 Mon Sep 17 00:00:00 2001 From: Brian Downs Date: Sun, 8 Sep 2024 22:42:50 -0700 Subject: [PATCH 139/148] add another test Signed-off-by: Brian Downs --- tests/lists/insert.du | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/lists/insert.du b/tests/lists/insert.du index 492848717..0883da17b 100644 --- a/tests/lists/insert.du +++ b/tests/lists/insert.du @@ -26,6 +26,9 @@ class TestListInsert < UnitTest { x.insert(8, -1); this.assertEquals(x, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + + x.insert(28, -4); + this.assertEquals(x, [0, 1, 2, 3, 4, 5, 28, 6, 7, 8]); } } From 65373affbd67a528315aec5eee1a09c09b550112 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 12 Sep 2024 00:22:50 +0200 Subject: [PATCH 140/148] feat: add System.arch constant --- src/optionals/arch.h | 58 +++++++++++++++++++++++++++++++++++++++ src/optionals/system.c | 2 ++ src/optionals/system.h | 13 +++++---- tests/system/constants.du | 8 ++++++ 4 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 src/optionals/arch.h diff --git a/src/optionals/arch.h b/src/optionals/arch.h new file mode 100644 index 000000000..ab0eebed2 --- /dev/null +++ b/src/optionals/arch.h @@ -0,0 +1,58 @@ +#ifndef dictu_system_arch_h +#define dictu_system_arch_h + +// https://stackoverflow.com/a/66249936 + +#if defined(__x86_64__) || defined(_M_X64) +#define SYSTEM_ARCH "x86_64" +#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) +#define SYSTEM_ARCH "x86_32" +#elif defined(__ARM_ARCH_2__) +#define SYSTEM_ARCH "arm2" +#elif defined(__ARM_ARCH_3__) || defined(__ARM_ARCH_3M__) +#define SYSTEM_ARCH "arm3" +#elif defined(__ARM_ARCH_4T__) || defined(__TARGET_ARM_4T) +#define SYSTEM_ARCH "arm4t" +#elif defined(__ARM_ARCH_5_) || defined(__ARM_ARCH_5E_) +#define SYSTEM_ARCH "arm6" +#elif defined(__ARM_ARCH_6T2_) || defined(__ARM_ARCH_6T2_) +#define SYSTEM_ARCH "arm6t2" +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6ZK__) +#define SYSTEM_ARCH "arm6" +#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7S__) +#define SYSTEM_ARCH "arm7" +#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \ + defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) +#define SYSTEM_ARCH "arm7a" +#elif defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7S__) +#define SYSTEM_ARCH "arm7r" +#elif defined(__ARM_ARCH_7M__) +#define SYSTEM_ARCH "arm7m" +#elif defined(__ARM_ARCH_7S__) +#define SYSTEM_ARCH "arm7s" +#elif defined(__aarch64__) || defined(_M_ARM64) +#define SYSTEM_ARCH "arm64" +#elif defined(mips) || defined(__mips__) || defined(__mips) +#define SYSTEM_ARCH "mips" +#elif defined(__sh__) +#define SYSTEM_ARCH "superh" +#elif defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || \ + defined(_ARCH_PPC) +#define SYSTEM_ARCH "powerpc" +#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64) +#define SYSTEM_ARCH "powerpc_x64" +#elif defined(__sparc__) || defined(__sparc) +#define SYSTEM_ARCH "spark" +#elif defined(__m68k__) +#define SYSTEM_ARCH "m68k" +#else +#define SYSTEM_ARCH "unknown" +#endif + +#endif \ No newline at end of file diff --git a/src/optionals/system.c b/src/optionals/system.c index da8d35fef..9a17a8b37 100644 --- a/src/optionals/system.c +++ b/src/optionals/system.c @@ -624,6 +624,8 @@ Value createSystemModule(DictuVM *vm) { initPlatform(vm, &module->values); setVersion(vm, &module->values); + defineNativeProperty(vm, &module->values, "arch", OBJ_VAL(copyString(vm, SYSTEM_ARCH, strlen(SYSTEM_ARCH)))); + defineNativeProperty(vm, &module->values, "S_IRWXU", NUMBER_VAL(448)); defineNativeProperty(vm, &module->values, "S_IRUSR", NUMBER_VAL(256)); defineNativeProperty(vm, &module->values, "S_IWUSR", NUMBER_VAL(128)); diff --git a/src/optionals/system.h b/src/optionals/system.h index 4fe1851e6..d6731566b 100644 --- a/src/optionals/system.h +++ b/src/optionals/system.h @@ -1,11 +1,11 @@ #ifndef dictu_system_h #define dictu_system_h -#include +#include #include #include #include -#include +#include #ifdef _WIN32 #include "windowsapi.h" @@ -13,18 +13,19 @@ #define REMOVE remove #define MKDIR(d, m) ((void)m, _mkdir(d)) #else -#include #include +#include #define HAS_ACCESS #define REMOVE unlink #define MKDIR(d, m) mkdir(d, m) #endif -#include "optionals.h" #include "../vm/common.h" -#include "../vm/vm.h" #include "../vm/memory.h" +#include "../vm/vm.h" +#include "optionals.h" +#include "arch.h" Value createSystemModule(DictuVM *vm); -#endif //dictu_system_h +#endif // dictu_system_h diff --git a/tests/system/constants.du b/tests/system/constants.du index 59450051d..91e91a5e3 100644 --- a/tests/system/constants.du +++ b/tests/system/constants.du @@ -26,6 +26,14 @@ class TestSystemConstants < UnitTest { this.assertType(System.platform, 'string'); this.assertTruthy(System.platform.len() > 0); } + + /** + * arch stores the current system archictecture as a string + */ + testSysArch() { + this.assertType(System.arch, 'string'); + this.assertTruthy(System.arch.len() > 0); + } } TestSystemConstants().run(); \ No newline at end of file From bad6467bcfc9d961cbf4d8757a4b7a087203b996 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 12 Sep 2024 00:26:19 +0200 Subject: [PATCH 141/148] add docs --- docs/docs/standard-lib/system.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index 08da7200f..0e8a099c0 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -29,6 +29,7 @@ import System; | --------------- | ------------------------------------------------------------------------------------------------- | | System.argv | The list of command line arguments. The first element of the argv list is always the script name. | | System.platform | This string identifies the underlying system platform. | +| System.arch | This string identifies theunderlying process architecture. | | System.version | Dictionary containing Dictu major, minor and patch versions. | | System.S_IRWXU | Read, write, and execute by owner. | | System.S_IRUSR | Read by owner. | From 40448c2582cbde5ba65a148e732bffeb4a5c8d24 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 12 Sep 2024 00:28:19 +0200 Subject: [PATCH 142/148] fix formatting --- src/optionals/system.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/optionals/system.h b/src/optionals/system.h index d6731566b..aec659f0a 100644 --- a/src/optionals/system.h +++ b/src/optionals/system.h @@ -1,11 +1,11 @@ #ifndef dictu_system_h #define dictu_system_h -#include +#include #include #include #include -#include +#include #ifdef _WIN32 #include "windowsapi.h" @@ -13,19 +13,19 @@ #define REMOVE remove #define MKDIR(d, m) ((void)m, _mkdir(d)) #else -#include #include +#include #define HAS_ACCESS #define REMOVE unlink #define MKDIR(d, m) mkdir(d, m) #endif +#include "optionals.h" #include "../vm/common.h" -#include "../vm/memory.h" #include "../vm/vm.h" -#include "optionals.h" +#include "../vm/memory.h" #include "arch.h" Value createSystemModule(DictuVM *vm); -#endif // dictu_system_h +#endif //dictu_system_h From e4887173342fe658a8bd6ea79d72ab666bdc09e2 Mon Sep 17 00:00:00 2001 From: "Liz3 (Yann HN)" Date: Thu, 12 Sep 2024 00:32:04 +0200 Subject: [PATCH 143/148] fix: docs typo --- docs/docs/standard-lib/system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/standard-lib/system.md b/docs/docs/standard-lib/system.md index 0e8a099c0..66f5a30be 100644 --- a/docs/docs/standard-lib/system.md +++ b/docs/docs/standard-lib/system.md @@ -29,7 +29,7 @@ import System; | --------------- | ------------------------------------------------------------------------------------------------- | | System.argv | The list of command line arguments. The first element of the argv list is always the script name. | | System.platform | This string identifies the underlying system platform. | -| System.arch | This string identifies theunderlying process architecture. | +| System.arch | This string identifies the underlying process architecture. | | System.version | Dictionary containing Dictu major, minor and patch versions. | | System.S_IRWXU | Read, write, and execute by owner. | | System.S_IRUSR | Read by owner. | From 9fdd7b63414bc67a6721975843a43f12819819e0 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 12 Sep 2024 17:51:00 +0100 Subject: [PATCH 144/148] Update src/vm/datatypes/lists/lists.c --- src/vm/datatypes/lists/lists.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/datatypes/lists/lists.c b/src/vm/datatypes/lists/lists.c index e44a3fdb0..7389e3904 100644 --- a/src/vm/datatypes/lists/lists.c +++ b/src/vm/datatypes/lists/lists.c @@ -136,7 +136,7 @@ static Value popListItem(DictuVM *vm, int argCount, Value *args) { index = list->values.count + index; } if (index < 0 || index > list->values.count) { - runtimeError(vm, "Index passed to insert() is out of bounds for the list given"); + runtimeError(vm, "Index passed to pop() is out of bounds for the list given"); return EMPTY_VAL; } From a0ba56b419fa6173a9150e64aabccd7d164aa95e Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 12 Sep 2024 17:54:34 +0100 Subject: [PATCH 145/148] Bump mac os --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 02fb71d18..9bdf2d00c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macOS-latest, macOS-11] + os: [macOS-latest, macOS-13, macOS-12] steps: - uses: actions/checkout@v3 From 6b94dec6c8f96d3803a38884c82e8ce0929d86c7 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 12 Sep 2024 18:03:05 +0100 Subject: [PATCH 146/148] Handle intel / ARM on mac for tests --- tests/ffi/ffi.du | 5 ++++- tests/ffi/libs/test-lib_64.dylib | Bin 0 -> 18240 bytes .../libs/{test-lib.dylib => test-lib_arm.dylib} | Bin 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100755 tests/ffi/libs/test-lib_64.dylib rename tests/ffi/libs/{test-lib.dylib => test-lib_arm.dylib} (100%) diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du index d5af15dd4..21ad1cbfa 100644 --- a/tests/ffi/ffi.du +++ b/tests/ffi/ffi.du @@ -38,7 +38,10 @@ import Path; class TestFFIModule < UnitTest { testFFIModule() { - const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}".format(FFI.suffix)); + const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}{}".format( + System.platform == "darwin" ? System.arch == "x86_64" ? "_64" : "_arm" : "", + FFI.suffix + )); const mod = FFI.load(path); this.assertEquals(mod.test, "Dictu!"); for(var i = 0; i < 40; i+=2) { diff --git a/tests/ffi/libs/test-lib_64.dylib b/tests/ffi/libs/test-lib_64.dylib new file mode 100755 index 0000000000000000000000000000000000000000..84887d6be51b7e867e098ba80eed35f78f17d9d7 GIT binary patch literal 18240 zcmeHPe{38_6@GhnZd0JSM5rSCQm!hkXrXP|P;eE6o`ct2(}*Kw+E;%%Dxtcof?9aJA;Sr9;xW zetq^`0ns1wg2Nbz&t|4T%>Pq92`66rlTU4b`1|kOKK0U1@9%rD ze%ZVoeHqkXuQ&~f&B|7q8kdtdfeTIs43v+chC1+?jNRS%>mKr5gX&v_G7WE5zGDs*WET=^Y3EWpU1L4ie(>?Des1I+pz> zzMhSh{9`Qpn^^W|vFy{a>|`wK$Fg=T+aJsBjAcI^%U&7FzQ<>A!!!7YSoW8S9cx*W zezUa$hq-Q^pBOt&=~H}hdJ{cHFeDeBoJ%r>It~MkHpaR)lT~N0iDM~(L0&0n^=*FfaapwS>0^HGlSG) zO=6y@J6^)@vpC1fXAFbkjsSt5QL&JiUD!eSzMrbs$fh zecA`ljik39XIk+bY?%o(TRAuLh^YU>Qik7G-TyoG52d?agQqC_37BU;g$8dU+&!dR zfPR^S=PajCC};Y-axv5E4%hrlUtfQwSkC(e=UU2h4>|^MOS&hY@4y2!kNEa9DYt9Y z9b}$`OZ3UVE__!$iznCc-aFgTg0BR3l?~iE#`_J*s*wTaZ<#BXRRT8qePA(cdKt$I zm-Ji5475$Ol(^e-ay7@JtM)q8Dy4C0f1JCEm7M2bOMGAdn#!nHH>7A;`L>T4#sRNf zalG0nnJJo8y)&wvMw_JeH_^;~hnsI3Hg5itM+vv&)~KjdIs(GOM7VTr({~NGghiBc z1)H%NHjOp*It8cZ(1Uk7HOdX3Ipo{)J%bX?h+A^@=W6aF4&8&7LeCp1I;o~##`>{E zwF^vlf3Dy=J)V~vr3*&2FIT8KqqKz4r`5P=)y}H+q-y6?JEz(+<3_^tys}5nCI=F7}e&<6N7X-RW-li=L+;x3LgVIeQ3B$ zpU=~;jSCrmo6D4=Lj_t6?!h|`K6j$bb|f7maJkO?MUM1RJNn^Buz4)EUull(siK0o+Osg(_Q{+|Ghn}RZpt}vfd{{EbIMAh;in*a3 Date: Thu, 12 Sep 2024 18:05:08 +0100 Subject: [PATCH 147/148] Import System --- tests/ffi/ffi.du | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ffi/ffi.du b/tests/ffi/ffi.du index 21ad1cbfa..a072f0d47 100644 --- a/tests/ffi/ffi.du +++ b/tests/ffi/ffi.du @@ -31,6 +31,7 @@ int dictu_ffi_init(DictuVM *vm, Table *method_table) { Used c code end */ +import System; from UnitTest import UnitTest; import FFI; From 029706a5a41cde9b59cc93aef86439646b5969a4 Mon Sep 17 00:00:00 2001 From: Jason_000 Date: Thu, 12 Sep 2024 18:42:48 +0100 Subject: [PATCH 148/148] Bump version --- docs/_config.yml | 2 +- src/include/dictu_include.h | 2 +- vcpkg.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_config.yml b/docs/_config.yml index 0b3a8c27e..702915e10 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -5,7 +5,7 @@ description: >- color_scheme: "dictu" # Custom theme logo: "/assets/images/dictu-logo/dictu-wordmark.svg" -version: "0.29.0" +version: "0.30.0" github_username: dictu-lang search_enabled: true diff --git a/src/include/dictu_include.h b/src/include/dictu_include.h index 256fde3d1..273ff8bad 100644 --- a/src/include/dictu_include.h +++ b/src/include/dictu_include.h @@ -4,7 +4,7 @@ #include #define DICTU_MAJOR_VERSION "0" -#define DICTU_MINOR_VERSION "29" +#define DICTU_MINOR_VERSION "30" #define DICTU_PATCH_VERSION "0" #define DICTU_STRING_VERSION "Dictu Version: " DICTU_MAJOR_VERSION "." DICTU_MINOR_VERSION "." DICTU_PATCH_VERSION "\n" diff --git a/vcpkg.json b/vcpkg.json index faba17832..db7a1175a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "dictu", - "version": "0.28.0", + "version": "0.30.0", "dependencies": [ "curl" ]