From 8deec027d1fa1e8bcccbe4f4fe3723bd627dd6ec Mon Sep 17 00:00:00 2001 From: cozis Date: Thu, 10 Mar 2022 19:00:30 +0100 Subject: [PATCH] added statis map object and used it to implement builtins. Also, new objects File and Directory --- build.sh | 58 ++-- docs/language.md | 3 +- src/builtins/basic.c | 146 ++++++++ src/builtins/basic.h | 2 + src/builtins/file.c | 278 +++++++++++++++ src/builtins/file.h | 2 + src/builtins/math.c | 94 +++++ src/builtins/math.h | 2 + src/noja.c | 5 +- src/o_builtins.c | 256 -------------- src/o_builtins.h | 3 - src/o_net_builtins.c | 755 ----------------------------------------- src/o_staticmap.c | 94 +++++ src/o_staticmap.h | 37 ++ src/objects/o_buffer.c | 5 + src/objects/o_dir.c | 53 +++ src/objects/o_file.c | 53 +++ src/objects/o_none.c | 5 + src/objects/objects.h | 18 +- 19 files changed, 824 insertions(+), 1045 deletions(-) create mode 100644 src/builtins/basic.c create mode 100644 src/builtins/basic.h create mode 100644 src/builtins/file.c create mode 100644 src/builtins/file.h create mode 100644 src/builtins/math.c create mode 100644 src/builtins/math.h delete mode 100644 src/o_builtins.c delete mode 100644 src/o_builtins.h delete mode 100644 src/o_net_builtins.c create mode 100644 src/o_staticmap.c create mode 100644 src/o_staticmap.h create mode 100644 src/objects/o_dir.c create mode 100644 src/objects/o_file.c diff --git a/build.sh b/build.sh index 0de9ebf..c4f2226 100755 --- a/build.sh +++ b/build.sh @@ -20,6 +20,8 @@ gcc -c src/objects/o_map.c -o temp/objects/o_map.o $FLAGS gcc -c src/objects/o_list.c -o temp/objects/o_list.o $FLAGS 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_file.c -o temp/objects/o_file.o $FLAGS +gcc -c src/objects/o_dir.c -o temp/objects/o_dir.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 @@ -40,8 +42,12 @@ gcc -c src/runtime/runtime.c -o temp/runtime/runtime.o $FLAGS gcc -c src/runtime/o_nfunc.c -o temp/runtime/o_nfunc.o $FLAGS gcc -c src/runtime/o_func.c -o temp/runtime/o_func.o $FLAGS -gcc -c src/o_builtins.c -o temp/o_builtins.o $FLAGS -gcc -c src/o_net_builtins.c -o temp/o_net_builtins.o $FLAGS +mkdir temp/builtins +gcc -c src/builtins/basic.c -o temp/builtins/basic.o $FLAGS +gcc -c src/builtins/file.c -o temp/builtins/file.o $FLAGS +gcc -c src/builtins/math.c -o temp/builtins/math.o $FLAGS + +gcc -c src/o_staticmap.c -o temp/o_staticmap.o $FLAGS rm -rf build mkdir build @@ -68,27 +74,31 @@ ar rcs build/libnoja-runtime.a \ build/libnoja-compile.a \ build/libnoja-objects.a -gcc src/main.c \ - src/noja.c \ - temp/o_builtins.o \ - temp/o_net_builtins.o \ - temp/utils/hash.o \ - temp/utils/stack.o \ - temp/utils/source.o \ - temp/utils/promise.o \ - temp/utils/bucketlist.o \ - temp/objects/o_map.o \ - 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 \ - temp/runtime/runtime_error.o \ - temp/runtime/o_nfunc.o \ - temp/runtime/o_func.o \ - temp/common/executable.o \ - -o build/noja $FLAGS -Lbuild/ -lnoja-compile -lnoja-objects -lxjson +gcc src/main.c \ + src/noja.c \ + temp/o_staticmap.o \ + temp/utils/hash.o \ + temp/utils/stack.o \ + temp/utils/source.o \ + temp/utils/promise.o \ + temp/utils/bucketlist.o \ + temp/objects/o_map.o \ + temp/objects/o_none.o \ + temp/objects/o_list.o \ + temp/objects/o_file.o \ + temp/objects/o_dir.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 \ + temp/runtime/runtime_error.o \ + temp/runtime/o_nfunc.o \ + temp/runtime/o_func.o \ + temp/builtins/basic.o \ + temp/builtins/file.o \ + temp/builtins/math.o \ + temp/common/executable.o \ + -o build/noja $FLAGS -Lbuild/ -lnoja-compile -lnoja-objects -lxjson -lm rm -rf temp \ No newline at end of file diff --git a/docs/language.md b/docs/language.md index bdd7a02..4f21fdb 100644 --- a/docs/language.md +++ b/docs/language.md @@ -56,8 +56,9 @@ none; # The none value: there are also other types of values (like functions and buffers) but they'll be covered later. -These type of values, in conjuctions with the operators that are made available by the language, can be used to build arbitrarily complex expressions. The basic arithmetic operators are available: +These type of values, in conjuction with the operators that are made available by the language, can be used to build arbitrarily complex expressions. +The basic arithmetic operators are available: ```py 1 + 1; # 2 1 - 2; # -1 diff --git a/src/builtins/basic.c b/src/builtins/basic.c new file mode 100644 index 0000000..9b0edbb --- /dev/null +++ b/src/builtins/basic.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include "basic.h" +#include "file.h" +#include "math.h" + +static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + for(int i = 0; i < (int) argc; i += 1) + Object_Print(argv[i], stdout); + + return Object_NewNone(Runtime_GetHeap(runtime), error); +} + +static Object *bin_type(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + (void) runtime; + (void) error; + return (Object*) argv[0]->type; +} + +static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + int n = Object_Count(argv[0], error); + + if(error->occurred) + return NULL; + + return Object_FromInt(n, Runtime_GetHeap(runtime), error); +} + +static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + for(unsigned int i = 0; i < argc; i += 1) + if(!Object_ToBool(argv[i], error)) + { + if(!error->occurred) + Error_Report(error, 0, "Assertion failed"); + return NULL; + } + return Object_NewNone(Runtime_GetHeap(runtime), error); +} + +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; +} + +static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + long long int size = Object_ToInt(argv[0], error); + + if(error->occurred == 1) + return NULL; + + return Object_NewBuffer(size, Runtime_GetHeap(runtime), error); +} + +static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 3); + + long long int offset = Object_ToInt(argv[1], error); + if(error->occurred == 1) return NULL; + + long long int length = Object_ToInt(argv[2], error); + if(error->occurred == 1) return NULL; + + return Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error); +} + +const StaticMapSlot bins_basic[] = { + { "math", SM_SMAP, .as_smap = bins_math, }, + { "file", SM_SMAP, .as_smap = bins_file, }, +// { "net", SM_SMAP, .as_smap = bins_net, }, + + { "newBuffer", SM_FUNCT, .as_funct = bin_newBuffer, .argc = 1 }, + { "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 }, + + { "strcat", SM_FUNCT, .as_funct = bin_strcat }, + + { "type", SM_FUNCT, .as_funct = bin_type, .argc = 1 }, + { "print", SM_FUNCT, .as_funct = bin_print, .argc = -1 }, + { "count", SM_FUNCT, .as_funct = bin_count, .argc = 1 }, + { "assert", SM_FUNCT, .as_funct = bin_assert, .argc = -1 }, + { NULL, SM_END, {}, {} }, +}; \ No newline at end of file diff --git a/src/builtins/basic.h b/src/builtins/basic.h new file mode 100644 index 0000000..47693aa --- /dev/null +++ b/src/builtins/basic.h @@ -0,0 +1,2 @@ +#include "../o_staticmap.h" +extern const StaticMapSlot bins_basic[]; \ No newline at end of file diff --git a/src/builtins/file.c b/src/builtins/file.c new file mode 100644 index 0000000..f68e6d2 --- /dev/null +++ b/src/builtins/file.c @@ -0,0 +1,278 @@ +#include +#include +#include "file.h" + +enum { + MD_READ = 0, + MD_WRITE = 1, + MD_APPEND = 2, +}; + +static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 2); + + if(!Object_IsString(argv[0])) + { + Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + if(!Object_IsInt(argv[1])) + { + Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + Heap *heap = Runtime_GetHeap(runtime); + + const char *path = Object_ToString(argv[0], NULL, heap, error); + + if(error->occurred) + return NULL; + + int mode = Object_ToInt(argv[1], error); + + if(error->occurred) + return NULL; + + FILE *fp; + { + const char *mode2; + + switch(mode) + { + case MD_READ: + mode2 = "r"; + break; + + case MD_READ | MD_WRITE: + mode2 = "w+"; + break; + + case MD_READ | MD_APPEND: + case MD_READ | MD_WRITE | MD_APPEND: + mode2 = "a"; + break; + + default: + assert(0); + break; + } + + fp = fopen(path, mode2); + + if(fp == NULL) + return Object_NewNone(heap, error); + } + + return Object_FromStream(fp, heap, error); +} + +static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 3); + + // Arg 0: file + // Arg 1: buffer + // Arg 2: count + + if(!Object_IsFile(argv[0])) + { + Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + if(!Object_IsBuffer(argv[1])) + { + Error_Report(error, 0, "Expected first argument to be a buffer, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + Heap *heap = Runtime_GetHeap(runtime); + + void *buff_addr; + int buff_size; + + buff_addr = Object_GetBufferAddrAndSize(argv[1], &buff_size, error); + + int read_size; + + if(Object_IsNone(argv[2])) + { + read_size = buff_size; + } + else if(Object_IsInt(argv[2])) + { + long long int temp = Object_ToInt(argv[2], error); + + if(error->occurred) + return NULL; + + read_size = temp; // TODO: Handle potential overflow. + + if(read_size > buff_size) + read_size = buff_size; + } + else + { + Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + FILE *fp = Object_ToStream(argv[0], error); + + if(fp == NULL) + return NULL; + + size_t n = fread(buff_addr, 1, read_size, fp); + + return Object_FromInt(n, heap, error); +} + +static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 3); + + // Arg 0: file + // Arg 1: buffer + // Arg 2: count + + if(!Object_IsFile(argv[0])) + { + Error_Report(error, 0, "Expected first argument to be a file, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + if(!Object_IsBuffer(argv[1])) + { + Error_Report(error, 0, "Expected first argument to be a buffer, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + Heap *heap = Runtime_GetHeap(runtime); + + void *buff_addr; + int buff_size; + + buff_addr = Object_GetBufferAddrAndSize(argv[1], &buff_size, error); + + int write_size; + + if(Object_IsNone(argv[2])) + { + write_size = buff_size; + } + else if(Object_IsInt(argv[2])) + { + long long int temp = Object_ToInt(argv[2], error); + + if(error->occurred) + return NULL; + + write_size = temp; // TODO: Handle potential overflow. + + if(write_size > buff_size) + write_size = buff_size; + } + else + { + Error_Report(error, 0, "Expected third argument to be an int or none, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + FILE *fp = Object_ToStream(argv[0], error); + + if(fp == NULL) + return NULL; + + size_t n = fwrite(buff_addr, 1, write_size, fp); + + return Object_FromInt(n, heap, error); +} + +static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + // Arg 0: path + + if(!Object_IsString(argv[0])) + { + Error_Report(error, 0, "Expected first argument to be a string, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + Heap *heap = Runtime_GetHeap(runtime); + + const char *path = Object_ToString(argv[0], NULL, heap, error); + + if(error->occurred) + return NULL; + + DIR *dir = opendir(path); + + if(dir == NULL) + return Object_NewNone(heap, error); + + Object *dob = Object_FromDIR(dir, heap, error); + + if(error->occurred) + { + (void) closedir(dir); + return NULL; + } + + return dob; +} + +static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + // Arg 0: path + + if(!Object_IsDir(argv[0])) + { + Error_Report(error, 0, "Expected first argument to be a directory, but it's a %s", Object_GetName(argv[0])); + return NULL; + } + + DIR *dir = Object_ToDIR(argv[0], error); + + if(error->occurred) + return NULL; + + assert(dir != NULL); + + Heap *heap = Runtime_GetHeap(runtime); + + errno = 0; + + struct dirent *ent = readdir(dir); + + if(ent == NULL) + { + if(errno == 0) + // Nothing left to read. + return Object_NewNone(heap, error); + + // An error occurred. + Error_Report(error, 1, "Failed to read directory item"); + return NULL; + } + + return Object_FromString(ent->d_name, -1, heap, error); +} + +const StaticMapSlot bins_file[] = { + { "READ", SM_INT, .as_int = MD_READ, }, + { "WRITE", SM_INT, .as_int = MD_WRITE, }, + { "APPEND", SM_INT, .as_int = MD_APPEND, }, + { "openFile", SM_FUNCT, .as_funct = bin_openFile, .argc = 2, }, + { "openDir", SM_FUNCT, .as_funct = bin_openDir, .argc = 1, }, + { "nextDirItem", SM_FUNCT, .as_funct = bin_nextDirItem, .argc = 1, }, + { "read", SM_FUNCT, .as_funct = bin_read, .argc = 2, }, + { "write", SM_FUNCT, .as_funct = bin_write, .argc = 3, }, + { NULL, SM_END, {}, {} }, +}; \ No newline at end of file diff --git a/src/builtins/file.h b/src/builtins/file.h new file mode 100644 index 0000000..b4b522f --- /dev/null +++ b/src/builtins/file.h @@ -0,0 +1,2 @@ +#include "../o_staticmap.h" +extern const StaticMapSlot bins_file[]; \ No newline at end of file diff --git a/src/builtins/math.c b/src/builtins/math.c new file mode 100644 index 0000000..6cac222 --- /dev/null +++ b/src/builtins/math.c @@ -0,0 +1,94 @@ +#include +#include +#include "math.h" + +#define WRAP_FUNC(name) \ + static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \ + { \ + assert(argc == 1); \ + \ + if(Object_IsFloat(argv[0])) \ + { \ + double v = Object_ToFloat(argv[0], error); \ + \ + if(error->occurred) \ + return NULL; \ + \ + return Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \ + } \ + else \ + { \ + Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\ + return NULL; \ + } \ + } + +#define WRAP_FUNC_2(name) \ + static Object *bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Error *error) \ + { \ + assert(argc == 2); \ + \ + if(!Object_IsFloat(argv[0])) \ + { \ + Error_Report(error, 0, "Expected first argument to be a float, but it's a %s", Object_GetName(argv[0]));\ + return NULL; \ + } \ + \ + if(!Object_IsFloat(argv[1])) \ + { \ + Error_Report(error, 0, "Expected second argument to be a float, but it's a %s", Object_GetName(argv[1]));\ + return NULL; \ + } \ + \ + double v1 = Object_ToFloat(argv[0], error); \ + \ + if(error->occurred) \ + return NULL; \ + \ + double v2 = Object_ToFloat(argv[1], error); \ + \ + if(error->occurred) \ + return NULL; \ + \ + return Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \ + } + +WRAP_FUNC(ceil) +WRAP_FUNC(floor) +WRAP_FUNC(sin) +WRAP_FUNC(cos) +WRAP_FUNC(tan) +WRAP_FUNC(asin) +WRAP_FUNC(acos) +WRAP_FUNC(atan) +WRAP_FUNC(exp) +WRAP_FUNC(log) +WRAP_FUNC(log10) +WRAP_FUNC(sqrt) +WRAP_FUNC_2(atan2) +WRAP_FUNC_2(pow) + +const StaticMapSlot bins_math[] = { + { "PI", SM_FLOAT, .as_float = M_PI }, + { "E", SM_FLOAT, .as_float = M_E }, + + { "floor", SM_FUNCT, .as_funct = bin_floor, .argc = 1, }, + { "ceil", SM_FUNCT, .as_funct = bin_ceil, .argc = 1, }, + + { "cos", SM_FUNCT, .as_funct = bin_cos, .argc = 1, }, + { "sin", SM_FUNCT, .as_funct = bin_sin, .argc = 1, }, + { "tan", SM_FUNCT, .as_funct = bin_tan, .argc = 1, }, + + { "acos", SM_FUNCT, .as_funct = bin_acos, .argc = 1, }, + { "asin", SM_FUNCT, .as_funct = bin_asin, .argc = 1, }, + { "atan", SM_FUNCT, .as_funct = bin_atan, .argc = 1, }, + { "atan2", SM_FUNCT, .as_funct = bin_atan2, .argc = 2, }, + + { "exp", SM_FUNCT, .as_funct = bin_exp, .argc = 1, }, + { "log", SM_FUNCT, .as_funct = bin_log, .argc = 1, }, + { "log10", SM_FUNCT, .as_funct = bin_log10, .argc = 1, }, + + { "pow", SM_FUNCT, .as_funct = bin_pow, .argc = 1, }, + { "sqrt", SM_FUNCT, .as_funct = bin_sqrt, .argc = 1, }, + { NULL, SM_END, {}, {} }, +}; \ No newline at end of file diff --git a/src/builtins/math.h b/src/builtins/math.h new file mode 100644 index 0000000..530cf13 --- /dev/null +++ b/src/builtins/math.h @@ -0,0 +1,2 @@ +#include "../o_staticmap.h" +extern const StaticMapSlot bins_math[]; \ No newline at end of file diff --git a/src/noja.c b/src/noja.c index 9bf8d4b..50c63e2 100644 --- a/src/noja.c +++ b/src/noja.c @@ -2,12 +2,13 @@ #include #include #include -#include "o_builtins.h" +#include "o_staticmap.h" #include "compiler/parse.h" #include "compiler/serialize.h" #include "compiler/compile.h" #include "runtime/runtime.h" #include "runtime/runtime_error.h" +#include "builtins/basic.h" static const char usage[] = "Usage:\n" @@ -207,7 +208,7 @@ static _Bool interpret(Source *src) RuntimeError error; RuntimeError_Init(&error, runt); // Here we specify the runtime to snapshot in case of failure. - Object *bins = Object_NewBuiltinsMap(runt, Runtime_GetHeap(runt), (Error*) &error); + Object *bins = Object_NewStaticMap(bins_basic, runt, (Error*) &error); if(bins == NULL) { diff --git a/src/o_builtins.c b/src/o_builtins.c deleted file mode 100644 index d5966d1..0000000 --- a/src/o_builtins.c +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include "runtime/runtime.h" -#include "utils/defs.h" -#include "o_builtins.h" - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err); - -static Object *bin_type (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_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); -static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error); - -typedef struct { - Object base; - Runtime *runtime; -} BuiltinsMapOjbect; - -static TypeObject t_builtins_map = { - .base = (Object) { .type = &t_type, .flags = Object_STATIC }, - .name = "builtins map", - .size = sizeof(BuiltinsMapOjbect), - .select = select_, -}; - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err) -{ - BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) self; - - if(!Object_IsString(key)) - { - Error_Report(err, 0, "Non string key"); - return NULL; - } - - int n; - const char *s; - - s = Object_ToString(key, &n, heap, err); - - if(s == NULL) - return NULL; - - #define PAIR(p, q) \ - (((uint64_t) (p) << 32) | (uint32_t) (q)) - - switch(PAIR(n, s[0])) - { - case PAIR(4, 't'): - { - if(!strcmp(s, "type")) - return Object_FromNativeFunction(bm->runtime, bin_type, 1, heap, err); - return NULL; - } - - case PAIR(sizeof("count")-1, 'c'): - { - if(!strcmp(s, "count")) - return Object_FromNativeFunction(bm->runtime, bin_count, 1, heap, err); - return NULL; - } - - case PAIR(sizeof("print")-1, 'p'): - { - if(!strcmp(s, "print")) - return Object_FromNativeFunction(bm->runtime, bin_print, -1, heap, err); - return NULL; - } - - case PAIR(sizeof("assert")-1, 'a'): - { - if(!strcmp(s, "assert")) - 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; - } - - case PAIR(sizeof("sliceBuffer")-1, 's'): - { - if(!strcmp(s, "sliceBuffer")) - return Object_FromNativeFunction(bm->runtime, bin_sliceBuffer, 3, heap, err); - - return NULL; - } - - case PAIR(sizeof("net")-1, 'n'): - { - if(!strcmp(s, "net")) - return Object_NewNetworkBuiltinsMap(bm->runtime, heap, 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. - return NULL; -} - -Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err) -{ - BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err); - - if(bm == NULL) - return NULL; - - bm->runtime = runtime; - - return (Object*) bm; -} - -static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - for(int i = 0; i < (int) argc; i += 1) - Object_Print(argv[i], stdout); - - return Object_NewNone(Runtime_GetHeap(runtime), error); -} - -static Object *bin_type(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - (void) runtime; - (void) error; - return (Object*) argv[0]->type; -} - -static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - int n = Object_Count(argv[0], error); - - if(error->occurred) - return NULL; - - return Object_FromInt(n, Runtime_GetHeap(runtime), error); -} - -static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - if(Object_ToBool(argv[0], error)) - { - return Object_NewNone(Runtime_GetHeap(runtime), error); - } - else - { - if(!error->occurred) - Error_Report(error, 0, "Assertion failed"); - 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; -} - -static Object *bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - long long int size = Object_ToInt(argv[0], error); - - if(error->occurred == 1) - return NULL; - - return Object_NewBuffer(size, Runtime_GetHeap(runtime), error); -} - -static Object *bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 3); - - long long int offset = Object_ToInt(argv[1], error); - if(error->occurred == 1) return NULL; - - long long int length = Object_ToInt(argv[2], error); - if(error->occurred == 1) return NULL; - - return Object_SliceBuffer(argv[0], offset, length, Runtime_GetHeap(runtime), error); -} \ No newline at end of file diff --git a/src/o_builtins.h b/src/o_builtins.h deleted file mode 100644 index f5b02e6..0000000 --- a/src/o_builtins.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "runtime/runtime.h" -Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err); -Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err); \ No newline at end of file diff --git a/src/o_net_builtins.c b/src/o_net_builtins.c deleted file mode 100644 index c80b2da..0000000 --- a/src/o_net_builtins.c +++ /dev/null @@ -1,755 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "runtime/runtime.h" -#include "utils/defs.h" - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err); - -static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_inet_ntoa(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_send(Runtime *runtime, Object **argv, unsigned int argc, Error *error); -static Object *bin_recv(Runtime *runtime, Object **argv, unsigned int argc, Error *error); - - -typedef struct { - Object base; - Runtime *runtime; -} NetworkBuiltinsMapOjbect; - -static TypeObject t_builtins_map = { - .base = (Object) { .type = &t_type, .flags = Object_STATIC }, - .name = "network builtins map", - .size = sizeof(NetworkBuiltinsMapOjbect), - .select = select_, -}; - -static Object *select_(Object *self, Object *key, Heap *heap, Error *err) -{ - NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) self; - - if(!Object_IsString(key)) - { - Error_Report(err, 0, "Non string key"); - return NULL; - } - - int n; - const char *s; - - s = Object_ToString(key, &n, heap, err); - - if(s == NULL) - return NULL; - - #define PAIR(p, q) \ - (((uint64_t) (p) << 32) | (uint32_t) (q)) - - switch(PAIR(n, s[0])) - { - case PAIR(4, 's'): - { - if(!strcmp(s, "send")) - return Object_FromNativeFunction(bm->runtime, bin_send, 3, heap, err); - - return NULL; - } - - case PAIR(4, 'r'): - { - if(!strcmp(s, "recv")) - return Object_FromNativeFunction(bm->runtime, bin_recv, 3, heap, err); - - return NULL; - } - - case PAIR(10, 'I'): - { - if(!strcmp(s, "INADDR_ANY")) - return Object_FromInt(INADDR_ANY, heap, err); - - return NULL; - } - - case PAIR(6, 'a'): - { - if(!strcmp(s, "accept")) - return Object_FromNativeFunction(bm->runtime, bin_accept, 2, heap, err); - - return NULL; - } - - case PAIR(4, 'b'): - { - if(!strcmp(s, "bind")) - return Object_FromNativeFunction(bm->runtime, bin_bind, 2, heap, err); - - return NULL; - } - - case PAIR(6, 'l'): - { - if(!strcmp(s, "listen")) - return Object_FromNativeFunction(bm->runtime, bin_listen, 2, heap, err); - - return NULL; - } - - case PAIR(5, 'n'): - { - if(!strcmp(s, "ntohl")) - return Object_FromNativeFunction(bm->runtime, bin_ntohl, 1, heap, err); - - if(!strcmp(s, "ntohs")) - return Object_FromNativeFunction(bm->runtime, bin_ntohs, 1, heap, err); - - return NULL; - } - - case PAIR(5, 'h'): - { - if(!strcmp(s, "htonl")) - return Object_FromNativeFunction(bm->runtime, bin_htonl, 1, heap, err); - - if(!strcmp(s, "htons")) - return Object_FromNativeFunction(bm->runtime, bin_htons, 1, heap, err); - - return NULL; - } - - case PAIR(9, 'i'): - { - if(!strcmp(s, "inet_aton")) - return Object_FromNativeFunction(bm->runtime, bin_inet_aton, 2, heap, err); - - if(!strcmp(s, "inet_ntoa")) - return Object_FromNativeFunction(bm->runtime, bin_inet_ntoa, 1, heap, err); - - return NULL; - } - - case PAIR(6, 's'): - { - if(!strcmp(s, "socket")) - return Object_FromNativeFunction(bm->runtime, bin_socket, 3, heap, err); - return NULL; - } - - case PAIR(7, 'c'): - { - if(!strcmp(s, "connect")) - return Object_FromNativeFunction(bm->runtime, bin_connect, 2, heap, err); - return NULL; - } - - case PAIR(8, 'S'): - { - if(!strcmp(s, "SOCK_RAW")) - return Object_FromInt(SOCK_RAW, heap, err); - - if(!strcmp(s, "SOCK_RDM")) - return Object_FromInt(SOCK_RDM, heap, err); - - return NULL; - } - - case PAIR(10, 'S'): - { - if(!strcmp(s, "SOCK_DGRAM")) - return Object_FromInt(SOCK_DGRAM, heap, err); - - return NULL; - } - - case PAIR(11, 'S'): - { - if(!strcmp(s, "SOCK_STREAM")) - return Object_FromInt(SOCK_STREAM, heap, err); - - if(!strcmp(s, "SOCK_PACKET")) - return Object_FromInt(SOCK_PACKET, heap, err); - - return NULL; - } - - case PAIR(12, 'S'): - { - if(!strcmp(s, "SOCK_CLOEXEC")) - return Object_FromInt(SOCK_CLOEXEC, heap, err); - - return NULL; - } - - case PAIR(13, 'S'): - { - if(!strcmp(s, "SOCK_NONBLOCK")) - return Object_FromInt(SOCK_NONBLOCK, heap, err); - - return NULL; - } - - case PAIR(14, 'S'): - { - if(!strcmp(s, "SOCK_SEQPACKET")) - return Object_FromInt(SOCK_SEQPACKET, heap, err); - - return NULL; - } - - case PAIR(5, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "IB")) - return Object_FromInt(AF_IB, heap, err); - } - return NULL; - } - - case PAIR(6, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "IPX")) - return Object_FromInt(AF_IPX, heap, err); - - if(!strcmp(s+3, "X25")) - return Object_FromInt(AF_X25, heap, err); - - if(!strcmp(s+3, "KEY")) - return Object_FromInt(AF_KEY, heap, err); - - if(!strcmp(s+3, "RDS")) - return Object_FromInt(AF_RDS, heap, err); - - if(!strcmp(s+3, "LLC")) - return Object_FromInt(AF_LLC, heap, err); - - if(!strcmp(s+3, "CAN")) - return Object_FromInt(AF_CAN, heap, err); - - if(!strcmp(s+3, "ALG")) - return Object_FromInt(AF_ALG, heap, err); - - if(!strcmp(s+3, "KCM")) - return Object_FromInt(AF_KCM, heap, err); - - if(!strcmp(s+3, "XDP")) - return Object_FromInt(AF_XDP, heap, err); - } - return NULL; - } - - case PAIR(7, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "UNIX")) - return Object_FromInt(AF_UNIX, heap, err); - - if(!strcmp(s+3, "INET")) - return Object_FromInt(AF_INET, heap, err); - - if(!strcmp(s+3, "AX25")) - return Object_FromInt(AF_AX25, heap, err); - - if(!strcmp(s+3, "MPLS")) - return Object_FromInt(AF_MPLS, heap, err); - - if(!strcmp(s+3, "TIPC")) - return Object_FromInt(AF_TIPC, heap, err); - } - return NULL; - } - - case PAIR(8, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "LOCAL")) - return Object_FromInt(AF_LOCAL, heap, err); - - if(!strcmp(s+3, "INET6")) - return Object_FromInt(AF_INET6, heap, err); - - if(!strcmp(s+3, "PPPOX")) - return Object_FromInt(AF_PPPOX, heap, err); - - if(!strcmp(s+3, "VSOCK")) - return Object_FromInt(AF_VSOCK, heap, err); - } - return NULL; - } - - case PAIR(9, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "DECnet")) - return Object_FromInt(AF_DECnet, heap, err); - - if(!strcmp(s+3, "PACKET")) - return Object_FromInt(AF_PACKET, heap, err); - } - return NULL; - } - - case PAIR(10, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "NETLINK")) - return Object_FromInt(AF_NETLINK, heap, err); - } - return NULL; - } - - case PAIR(12, 'A'): - { - if(s[1] == 'F' && s[2] == '_') - { - if(!strcmp(s+3, "BLUETOOTH")) - return Object_FromInt(AF_BLUETOOTH, heap, err); - - if(!strcmp(s+3, "APPLETALK")) - return Object_FromInt(AF_APPLETALK, heap, err); - } - return NULL; - } - } - - // Not found. - return NULL; -} - -Object *Object_NewNetworkBuiltinsMap(Runtime *runtime, Heap *heap, Error *err) -{ - NetworkBuiltinsMapOjbect *bm = (NetworkBuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err); - - if(bm == NULL) - return NULL; - - bm->runtime = runtime; - - return (Object*) bm; -} - -static Object *bin_socket(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 3); - - int domain, type, protocol; - - domain = Object_ToInt(argv[0], error); - if(error->occurred == 1) return NULL; - - type = Object_ToInt(argv[1], error); - if(error->occurred == 1) return NULL; - - protocol = Object_ToInt(argv[2], error); - if(error->occurred == 1) return NULL; - - int fd = socket(domain, type, protocol); - - return Object_FromInt(fd, Runtime_GetHeap(runtime), error); -} - - -static _Bool get_in_addr_from_map(Object *map, struct in_addr *addr, Heap *heap, Error *error) -{ - Object *o_key = Object_FromString("s_addr", -1, heap, error); - if(o_key == NULL) return 0; - - Object *o_s_addr = Object_Select(map, o_key, heap, error); - if(o_s_addr == NULL) - { - if(error->occurred == 0) - Error_Report(error, 0, "Missing the \"s_addr\" key"); - return 0; - } - - long long int s_addr = Object_ToInt(o_s_addr, error); - if(error->occurred) return 0; - - if(s_addr < 0 || s_addr >= (long long int) ULONG_MAX) - { - Error_Report(error, 0, "s_addr must be in range [0, %lu]", ULONG_MAX); - return 0; - } - - if(addr) - addr->s_addr = s_addr; - - return 1; -} - -static _Bool get_sockaddr_in_from_map(Object *map, struct sockaddr_in *addr, Heap *heap, Error *error) -{ - Object *o_key = Object_FromString("sin_family", -1, heap, error); - if(o_key == NULL) return 0; - - Object *o_sin_family = Object_Select(map, o_key, heap, error); - if(o_sin_family == NULL) - { - if(error->occurred == 0) - Error_Report(error, 0, "Argument 2 is missing the \"sin_family\" key"); - return 0; - } - - long long int sin_family = Object_ToInt(o_sin_family, error); - if(error->occurred) return 0; - - if(sin_family < 0 || sin_family >= 65536) - { - Error_Report(error, 0, "sin_family must be in range [0, 65535]"); - return 0; - } - - o_key = Object_FromString("sin_port", -1, heap, error); - if(o_key == NULL) return 0; - - Object *o_sin_port = Object_Select(map, o_key, heap, error); - if(o_sin_port == NULL) - { - if(error->occurred == 0) - Error_Report(error, 0, "Argument 2 is missing the \"sin_port\" key"); - return 0; - } - - long long int sin_port = Object_ToInt(o_sin_port, error); - if(error->occurred) return 0; - - if(sin_port < 0 || sin_port >= 65536) - { - Error_Report(error, 0, "sin_port must be in range [0, 65535]"); - return 0; - } - - o_key = Object_FromString("sin_addr", -1, heap, error); - if(o_key == NULL) return 0; - - Object *o_sin_addr = Object_Select(map, o_key, heap, error); - if(o_sin_addr == NULL) - { - if(error->occurred == 0) - Error_Report(error, 0, "Argument 2 is missing the \"sin_addr\" key"); - return 0; - } - - struct in_addr sin_addr; - - if(!get_in_addr_from_map(o_sin_addr, &sin_addr, heap, error)) - return 0; - - if(addr) - { - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = sin_family; - addr->sin_port = sin_port; - addr->sin_addr = sin_addr; - } - return 1; -} - -static Object *bin_connect(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 2); - - Heap *heap = Runtime_GetHeap(runtime); - - int sockfd; - struct sockaddr_in addr; - - sockfd = Object_ToInt(argv[0], error); - if(error->occurred == 1) return NULL; - - if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error)) - return NULL; - - int r = connect(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)); - - return Object_FromInt(r, Runtime_GetHeap(runtime), error); -} - -static Object *bin_inet_aton(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 2); - - Heap *heap = Runtime_GetHeap(runtime); - - const char *s = Object_ToString(argv[0], NULL, heap, error); - if(s == NULL) return NULL; - - // Note that the string must be zero-terminated. - - struct in_addr addr; - - int r = inet_aton(s, &addr); - - if(r != 0) - { - // inet_aton succeded. - - Object *o_key = Object_FromString("s_addr", -1, heap, error); - if(o_key == NULL) return NULL; - - Object *o_val = Object_FromInt(addr.s_addr, heap, error); - if(o_val == NULL) return NULL; - - if(!Object_Insert(argv[1], o_key, o_val, heap, error)) - return NULL; - } - - return Object_FromInt(r, heap, error); -} - -static Object *bin_inet_ntoa(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - Heap *heap = Runtime_GetHeap(runtime); - - struct in_addr in_addr; - - if(!get_in_addr_from_map(argv[0], &in_addr, heap, error)) - return NULL; - - const char *addr = inet_ntoa(in_addr); - assert(addr != NULL); - - return Object_FromString(addr, -1, heap, error); -} - -static Object *bin_htonl(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - Heap *heap = Runtime_GetHeap(runtime); - - - uint32_t r, p; - - p = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - r = htonl(p); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_ntohl(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - Heap *heap = Runtime_GetHeap(runtime); - - - uint32_t r, p; - - p = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - r = ntohl(p); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_ntohs(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - Heap *heap = Runtime_GetHeap(runtime); - - int p = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - if(p < 0 || p > 65535) - { - Error_Report(error, 0, "Argument is not in range [0, 65535]"); - return NULL; - } - - uint16_t r = ntohs(p); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_htons(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - Heap *heap = Runtime_GetHeap(runtime); - - int p = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - if(p < 0 || p > 65535) - { - Error_Report(error, 0, "Argument is not in range [0, 65535]"); - return NULL; - } - - uint16_t r = htons(p); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_bind(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 2); - - Heap *heap = Runtime_GetHeap(runtime); - - int sockfd; - struct sockaddr_in addr; - - sockfd = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - if(!get_sockaddr_in_from_map(argv[1], &addr, heap, error)) - return 0; - - int r = bind(sockfd, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_listen(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 2); - - Heap *heap = Runtime_GetHeap(runtime); - - int sockfd, backlog; - - sockfd = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - backlog = Object_ToInt(argv[1], error); - if(error->occurred) return NULL; - - int r = listen(sockfd, backlog); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_accept(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 2); - - Heap *heap = Runtime_GetHeap(runtime); - - long long int sockfd = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - struct sockaddr_in addr; - socklen_t len = sizeof(addr); - - int r = accept(sockfd, (struct sockaddr*) &addr, &len); - - if(r >= 0) { - - // accept succeded. - - Object *o_key, - *o_sin_family, - *o_sin_addr, - *o_sin_port, - *o_s_addr; - - o_sin_family = Object_FromInt(addr.sin_family, heap, error); - if(error->occurred) return NULL; - - o_sin_port = Object_FromInt(addr.sin_port, heap, error); - if(error->occurred) return NULL; - - o_sin_addr = Object_NewMap(1, heap, error); - if(error->occurred) return NULL; - - o_s_addr = Object_FromInt(addr.sin_addr.s_addr, heap, error); - if(error->occurred) return NULL; - - o_key = Object_FromString("s_addr", -1, heap, error); - if(error->occurred) return NULL; - - if(!Object_Insert(o_sin_addr, o_key, o_s_addr, heap, error)) - return NULL; - - o_key = Object_FromString("sin_family", -1, heap, error); - if(error->occurred) return NULL; - - if(!Object_Insert(argv[1], o_key, o_sin_family, heap, error)) - return NULL; - - o_key = Object_FromString("sin_port", -1, heap, error); - if(error->occurred) return NULL; - - if(!Object_Insert(argv[1], o_key, o_sin_port, heap, error)) - return NULL; - - o_key = Object_FromString("sin_addr", -1, heap, error); - if(error->occurred) return NULL; - - if(!Object_Insert(argv[1], o_key, o_sin_addr, heap, error)) - return NULL; - } - - return Object_FromInt(r, heap, error); -} - -static Object *bin_send(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 3); - - Heap *heap = Runtime_GetHeap(runtime); - - int sockfd = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - int size; - void *addr = Object_GetBufferAddrAndSize(argv[1], &size, error); - if(addr == NULL) return NULL; - - int flags = Object_ToInt(argv[2], error); - if(error->occurred) return NULL; - - ssize_t r = send(sockfd, addr, size, flags); - - return Object_FromInt(r, heap, error); -} - -static Object *bin_recv(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 3); - - Heap *heap = Runtime_GetHeap(runtime); - - int sockfd = Object_ToInt(argv[0], error); - if(error->occurred) return NULL; - - int size; - void *addr = Object_GetBufferAddrAndSize(argv[1], &size, error); - if(addr == NULL) return NULL; - - int flags = Object_ToInt(argv[2], error); - if(error->occurred) return NULL; - - ssize_t r = recv(sockfd, addr, size, flags); - - return Object_FromInt(r, heap, error); -} \ No newline at end of file diff --git a/src/o_staticmap.c b/src/o_staticmap.c new file mode 100644 index 0000000..22923e6 --- /dev/null +++ b/src/o_staticmap.c @@ -0,0 +1,94 @@ +#include +#include +#include "o_staticmap.h" +#include "utils/defs.h" +#include "objects/objects.h" + +typedef struct { + Object base; + Runtime *runt; + const StaticMapSlot *slots; +} StaticMapObject; + +static Object *select(Object *self, Object *key, Heap *heap, Error *err); +static Object *copy(Object *self, Heap *heap, Error *err); +static int hash(Object *self); + +static TypeObject t_staticmap = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "static map", + .size = sizeof (StaticMapObject), + .copy = copy, + .hash = hash, + .select = select, +}; + +static Object *copy(Object *self, Heap *heap, Error *err) +{ + (void) heap; + (void) err; + return self; +} + +static int hash(Object *self) +{ + (void) self; + return 0; +} + +Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error) +{ + Heap *heap = Runtime_GetHeap(runt); + + // Make the thing. + StaticMapObject *obj = (StaticMapObject*) Heap_Malloc(heap, &t_staticmap, error); + { + if(obj == 0) + return 0; + + obj->runt = runt; + obj->slots = slots; + } + + return (Object*) obj; +} + +static Object *select(Object *self, Object *key, Heap *heap, Error *error) +{ + assert(self != NULL); + assert(self->type == &t_staticmap); + assert(key != NULL); + assert(heap != NULL); + assert(error != NULL); + + StaticMapObject *map = (StaticMapObject*) self; + + if(!Object_IsString(key)) + return NULL; + + const char *name = Object_ToString(key, NULL, heap, error); + + if(map->slots == NULL) + return NULL; + + for(int i = 0; map->slots[i].name != NULL; i += 1) + if(!strcmp(name, map->slots[i].name)) + { + StaticMapSlot slot = map->slots[i]; + Object *obj; + switch(slot.kind) + { + case SM_BOOL: return Object_FromBool(slot.as_bool, heap, error); + case SM_INT: return Object_FromInt(slot.as_int, heap, error); + case SM_FLOAT: return Object_FromFloat(slot.as_float, heap, error); + case SM_FUNCT: return Object_FromNativeFunction(map->runt, slot.as_funct, slot.argc, heap, error); + case SM_STRING: return Object_FromString(slot.as_string, slot.length, heap, error); + case SM_SMAP: return Object_NewStaticMap(slot.as_smap, map->runt, error); + case SM_NONE: return Object_NewNone(heap, error); + case SM_TYPE: return (Object*) slot.as_type; + default: assert(0); break; + } + return obj; + } + return NULL; +} \ No newline at end of file diff --git a/src/o_staticmap.h b/src/o_staticmap.h new file mode 100644 index 0000000..db1893a --- /dev/null +++ b/src/o_staticmap.h @@ -0,0 +1,37 @@ +#ifndef STATICMAP_H +#define STATICMAP_H + +#include "objects/objects.h" +#include "runtime/runtime.h" + +typedef enum { + SM_END, + SM_BOOL, + SM_INT, + SM_FLOAT, + SM_FUNCT, + SM_STRING, + SM_SMAP, + SM_NONE, + SM_TYPE, +} StaticMapSlotKind; + +typedef struct StaticMapSlot StaticMapSlot; + +struct StaticMapSlot { + const char *name; + StaticMapSlotKind kind; + union { + const StaticMapSlot *as_smap; + const char *as_string; + _Bool as_bool; + long long int as_int; + double as_float; + Object *(*as_funct)(Runtime*, Object**, unsigned int, Error*); + TypeObject *as_type; + }; + union { int argc; int length; }; +}; + +Object *Object_NewStaticMap(const StaticMapSlot *slots, Runtime *runt, Error *error); +#endif \ No newline at end of file diff --git a/src/objects/o_buffer.c b/src/objects/o_buffer.c index 9d927ba..3c9a0fb 100644 --- a/src/objects/o_buffer.c +++ b/src/objects/o_buffer.c @@ -52,6 +52,11 @@ static TypeObject t_buffer_slice = { #define THRESHOLD 128 +_Bool Object_IsBuffer(Object *obj) +{ + return obj->type == &t_buffer_slice || obj->type == &t_buffer; +} + Object *Object_NewBuffer(int size, Heap *heap, Error *error) { assert(size >= 0); diff --git a/src/objects/o_dir.c b/src/objects/o_dir.c new file mode 100644 index 0000000..fc15a17 --- /dev/null +++ b/src/objects/o_dir.c @@ -0,0 +1,53 @@ +#include "objects.h" + +typedef struct { + Object base; + DIR *dir; +} DirObject; + +static _Bool dir_free(Object *obj, Error *error); + +static TypeObject t_dir = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "Directory", + .size = sizeof(DirObject), + .free = dir_free, +}; + +_Bool Object_IsDir(Object *obj) +{ + return obj->type == &t_dir; +} + +Object *Object_FromDIR(DIR *handle, Heap *heap, Error *error) +{ + DirObject *dob = (DirObject*) Heap_Malloc(heap, &t_dir, error); + + if(dob == NULL) + return NULL; + + dob->dir = handle; + + return (Object*) dob; +} + +DIR *Object_ToDIR(Object *obj, Error *error) +{ + if(!Object_IsDir(obj)) + { + Error_Report(error, 0, "Object is not a directory"); + return NULL; + } + + return ((DirObject*) obj)->dir; +} + +static _Bool dir_free(Object *obj, Error *error) +{ + DirObject *dob = (DirObject*) obj; + if(closedir(dob->dir) == 0) + return 1; + + Error_Report(error, 0, "Failed to close directory"); + return 0; +} \ No newline at end of file diff --git a/src/objects/o_file.c b/src/objects/o_file.c new file mode 100644 index 0000000..ddc2fa3 --- /dev/null +++ b/src/objects/o_file.c @@ -0,0 +1,53 @@ +#include "objects.h" + +typedef struct { + Object base; + FILE *fp; +} FileObject; + +static _Bool file_free(Object *self, Error *error); + +static TypeObject t_file = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "File", + .size = sizeof(FileObject), + .free = file_free, +}; + +_Bool Object_IsFile(Object *obj) +{ + return obj->type == &t_file; +} + +FILE *Object_ToStream(Object *obj, Error *error) +{ + if(!Object_IsFile(obj)) + { + Error_Report(error, 0, "Object is not a file"); + return NULL; + } + + return ((FileObject*) obj)->fp; +} + +Object *Object_FromStream(FILE *fp, Heap *heap, Error *error) +{ + FileObject *fob = Heap_Malloc(heap, &t_file, error); + + if(fob == NULL) + return NULL; + + fob->fp = fp; + + return (Object*) fob; +} + +static _Bool file_free(Object *self, Error *error) +{ + FileObject *fob = (FileObject*) self; + if(fclose(fob->fp) == 0) + return 1; + + Error_Report(error, 0, "Failed to close stream"); + return 0; +} \ No newline at end of file diff --git a/src/objects/o_none.c b/src/objects/o_none.c index d0e0a19..a5321cc 100644 --- a/src/objects/o_none.c +++ b/src/objects/o_none.c @@ -22,6 +22,11 @@ static Object the_none_object = { .flags = Object_STATIC, }; +_Bool Object_IsNone(Object *obj) +{ + return obj == &the_none_object; +} + static int hash(Object *self) { assert(self == &the_none_object); diff --git a/src/objects/objects.h b/src/objects/objects.h index bdb36b3..18b0e61 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -1,6 +1,7 @@ #ifndef OBJECT_H #define OBJECT_H +#include #include #include "../utils/error.h" @@ -115,18 +116,27 @@ Object* Object_FromInt (long long int val, Heap *heap, Error *error); Object* Object_FromBool (_Bool val, Heap *heap, Error *error); Object* Object_FromFloat (double val, Heap *heap, Error *error); Object* Object_FromString(const char *str, int len, Heap *heap, Error *error); +Object* Object_FromStream(FILE *fp, Heap *heap, Error *error); +Object* Object_FromDIR(DIR *handle, Heap *heap, Error *error); -_Bool Object_IsInt (Object *obj); -_Bool Object_IsBool (Object *obj); -_Bool Object_IsFloat(Object *obj); -_Bool Object_IsString(Object *obj); +_Bool Object_IsNone(Object *obj); +_Bool Object_IsInt(Object *obj); +_Bool Object_IsBool(Object *obj); +_Bool Object_IsFloat(Object *obj); +_Bool Object_IsString(Object *obj); +_Bool Object_IsBuffer(Object *obj); +_Bool Object_IsFile(Object *obj); +_Bool Object_IsDir(Object *obj); long long int Object_ToInt (Object *obj, Error *err); _Bool Object_ToBool (Object *obj, Error *err); double Object_ToFloat(Object *obj, Error *err); const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err); +DIR *Object_ToDIR(Object *obj, Error *error); +FILE *Object_ToStream(Object *obj, Error *error); _Bool Object_Compare(Object *obj1, Object *obj2, Error *error); + extern TypeObject t_type; #endif \ No newline at end of file