From 3238c2fb8e4275b5a00186daff5d6b48ab326df6 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Wed, 1 Dec 2021 13:19:18 +0100 Subject: [PATCH] added strcat builtin --- samples/deepfailure.noja | 18 +++++----- samples/strcat.noja | 22 ++++++++++++ src/runtime/o_builtins.c | 77 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 samples/strcat.noja diff --git a/samples/deepfailure.noja b/samples/deepfailure.noja index 6584a67..5dacddd 100644 --- a/samples/deepfailure.noja +++ b/samples/deepfailure.noja @@ -1,12 +1,14 @@ -depth = 9; - -fun fail(p) +fun fail_at_depth(depth) { - if p < depth: - fail(p+1, depth, fail); - else - assert(false); + fun fail(current_depth) + { + assert(current_depth < depth); + fail(current_depth + 1); + } + + fail(0); } -fail(0); \ No newline at end of file + +fail_at_depth(9); \ No newline at end of file diff --git a/samples/strcat.noja b/samples/strcat.noja new file mode 100644 index 0000000..a875948 --- /dev/null +++ b/samples/strcat.noja @@ -0,0 +1,22 @@ + +A = 'Hello'; +B = ', '; +C = 'world'; +D = strcat(A, B, C); + +fun append_esclamation_mark(A, n) +{ + if n == none: + n = 1; + + i = 0; + while i < n: + { + A = strcat(A, '!'); + i = i + 1; + } + + return A; +} + +print(append_esclamation_mark(D, 7), '\n'); \ No newline at end of file diff --git a/src/runtime/o_builtins.c b/src/runtime/o_builtins.c index b6ef4ad..c7ba38a 100644 --- a/src/runtime/o_builtins.c +++ b/src/runtime/o_builtins.c @@ -1,15 +1,17 @@ #include #include #include +#include #include "runtime.h" #include "../utils/defs.h" -static Object *select(Object *self, Object *key, Heap *heap, Error *err); +static Object *select_(Object *self, Object *key, Heap *heap, Error *err); static int count(Object *self); static Object *bin_print (Runtime *runtime, Object **argv, unsigned int argc, Error *error); static Object *bin_count (Runtime *runtime, Object **argv, unsigned int argc, Error *error); static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error); typedef struct { Object base; @@ -20,12 +22,12 @@ static const Type t_builtins_map = { .base = (Object) { .type = &t_type, .flags = Object_STATIC }, .name = "builtins map", .size = sizeof(BuiltinsMapOjbect), - .select = select, + .select = select_, .count = count, .print = NULL, }; -static Object *select(Object *self, Object *key, Heap *heap, Error *err) +static Object *select_(Object *self, Object *key, Heap *heap, Error *err) { BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) self; @@ -68,6 +70,14 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err) return Object_FromNativeFunction(bm->runtime, bin_assert, -1, heap, err); return NULL; } + + case PAIR(sizeof("strcat")-1, 's'): + { + if(!strcmp(s, "strcat")) + return Object_FromNativeFunction(bm->runtime, bin_strcat, -1, heap, err); + + return NULL; + } } // Not found. @@ -126,4 +136,63 @@ static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Er Error_Report(error, 0, "Assertion failed"); return NULL; } -} \ No newline at end of file +} + +static Object *bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + unsigned int total_count = 0; + + for(unsigned int i = 0; i < argc; i += 1) + { + if(!Object_IsString(argv[i])) + { + Error_Report(error, 0, "Argument #%d is not a string", i+1); + return NULL; + } + + total_count += Object_Count(argv[i], error); + + if(error->occurred) + return NULL; + } + + char starting[128]; + char *buffer = starting; + + if(total_count > sizeof(starting)-1) + { + buffer = malloc(total_count+1); + + if(buffer == NULL) + { + Error_Report(error, 1, "No memory"); + return NULL; + } + } + + Object *result = NULL; + + for(unsigned int i = 0, written = 0; i < argc; i += 1) + { + int n; + const char *s; + + s = Object_ToString(argv[i], &n, Runtime_GetHeap(runtime), error); + + if(error->occurred) + goto done; + + memcpy(buffer + written, s, n); + written += n; + } + + buffer[total_count] = '\0'; + + result = Object_FromString(buffer, total_count, Runtime_GetHeap(runtime), error); + +done: + if(starting != buffer) + free(buffer); + return result; +} +