diff --git a/build.sh b/build.sh index 71ce94d..bb6aff2 100755 --- a/build.sh +++ b/build.sh @@ -22,6 +22,7 @@ gcc -c src/objects/o_none.c -o temp/objects/o_none.o $FLAGS gcc -c src/objects/o_bool.c -o temp/objects/o_bool.o $FLAGS gcc -c src/objects/o_float.c -o temp/objects/o_float.o $FLAGS gcc -c src/objects/o_string.c -o temp/objects/o_string.o $FLAGS +gcc -c src/objects/o_buffer.c -o temp/objects/o_buffer.o $FLAGS gcc -c src/objects/o_closure.c -o temp/objects/o_closure.o $FLAGS gcc -c src/objects/objects.c -o temp/objects/objects.o $FLAGS @@ -81,6 +82,7 @@ gcc src/main.c \ temp/objects/o_none.o \ temp/objects/o_list.o \ temp/objects/o_bool.o \ + temp/objects/o_buffer.o \ temp/objects/o_string.o \ temp/objects/o_closure.o \ temp/runtime/runtime.o \ diff --git a/samples/buffer.noja b/samples/buffer.noja new file mode 100644 index 0000000..537bea9 --- /dev/null +++ b/samples/buffer.noja @@ -0,0 +1,6 @@ + +b = newBuffer(16); + +b[2] = 10; + +print(b); \ No newline at end of file diff --git a/src/o_builtins.c b/src/o_builtins.c index 5a4341d..8981811 100644 --- a/src/o_builtins.c +++ b/src/o_builtins.c @@ -12,6 +12,7 @@ static Object *bin_print (Runtime *runtime, Object **argv, unsigned int argc, Er 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); +static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error); typedef struct { Object base; @@ -78,6 +79,14 @@ static Object *select_(Object *self, Object *key, Heap *heap, Error *err) return NULL; } + + case PAIR(sizeof("newBuffer")-1, 'n'): + { + if(!strcmp(s, "newBuffer")) + return Object_FromNativeFunction(bm->runtime, bin_newBuffer, -1, heap, err); + + return NULL; + } } // Not found. @@ -196,3 +205,14 @@ done: return result; } +static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + int size = Object_ToInt(argv[0], error); + + if(error->occurred == 1) + return NULL; + + return Object_NewBuffer(size, Runtime_GetHeap(runtime), error); +} \ No newline at end of file diff --git a/src/objects/o_buffer.c b/src/objects/o_buffer.c new file mode 100644 index 0000000..a8a1ca0 --- /dev/null +++ b/src/objects/o_buffer.c @@ -0,0 +1,148 @@ +#include +#include "../utils/defs.h" +#include "objects.h" + +typedef struct { + Object base; + int size; + unsigned char *body; +} BufferObject; + +static Object *select(Object *self, Object *key, Heap *heap, Error *err); +static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err); +static int count(Object *self); +static void print(Object *obj, FILE *fp); + +static const Type t_buffer = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "buffer", + .size = sizeof (BufferObject), + .select = select, + .insert = insert, + .count = count, + .print = print, +}; + +Object *Object_NewBuffer(int size, Heap *heap, Error *error) +{ + assert(size >= 0); + + // Make the thing. + BufferObject *obj; + { + obj = (BufferObject*) Heap_Malloc(heap, &t_buffer, error); + + if(obj == NULL) + return NULL; + + obj->size = size; + obj->body = Heap_RawMalloc(heap, sizeof(unsigned char) * size, error); + + if(obj->body == NULL) + return NULL; + } + + return (Object*) obj; +} + +static Object *select(Object *self, Object *key, Heap *heap, Error *error) +{ + assert(self != NULL); + assert(self->type == &t_buffer); + assert(key != NULL); + assert(heap != NULL); + assert(error != NULL); + + if(!Object_IsInt(key)) + { + Error_Report(error, 0, "Non integer key"); + return NULL; + } + + int idx = Object_ToInt(key, error); + assert(error->occurred == 0); + + BufferObject *buffer = (BufferObject*) self; + + if(idx < 0 || idx >= buffer->size) + { + Error_Report(error, 0, "Out of range index"); + return NULL; + } + + unsigned char byte = buffer->body[idx]; + + return Object_FromInt(byte, heap, error); +} + +static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *error) +{ + assert(error != NULL); + assert(key != NULL); + assert(val != NULL); + assert(heap != NULL); + assert(self != NULL); + assert(self->type == &t_buffer); + + BufferObject *buffer = (BufferObject*) self; + + if(!Object_IsInt(key)) + { + Error_Report(error, 0, "Non integer key"); + return NULL; + } + + int idx = Object_ToInt(key, error); + assert(error->occurred == 0); + + if(idx < 0 || idx >= buffer->size) + { + Error_Report(error, 0, "Out of range index"); + return NULL; + } + + unsigned char byte = Object_ToInt(val, error); + + if(error->occurred == 1) + return 0; + + buffer->body[idx] = byte; + return 1; +} + +static int count(Object *self) +{ + BufferObject *buffer = (BufferObject*) self; + + return buffer->size; +} + +static void print(Object *self, FILE *fp) +{ + BufferObject *buffer = (BufferObject*) self; + + fprintf(fp, "["); + + for(int i = 0; i < buffer->size; i += 1) + { + unsigned char byte, low, high; + + byte = buffer->body[i]; + low = byte & 0xf; + high = byte >> 4; + + assert(low < 16); + assert(high < 16); + + char c1, c2; + + c1 = low < 10 ? low + '0' : low - 10 + 'A'; + c2 = high < 10 ? high + '0' : high - 10 + 'A'; + + fprintf(fp, "%c%c", c1, c2); + + if(i+1 < buffer->size) + fprintf(fp, ", "); + } + fprintf(fp, "]"); +} \ No newline at end of file diff --git a/src/objects/objects.h b/src/objects/objects.h index a2b8c19..29b490e 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -86,6 +86,7 @@ Object* Object_Prev (Object *iter, Heap *heap, Error *err); Object* Object_NewMap(int num, Heap *heap, Error *error); Object* Object_NewList(int capacity, Heap *heap, Error *error); Object* Object_NewNone(Heap *heap, Error *error); +Object* Object_NewBuffer(int size, Heap *heap, Error *error); Object* Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error); Object* Object_FromInt (long long int val, Heap *heap, Error *error);