From 6ba7fd21ef328208417c6c38bdd621f79678f1a2 Mon Sep 17 00:00:00 2001 From: cozis Date: Wed, 17 Aug 2022 04:33:00 +0200 Subject: [PATCH] modified C api for native functions --- examples/json.noja | 271 -------------------------------------- examples/json/json.noja | 9 +- examples/return.noja | 9 -- examples/return2.noja | 33 ----- examples/stack.noja | 45 +++++-- src/lib/builtins/basic.c | 132 ++++++------------- src/lib/builtins/files.c | 108 ++++++++------- src/lib/builtins/math.c | 17 +-- src/lib/noja.c | 4 +- src/lib/objects/objects.c | 4 +- src/lib/objects/objects.h | 6 +- src/lib/runtime/o_func.c | 4 +- src/lib/runtime/o_nfunc.c | 10 +- src/lib/runtime/runtime.c | 10 +- src/lib/runtime/runtime.h | 6 +- 15 files changed, 171 insertions(+), 497 deletions(-) delete mode 100644 examples/json.noja delete mode 100644 examples/return.noja delete mode 100644 examples/return2.noja diff --git a/examples/json.noja b/examples/json.noja deleted file mode 100644 index bc5007b..0000000 --- a/examples/json.noja +++ /dev/null @@ -1,271 +0,0 @@ - -fun isSpace(c) - return c == ' ' - or c == '\t' - or c == '\n'; - -fun isDigit(c) - return unicode(c) <= unicode('9') - and unicode(c) >= unicode('0'); - -fun skip(ctx, test) - while not ended(ctx) and test(current(ctx)): - next(ctx); - -fun ended(ctx) - return ctx.i == count(ctx.str); - -fun next(ctx) { - assert(ctx.i < count(ctx.str)); - ctx.i = ctx.i + 1; -} - -fun current(ctx) { - assert(ctx.i < count(ctx.str)); - return ctx.str[ctx.i]; -} - -fun parse(str) { - - if str == none: - str = ''; - - ctx = {str: str, i: 0}; - - skip(ctx, isSpace); - - if ended(ctx): - return none, 'Source only contains whitespace'; - - res, err = parseAny(ctx); - return res, err; -} - -fun parseArray(ctx) { - - assert(current(ctx) == '['); - - next(ctx); # Skip '['. - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an array"; - - arr = []; - - if current(ctx) == ']': { - next(ctx); - return arr; - } - - while true: { - - child = parseAny(ctx); - - if child == none: - return none; - - arr[count(arr)] = child; - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an array"; - - if current(ctx) == ']': - break; - - if current(ctx) != ',': - return none, "Bad character inside array"; - - next(ctx); # Skip ','. - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an array"; - } - - next(ctx); - return arr; -} - -fun parseObject(ctx) { - - assert(current(ctx) == '{'); - - next(ctx); # Skip '{'. - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an object"; - - obj = {}; - - if current(ctx) == '}': { - next(ctx); - return {}; - } - - while true: { - - if current(ctx) != '"': - return none, "Bad character where a string was expected"; - - key = parseString(ctx); - - if key == none: - return none; - - skip(ctx, isSpace); - - if current(ctx) != ':': - return none, "Bad character where ':' was expected"; - - next(ctx); # Skip ':'. - - skip(ctx, isSpace); - - child = parseAny(ctx); - - if child == none: - return none; - - obj[key] = child; - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an arrays"; - - if current(ctx) == '}': - break; - - if current(ctx) != ',': - return none, "Bad character inside array"; - - next(ctx); # Skip ','. - - skip(ctx, isSpace); - - if ended(ctx): - return none, "Source ended inside an array"; - } - - next(ctx); - return obj; -} - -fun parseString(ctx) { - - next(ctx); # Skip the '"'. - - buff = ''; - - while not ended(ctx) and current(ctx) != '"': { - buff = strcat(buff, current(ctx)); - next(ctx); - } - - if ended(ctx): - return none, "Source ended inside a string"; - - next(ctx); # Skip the '"'. - return buff; -} - -fun parseNumber(ctx) { - - assert(isDigit(current(ctx))); - - # Number (int or float) - - parsed = 0; - while not ended(ctx) and isDigit(current(ctx)): { - parsed = parsed * 10 + unicode(current(ctx)) - unicode('0'); - next(ctx); - } - - if ended(ctx): - return parsed; - - if current(ctx) == '.': { - - next(ctx); - - if ended(ctx): - return none, "Source string ended unexpectedly after dot"; - - if not isDigit(current(ctx)): - return none, "Got something other than a digit after dot"; - - fact = 1; - while not ended(ctx) and isDigit(current(ctx)): { - fact = fact / 10.0; - parsed = parsed + fact * (unicode(current(ctx)) - unicode('0')); - next(ctx); - } - } - - return parsed; -} - -fun parseAny(ctx) { - - assert(not ended(ctx)); - - if current(ctx) == '[': - res, err = parseArray(ctx); - else if current(ctx) == '{': - res, err = parseObject(ctx); - else if current(ctx) == '"': - res, err = parseString(ctx); - else if isDigit(current(ctx)): - res, err = parseNumber(ctx); - else - error("Not implemented yet"); - return res, err; -} - -tests = [ - '', - '1', - '10', - '1.@10', - '1.10', - '"jeje"', - '[]', - '[1,2,3]', - ' [ ] ', - ' [ 1 , 2 , 3 ]', - '{}', - ' { } ', - '{"hoy":4}', - ' { "hoy" : 4 } ' -]; - -i = 0; -while i < count(tests): { - res, err = parse(tests[i]); - if res == none: - print('Test ', i, ' failed (', err, ')\n'); - else - print('Test ', i, ' passed (', tests[i], ' -> ', res, ')\n'); - i = i + 1; -} - -#file = files.openFile('examples/large-file.json', files.READ); -#if file == none: -# error("Failed to open file"); -# -#buff = newBuffer(30000000); -#if buff == none: -# error("Failed to create buffer"); -# -#n = files.read(file, buff); -# -#text = bufferToString(sliceBuffer(buff, 0, n)); -# -#print(parse(text)); diff --git a/examples/json/json.noja b/examples/json/json.noja index 79d2cd4..059fca3 100644 --- a/examples/json/json.noja +++ b/examples/json/json.noja @@ -105,7 +105,7 @@ fun parseFloating(context: Map) { } while context.str[context.cur] != "."; assert(isDigit(context.str[context.cur+1])); - + # Scan the decimal part. q = 1; do { @@ -137,7 +137,8 @@ fun parseIntegerOrFloating(context: Map) { fun parseString(context: Map) { - assert(context.cur < count(context.str) and context.str[context.cur] == '"'); + assert(context.cur < count(context.str) + and context.str[context.cur] == '"'); context.cur = context.cur + 1; @@ -204,7 +205,7 @@ fun parseArray(context: Map) { } fun parseValue(context: Map) { - + if context.cur == count(context.str): return none, "Source ended where a value was expected"; @@ -265,4 +266,4 @@ fun compareAny(A, B) { error("Maps aren't supported yet!"); return A == B; -} \ No newline at end of file +} diff --git a/examples/return.noja b/examples/return.noja deleted file mode 100644 index 1e97864..0000000 --- a/examples/return.noja +++ /dev/null @@ -1,9 +0,0 @@ - -fun hello() - return [1, 2, 3], "hello"; - -print((a, b, c) = hello(), '\n'); - -print('a = ', a, '\n'); -print('b = ', b, '\n'); -print('c = ', c, '\n'); \ No newline at end of file diff --git a/examples/return2.noja b/examples/return2.noja deleted file mode 100644 index 1c85e07..0000000 --- a/examples/return2.noja +++ /dev/null @@ -1,33 +0,0 @@ - -fun duplica_forse(a) { - if a >= 10: - return a*2; - return none, "Il numero รจ inferiore a 10!"; -} - -fun duplica_forse2(a) { - res, err = duplica_forse(a); - return res, err; -} - -num = 5; -num2, err = duplica_forse2(num); - -if num2 == none: - print('ERRORE!!! ', err, '\n'); -else - print(num2, '\n'); - -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a, -a, a, a = print(); \ No newline at end of file diff --git a/examples/stack.noja b/examples/stack.noja index d44bc43..5e27f8c 100644 --- a/examples/stack.noja +++ b/examples/stack.noja @@ -1,8 +1,12 @@ # Implementation of a stack using a linked list. -stack = {count: 0, head: none}; +fun Stack_New(T) + return { count: 0, head: none, type: T }; -fun push(stack, value) { +fun Stack_Push(stack: Map, value) { + + if type(value) != stack.type: + error("Invalid type"); node = {prev: none, item: value}; @@ -11,7 +15,7 @@ fun push(stack, value) { stack.count = stack.count + 1; } -fun pop(stack) { +fun Stack_Pop(stack: Map) { if stack.head == none: return none; @@ -23,15 +27,36 @@ fun pop(stack) { return value; } -push(stack, 1); -push(stack, 2); -push(stack, 3); -x = pop(stack); -y = pop(stack); -z = pop(stack); -w = pop(stack); +fun Stack_Print(stack: Map) { + print("["); + curr = stack.head; + while curr != none: { + print(curr.item); + curr = curr.prev; + if curr != none: + print(", "); + } + print("]"); +} + +stack = Stack_New(int); + +Stack_Push(stack, 1); +Stack_Push(stack, 2); +Stack_Push(stack, 3); + +Stack_Print(stack); +print("\n"); + +x = Stack_Pop(stack); +y = Stack_Pop(stack); +z = Stack_Pop(stack); +w = Stack_Pop(stack); assert(x == 3); assert(y == 2); assert(z == 1); assert(w == none); + +Stack_Print(stack); +print("\n"); \ No newline at end of file diff --git a/src/lib/builtins/basic.c b/src/lib/builtins/basic.c index b6b3a15..245b013 100644 --- a/src/lib/builtins/basic.c +++ b/src/lib/builtins/basic.c @@ -41,11 +41,10 @@ #include "../compiler/compile.h" #include "../runtime/runtime.h" -static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(runtime); UNUSED(rets); - UNUSED(maxretc); UNUSED(error); for(int i = 0; i < (int) argc; i += 1) @@ -53,7 +52,7 @@ static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object return 0; } -static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 1); @@ -109,22 +108,15 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object Source *src = Source_FromFile(full_path, &sub_error); if(src == NULL) { - if(maxretc == 0) - return 0; - Object *o_none = Object_NewNone(heap, error); if(o_none == NULL) return -1; - if(maxretc == 1) { - rets[0] = o_none; - return 1; - } Object *o_err = Object_FromString(sub_error.message, -1, heap, error); if(o_err == NULL) return -1; - Error_Free(&sub_error); + Error_Free(&sub_error); rets[0] = o_none; rets[1] = o_err; return 2; @@ -142,85 +134,61 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object } UNUSED(errname); - { - if(maxretc == 0) - return 0; + Object *o_none = Object_NewNone(heap, error); + if(o_none == NULL) + return -1; - Object *o_none = Object_NewNone(heap, error); - if(o_none == NULL) - return -1; + Object *o_err = Object_FromString(sub_error.message, -1, heap, error); + if(o_err == NULL) + return -1; - if(maxretc == 1) { - rets[0] = o_none; - return 1; - } - Object *o_err = Object_FromString(sub_error.message, -1, heap, error); - if(o_err == NULL) - return -1; - Error_Free(&sub_error); - - rets[0] = o_none; - rets[1] = o_err; - return 2; - } + Error_Free(&sub_error); + rets[0] = o_none; + rets[1] = o_err; + return 2; } + Object *sub_rets[8]; { - Object *sub_rets[8]; - int sub_maxretc = sizeof(sub_rets)/sizeof(sub_rets[0]); - int retc = run(runtime, &sub_error, exe, 0, NULL, NULL, 0, sub_rets, sub_maxretc); + int retc = run(runtime, &sub_error, exe, 0, NULL, NULL, 0, sub_rets); if(retc < 0) { const char *errname = "Runtime"; // Snapshot? UNUSED(errname); - { - if(maxretc == 0) - return 0; - Object *o_none = Object_NewNone(heap, error); - if(o_none == NULL) - return -1; + Object *o_none = Object_NewNone(heap, error); + if(o_none == NULL) + return -1; - if(maxretc == 1) { - rets[0] = o_none; - return 1; - } + Object *o_err = Object_FromString(sub_error.message, -1, heap, error); + if(o_err == NULL) + return -1; - Object *o_err = Object_FromString(sub_error.message, -1, heap, error); - if(o_err == NULL) - return -1; - Error_Free(&sub_error); - - rets[0] = o_none; - rets[1] = o_err; - return 2; - } + Error_Free(&sub_error); + rets[0] = o_none; + rets[1] = o_err; + return 2; } ASSERT(retc == 1); - - if(maxretc == 0) - return 0; - rets[0] = sub_rets[0]; - return 1; } - return 0; + Error_Free(&sub_error); + rets[0] = sub_rets[0]; + return 1; } -static int bin_type(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_type(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { ASSERT(argc == 1); UNUSED(runtime); UNUSED(error); UNUSED(argc); - if(maxretc == 0) - return 0; rets[0] = (Object*) argv[0]->type; return 1; } -static int bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(runtime); UNUSED(error); @@ -257,13 +225,11 @@ static int bin_unicode(Runtime *runtime, Object **argv, unsigned int argc, Objec if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } -static int bin_chr(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_chr(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 1); @@ -295,13 +261,11 @@ static int bin_chr(Runtime *runtime, Object **argv, unsigned int argc, Object ** if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } -static int bin_count(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_count(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 1); @@ -316,13 +280,11 @@ static int bin_count(Runtime *runtime, Object **argv, unsigned int argc, Object if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } -static int bin_input(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_input(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argv); UNUSED(argc); @@ -368,17 +330,14 @@ static int bin_input(Runtime *runtime, Object **argv, unsigned int argc, Object if(res == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = res; return 1; } -static int bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(runtime); UNUSED(rets); - UNUSED(maxretc); for(unsigned int i = 0; i < argc; i += 1) if(!Object_ToBool(argv[i], error)) @@ -390,11 +349,10 @@ static int bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Object return 0; } -static int bin_error(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_error(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); UNUSED(rets); - UNUSED(maxretc); ASSERT(argc == 1); int length; @@ -409,7 +367,7 @@ static int bin_error(Runtime *runtime, Object **argv, unsigned int argc, Object return -1; } -static int bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_strcat(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { unsigned int total_count = 0; @@ -467,13 +425,11 @@ done: if(result == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = result; return 1; } -static int bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 1); @@ -488,13 +444,11 @@ static int bin_newBuffer(Runtime *runtime, Object **argv, unsigned int argc, Obj if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } -static int bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 3); @@ -510,13 +464,11 @@ static int bin_sliceBuffer(Runtime *runtime, Object **argv, unsigned int argc, O if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } -static int bin_bufferToString(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +static int bin_bufferToString(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { UNUSED(argc); ASSERT(argc == 1); @@ -534,8 +486,6 @@ static int bin_bufferToString(Runtime *runtime, Object **argv, unsigned int argc if(temp == NULL) return -1; - if(maxretc == 0) - return 0; rets[0] = temp; return 1; } @@ -567,8 +517,8 @@ StaticMapSlot bins_basic[] = { { "File", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ }, { "Dir", SM_TYPE, .as_type = NULL /* Until bins_basic_init is called */ }, - { "math", SM_SMAP, .as_smap = bins_math, }, -// { "files", SM_SMAP, .as_smap = bins_files, }, + { "math", SM_SMAP, .as_smap = bins_math, }, + { "files", SM_SMAP, .as_smap = bins_files, }, // { "net", SM_SMAP, .as_smap = bins_net, }, { "import", SM_FUNCT, .as_funct = bin_import, .argc = 1, }, diff --git a/src/lib/builtins/files.c b/src/lib/builtins/files.c index 1e817f6..166e411 100644 --- a/src/lib/builtins/files.c +++ b/src/lib/builtins/files.c @@ -27,11 +27,10 @@ ** | with The Noja Interpreter. If not, see . | ** +--------------------------------------------------------------------------+ */ -#warning "Commented out whole file" -/* -#include + #include #include "files.h" +#include "../utils/defs.h" enum { MD_READ = 0, @@ -39,20 +38,21 @@ enum { MD_APPEND = 2, }; -static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +static int bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { - assert(argc == 2); + UNUSED(argc); + 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; + return -1; } if(!Object_IsInt(argv[1])) { Error_Report(error, 0, "Expected second argument to be an int, but it's a %s", Object_GetName(argv[1])); - return NULL; + return -1; } Heap *heap = Runtime_GetHeap(runtime); @@ -60,12 +60,12 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, const char *path = Object_ToString(argv[0], NULL, heap, error); if(error->occurred) - return NULL; + return -1; int mode = Object_ToInt(argv[1], error); if(error->occurred) - return NULL; + return -1; FILE *fp; { @@ -87,22 +87,27 @@ static Object *bin_openFile(Runtime *runtime, Object **argv, unsigned int argc, break; default: - assert(0); + UNREACHABLE; + mode2 = NULL; break; } fp = fopen(path, mode2); if(fp == NULL) - return Object_NewNone(heap, error); + return 0; } - return Object_FromStream(fp, heap, error); + rets[0] = Object_FromStream(fp, heap, error); + if(rets[0] == NULL) + return -1; + return 1; } -static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +static int bin_read(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { - assert(argc == 3); + UNUSED(argc); + ASSERT(argc == 3); // Arg 0: file // Arg 1: buffer @@ -111,13 +116,13 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro 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; + return -1; } if(!Object_IsBuffer(argv[1])) { Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1])); - return NULL; + return -1; } Heap *heap = Runtime_GetHeap(runtime); @@ -138,7 +143,7 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro long long int temp = Object_ToInt(argv[2], error); if(error->occurred) - return NULL; + return -1; read_size = temp; // TODO: Handle potential overflow. @@ -148,22 +153,26 @@ static Object *bin_read(Runtime *runtime, Object **argv, unsigned int argc, Erro 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; + return -1; } FILE *fp = Object_ToStream(argv[0], error); if(fp == NULL) - return NULL; + return -1; size_t n = fread(buff_addr, 1, read_size, fp); - return Object_FromInt(n, heap, error); + rets[0] = Object_FromInt(n, heap, error); + if(rets[0] == NULL) + return -1; + return 1; } -static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +static int bin_write(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { - assert(argc == 3); + UNUSED(argc); + ASSERT(argc == 3); // Arg 0: file // Arg 1: buffer @@ -172,13 +181,13 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err 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; + return -1; } if(!Object_IsBuffer(argv[1])) { Error_Report(error, 0, "Expected second argument to be a buffer, but it's a %s", Object_GetName(argv[1])); - return NULL; + return -1; } Heap *heap = Runtime_GetHeap(runtime); @@ -199,7 +208,7 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err long long int temp = Object_ToInt(argv[2], error); if(error->occurred) - return NULL; + return -1; write_size = temp; // TODO: Handle potential overflow. @@ -209,29 +218,33 @@ static Object *bin_write(Runtime *runtime, Object **argv, unsigned int argc, Err 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; + return -1; } FILE *fp = Object_ToStream(argv[0], error); if(fp == NULL) - return NULL; + return -1; size_t n = fwrite(buff_addr, 1, write_size, fp); - return Object_FromInt(n, heap, error); + rets[0] = Object_FromInt(n, heap, error); + if(rets[0] == NULL) + return -1; + return 1; } -static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +static int bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { - assert(argc == 1); + UNUSED(argc); + 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; + return -1; } Heap *heap = Runtime_GetHeap(runtime); @@ -239,42 +252,44 @@ static Object *bin_openDir(Runtime *runtime, Object **argv, unsigned int argc, E const char *path = Object_ToString(argv[0], NULL, heap, error); if(error->occurred) - return NULL; + return -1; DIR *dir = opendir(path); if(dir == NULL) - return Object_NewNone(heap, error); + return 0; Object *dob = Object_FromDIR(dir, heap, error); if(error->occurred) { (void) closedir(dir); - return NULL; + return -1; } - return dob; + rets[0] = dob; + return 1; } -static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +static int bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) { - assert(argc == 1); + UNUSED(argc); + 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; + return -1; } DIR *dir = Object_ToDIR(argv[0], error); if(error->occurred) - return NULL; + return -1; - assert(dir != NULL); + ASSERT(dir != NULL); Heap *heap = Runtime_GetHeap(runtime); @@ -285,15 +300,17 @@ static Object *bin_nextDirItem(Runtime *runtime, Object **argv, unsigned int arg if(ent == NULL) { if(errno == 0) - // Nothing left to read. - return Object_NewNone(heap, error); + return 0; // Nothing left to read. // An error occurred. Error_Report(error, 1, "Failed to read directory item"); - return NULL; + return -1; } - return Object_FromString(ent->d_name, -1, heap, error); + rets[0] = Object_FromString(ent->d_name, -1, heap, error); + if(rets[0] == NULL) + return -1; + return 1; } StaticMapSlot bins_files[] = { @@ -306,5 +323,4 @@ StaticMapSlot bins_files[] = { { "read", SM_FUNCT, .as_funct = bin_read, .argc = 3, }, { "write", SM_FUNCT, .as_funct = bin_write, .argc = 3, }, { NULL, SM_END, {}, {} }, -}; -*/ \ No newline at end of file +}; \ No newline at end of file diff --git a/src/lib/builtins/math.c b/src/lib/builtins/math.c index cc10ed9..128190e 100644 --- a/src/lib/builtins/math.c +++ b/src/lib/builtins/math.c @@ -33,7 +33,7 @@ #include "../utils/defs.h" #define WRAP_FUNC(name) \ - static int bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) \ + static int bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) \ { \ UNUSED(argc); \ ASSERT(argc == 1); \ @@ -45,14 +45,10 @@ if(error->occurred) \ return -1; \ \ - if(maxretc > 0) \ - { \ - rets[0] = Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \ - if(rets[0] == NULL) \ - return -1; \ - return 1; \ - } \ - return 0; \ + rets[0] = Object_FromFloat(name(v), Runtime_GetHeap(runtime), error); \ + if(rets[0] == NULL) \ + return -1; \ + return 1; \ } \ else \ { \ @@ -62,7 +58,7 @@ } #define WRAP_FUNC_2(name) \ - static int bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) \ + static int bin_ ## name(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Error *error) \ { \ UNUSED(argc); \ ASSERT(argc == 2); \ @@ -91,7 +87,6 @@ \ Object *res = Object_FromFloat(name(v1, v2), Runtime_GetHeap(runtime), error); \ if(res == NULL) return -1; \ - if(maxretc == 0) return 0; \ rets[0] = res; \ return 1; \ } diff --git a/src/lib/noja.c b/src/lib/noja.c index b8a42e2..b3ead0a 100644 --- a/src/lib/noja.c +++ b/src/lib/noja.c @@ -70,9 +70,7 @@ static _Bool interpret(Executable *exe) Runtime_SetBuiltins(runt, bins); Object *rets[8]; - unsigned int maxretc = sizeof(rets)/sizeof(rets[0]); - - int retc = run(runt, (Error*) &error, exe, 0, NULL, NULL, 0, rets, maxretc); + int retc = run(runt, (Error*) &error, exe, 0, NULL, NULL, 0, rets); // NOTE: The pointer to the builtins object is invalidated // now because it may be moved by the garbage collector. diff --git a/src/lib/objects/objects.c b/src/lib/objects/objects.c index 28cc7d2..f8a1e2d 100644 --- a/src/lib/objects/objects.c +++ b/src/lib/objects/objects.c @@ -125,7 +125,7 @@ Object *Object_Copy(Object *obj, Heap *heap, Error *err) return type->copy(obj, heap, err); } -int Object_Call(Object *obj, Object **argv, unsigned int argc, Object **rets, unsigned int maxrets, Heap *heap, Error *err) +int Object_Call(Object *obj, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Heap *heap, Error *err) { ASSERT(err != NULL && obj != NULL); @@ -138,7 +138,7 @@ int Object_Call(Object *obj, Object **argv, unsigned int argc, Object **rets, un return -1; } - return type->call(obj, argv, argc, rets, maxrets, heap, err); + return type->call(obj, argv, argc, rets, heap, err); } void Object_Print(Object *obj, FILE *fp) diff --git a/src/lib/objects/objects.h b/src/lib/objects/objects.h index d1d1989..30d3128 100644 --- a/src/lib/objects/objects.h +++ b/src/lib/objects/objects.h @@ -35,6 +35,8 @@ #include #include "../utils/error.h" +#define MAX_RETS 8 + typedef struct TypeObject TypeObject; typedef struct Object Object; typedef struct xHeap Heap; @@ -70,7 +72,7 @@ struct TypeObject { _Bool (*free)(Object *self, Error *err); int (*hash)(Object *self); Object* (*copy)(Object *self, Heap *heap, Error *err); - int (*call)(Object *self, Object **argv, unsigned int argc, Object **rets, unsigned int maxrets, Heap *heap, Error *err); + int (*call)(Object *self, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Heap *heap, Error *err); void (*print)(Object *self, FILE *fp); unsigned int (*deepsize)(const Object *self); @@ -123,7 +125,7 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err); void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error); int Object_Hash (Object *obj); Object* Object_Copy (Object *obj, Heap *heap, Error *err); -int Object_Call (Object *obj, Object **argv, unsigned int argc, Object **rets, unsigned int maxrets, Heap *heap, Error *err); +int Object_Call (Object *obj, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Heap *heap, Error *err); void Object_Print (Object *obj, FILE *fp); Object* Object_Select(Object *coll, Object *key, Heap *heap, Error *err); Object* Object_Delete(Object *coll, Object *key, Heap *heap, Error *err); diff --git a/src/lib/runtime/o_func.c b/src/lib/runtime/o_func.c index 5037fda..3ce55aa 100644 --- a/src/lib/runtime/o_func.c +++ b/src/lib/runtime/o_func.c @@ -57,7 +57,7 @@ static void walk(Object *self, void (*callback)(Object **referer, void *userp), callback(&func->closure, userp); } -static int call(Object *self, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Heap *heap, Error *error) +static int call(Object *self, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Heap *heap, Error *error) { assert(self != NULL && heap != NULL && error != NULL); @@ -108,7 +108,7 @@ static int call(Object *self, Object **argv, unsigned int argc, Object **rets, u // The right amount of arguments was provided. argv2 = argv; - int retc = run(func->runtime, error, func->exe, func->index, func->closure, argv2, expected_argc, rets, maxretc); + int retc = run(func->runtime, error, func->exe, func->index, func->closure, argv2, expected_argc, rets); // NOTE: Every object reference is invalidated from here. diff --git a/src/lib/runtime/o_nfunc.c b/src/lib/runtime/o_nfunc.c index 9780ded..f5dc8cf 100644 --- a/src/lib/runtime/o_nfunc.c +++ b/src/lib/runtime/o_nfunc.c @@ -43,11 +43,11 @@ typedef struct { Object base; Runtime *runtime; - int (*callback)(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error); + int (*callback)(Runtime *runtime, Object **argv, unsigned int argc, Object *rets[MAX_RETS], Error *error); int argc; } NativeFunctionObject; -static int call(Object *self, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Heap *heap, Error *error) +static int call(Object *self, Object **argv, unsigned int argc, Object *rets[static MAX_RETS], Heap *heap, Error *error) { assert(self != NULL); assert(heap != NULL); @@ -112,8 +112,8 @@ static int call(Object *self, Object **argv, unsigned int argc, Object **rets, u } assert(func->callback != NULL); - int retc = func->callback(func->runtime, argv2, argc2, rets, maxretc, error); - + int retc = func->callback(func->runtime, argv2, argc2, rets, error); + // NOTE: Since the callback may have executed some bytecode, a GC // cycle may have been triggered, therefore we must assume // every object reference that was locally saved is invalidated @@ -156,7 +156,7 @@ static TypeObject t_nfunc = { * The newly created object. If an error occurred, NULL is returned * and information about the error is stored in the [error] argument. */ -Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error) +Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object*[static MAX_RETS], Error*), int argc, Heap *heap, Error *error) { assert(callback != NULL); diff --git a/src/lib/runtime/runtime.c b/src/lib/runtime/runtime.c index ca2a96c..9b540b7 100644 --- a/src/lib/runtime/runtime.c +++ b/src/lib/runtime/runtime.c @@ -916,9 +916,7 @@ static _Bool step(Runtime *runtime, Error *error) ASSERT(error->occurred == 0); Object *rets[8]; - unsigned int maxrets = sizeof(rets)/sizeof(rets[0]); - - int num_rets = Object_Call(callable, argv, argc, rets, maxrets, runtime->heap, error); + int num_rets = Object_Call(callable, argv, argc, rets, runtime->heap, error); if(num_rets < 0) return 0; @@ -1278,6 +1276,7 @@ static _Bool step(Runtime *runtime, Error *error) int retc = ops[0].as_int; UNUSED(retc); ASSERT(retc >= 0); + ASSERT(retc <= MAX_RETS); ASSERT(retc == runtime->frame->used); return 0; } @@ -1400,7 +1399,7 @@ int run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc, - Object **rets, int maxretc) + Object *rets[static MAX_RETS]) { ASSERT(runtime != NULL); ASSERT(error != NULL); @@ -1484,7 +1483,8 @@ int run(Runtime *runtime, Error *error, // If an error occurred, we want to return NULL. if(error->occurred == 0) { - retc = MIN(frame.used, maxretc); + retc = frame.used; + ASSERT(retc <= MAX_RETS); for(int i = 0; i < retc; i += 1) { diff --git a/src/lib/runtime/runtime.h b/src/lib/runtime/runtime.h index a1812a1..f65ca45 100644 --- a/src/lib/runtime/runtime.h +++ b/src/lib/runtime/runtime.h @@ -56,7 +56,7 @@ const char *Runtime_GetCurrentScriptAbsolutePath(Runtime *runtime); Snapshot *Snapshot_New(Runtime *runtime); void Snapshot_Free(Snapshot *snapshot); void Snapshot_Print(Snapshot *snapshot, FILE *fp); -int run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc, Object **rets, int maxretc); +int run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc, Object *rets[static MAX_RETS]); typedef enum { SM_END, @@ -81,7 +81,7 @@ struct StaticMapSlot { _Bool as_bool; long long int as_int; double as_float; - int (*as_funct)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*); + int (*as_funct)(Runtime*, Object**, unsigned int, Object*[static MAX_RETS], Error*); TypeObject *as_type; }; union { int argc; int length; }; @@ -89,7 +89,7 @@ struct StaticMapSlot { Object *Object_NewStaticMap(StaticMapSlot slots[], void (*initfn)(StaticMapSlot[]), Runtime *runt, Error *error); Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error); -Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error); +Object *Object_FromNativeFunction(Runtime *runtime, int (*callback)(Runtime*, Object**, unsigned int, Object*[static MAX_RETS], Error*), int argc, Heap *heap, Error *error); typedef struct { Error base; Runtime *runtime;