diff --git a/flamingo/flamingo.h b/flamingo/flamingo.h index 383436b..4568d7c 100644 --- a/flamingo/flamingo.h +++ b/flamingo/flamingo.h @@ -12,7 +12,7 @@ typedef struct flamingo_val_t flamingo_val_t; typedef struct flamingo_var_t flamingo_var_t; typedef struct flamingo_scope_t flamingo_scope_t; -typedef int (*flamingo_external_fn_cb_t)(flamingo_t* flamingo, size_t name_size, char* name, void* data); +typedef int (*flamingo_external_fn_cb_t)(flamingo_t* flamingo, size_t name_size, char* name, void* data, size_t arg_count, flamingo_val_t** args, flamingo_val_t** rv); typedef enum { FLAMINGO_VAL_KIND_NONE, @@ -138,3 +138,9 @@ int flamingo_inherit_scope_stack(flamingo_t* flamingo, size_t stack_size, flamin int flamingo_run(flamingo_t* flamingo); flamingo_var_t* flamingo_scope_find_var(flamingo_t* flamingo, char const* key, size_t key_size); + +flamingo_val_t* flamingo_val_make_none(void); +flamingo_val_t* flamingo_val_make_int(int64_t integer); +flamingo_val_t* flamingo_val_make_str(size_t size, char* str); +flamingo_val_t* flamingo_val_make_cstr(char* str); +flamingo_val_t* flamingo_val_make_bool(bool boolean); diff --git a/flamingo/grammar/call.h b/flamingo/grammar/call.h index 7496f76..7449bb1 100644 --- a/flamingo/grammar/call.h +++ b/flamingo/grammar/call.h @@ -183,9 +183,11 @@ static int parse_call(flamingo_t* flamingo, TSNode node, flamingo_val_t** val) { return error(flamingo, "cannot call external function without a external function callback being set"); } - // TODO Arguments, return value. + size_t arg_count = 0; + flamingo_val_t** args = NULL; + assert(flamingo->cur_fn_rv == NULL); - if (flamingo->external_fn_cb(flamingo, callable->name_size, callable->name, flamingo->external_fn_cb_data) < 0) { + if (flamingo->external_fn_cb(flamingo, callable->name_size, callable->name, flamingo->external_fn_cb_data, arg_count, args, &flamingo->cur_fn_rv) < 0) { return -1; } } diff --git a/flamingo/val.c b/flamingo/val.c index 6c03063..bb98974 100644 --- a/flamingo/val.c +++ b/flamingo/val.c @@ -7,6 +7,7 @@ #include #include +#include static flamingo_val_t* val_incref(flamingo_val_t* val) { assert(val->ref_count > 0); // value has already been freed @@ -16,9 +17,13 @@ static flamingo_val_t* val_incref(flamingo_val_t* val) { } static flamingo_val_t* val_init(flamingo_val_t* val) { + // By default, values are anonymous. + val->name = NULL; val->name_size = 0; + // By default, values are nones. + val->kind = FLAMINGO_VAL_KIND_NONE; val->ref_count = 1; @@ -70,6 +75,8 @@ static char const* val_role_str(flamingo_val_t* val) { static flamingo_val_t* val_alloc(void) { flamingo_val_t* const val = calloc(1, sizeof *val); + assert(val != NULL); + return val_init(val); } @@ -111,3 +118,42 @@ static flamingo_val_t* val_decref(flamingo_val_t* val) { val_free(val); return NULL; } + +flamingo_val_t* flamingo_val_make_none(void) { + return val_alloc(); +} + +flamingo_val_t* flamingo_val_make_int(int64_t integer) { + flamingo_val_t* const val = val_alloc(); + + val->kind = FLAMINGO_VAL_KIND_INT; + val->integer.integer = integer; + + return val; +} + +flamingo_val_t* flamingo_val_make_str(size_t size, char* str) { + flamingo_val_t* const val = val_alloc(); + + val->kind = FLAMINGO_VAL_KIND_STR; + + val->str.size = size; + val->str.str = malloc(size); + assert(val->str.str != NULL); + memcpy(val->str.str, str, size); + + return val; +} + +flamingo_val_t* flamingo_val_make_cstr(char* str) { + return flamingo_val_make_str(strlen(str), str); +} + +flamingo_val_t* flamingo_val_make_bool(bool boolean) { + flamingo_val_t* const val = val_alloc(); + + val->kind = FLAMINGO_VAL_KIND_BOOL; + val->boolean.boolean = boolean; + + return val; +} diff --git a/main.c b/main.c index 8a4278f..05d323d 100644 --- a/main.c +++ b/main.c @@ -36,8 +36,31 @@ static void usage(void) { exit(EXIT_FAILURE); } -static int external_fn_cb(flamingo_t* flamingo, size_t name_size, char* name, void* data) { - printf("function call: %.*s\n", (int) name_size, name); +static int external_fn_cb(flamingo_t* flamingo, size_t name_size, char* name, void* data, size_t arg_count, flamingo_val_t** args, flamingo_val_t** rv) { + if (memcmp(name, "test_return_number", name_size) == 0) { + *rv = flamingo_val_make_int(420); + } + + else if (memcmp(name, "test_return_bool", name_size) == 0) { + *rv = flamingo_val_make_bool(true); + } + + else if (memcmp(name, "test_return_str", name_size) == 0) { + *rv = flamingo_val_make_cstr("zonnebloemgranen"); + } + + else if (memcmp(name, "test_return_none", name_size) == 0) { + *rv = flamingo_val_make_none(); + } + + else if (memcmp(name, "test_do_literally_nothing", name_size) == 0) { + } + + else { + printf("Runtime does not support the '%.*s' external function call (%zu args)\n", (int) name_size, name, arg_count); + return -1; + } + return 0; } diff --git a/tests/proto.fl b/tests/proto.fl index 2e98e3f..77b687e 100644 --- a/tests/proto.fl +++ b/tests/proto.fl @@ -1,3 +1,14 @@ -proto i_am_a_prototype +proto test_do_literally_nothing +assert test_do_literally_nothing() == none -i_am_a_prototype() +proto test_return_number +assert test_return_number() == 420 + +proto test_return_bool +assert test_return_bool() == true + +proto test_return_str +assert test_return_str() == "zonnebloemgranen" + +proto test_return_none +assert test_return_none() == none