Skip to content

Commit

Permalink
external functions: Ability to set return value
Browse files Browse the repository at this point in the history
  • Loading branch information
obiwac committed Sep 13, 2024
1 parent ef182dd commit 57e91f3
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 7 deletions.
8 changes: 7 additions & 1 deletion flamingo/flamingo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
6 changes: 4 additions & 2 deletions flamingo/grammar/call.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
46 changes: 46 additions & 0 deletions flamingo/val.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <assert.h>
#include <stdlib.h>
#include <string.h>

static flamingo_val_t* val_incref(flamingo_val_t* val) {
assert(val->ref_count > 0); // value has already been freed
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
}
27 changes: 25 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
15 changes: 13 additions & 2 deletions tests/proto.fl
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 57e91f3

Please sign in to comment.