added strcat builtin

This commit is contained in:
Francesco Cozzuto
2021-12-01 13:19:18 +01:00
parent fba9698b8b
commit 3238c2fb8e
3 changed files with 105 additions and 12 deletions
+10 -8
View File
@@ -1,12 +1,14 @@
depth = 9; fun fail_at_depth(depth)
fun fail(p)
{ {
if p < depth: fun fail(current_depth)
fail(p+1, depth, fail); {
else assert(current_depth < depth);
assert(false); fail(current_depth + 1);
}
fail(0);
} }
fail(0);
fail_at_depth(9);
+22
View File
@@ -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');
+73 -4
View File
@@ -1,15 +1,17 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include "runtime.h" #include "runtime.h"
#include "../utils/defs.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 int count(Object *self);
static Object *bin_print (Runtime *runtime, Object **argv, unsigned int argc, Error *error); 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_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_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 { typedef struct {
Object base; Object base;
@@ -20,12 +22,12 @@ static const Type t_builtins_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "builtins map", .name = "builtins map",
.size = sizeof(BuiltinsMapOjbect), .size = sizeof(BuiltinsMapOjbect),
.select = select, .select = select_,
.count = count, .count = count,
.print = NULL, .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; 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 Object_FromNativeFunction(bm->runtime, bin_assert, -1, heap, err);
return NULL; 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. // Not found.
@@ -126,4 +136,63 @@ static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Er
Error_Report(error, 0, "Assertion failed"); Error_Report(error, 0, "Assertion failed");
return NULL; return NULL;
} }
} }
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;
}