diff options
-rw-r--r-- | data_structures.c | 8 | ||||
-rw-r--r-- | eval.c | 3 | ||||
-rw-r--r-- | foreign.c | 33 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 6 | ||||
-rw-r--r-- | types.c | 3 | ||||
-rw-r--r-- | types.h | 16 |
7 files changed, 50 insertions, 20 deletions
diff --git a/data_structures.c b/data_structures.c index 970d966..19f4efd 100644 --- a/data_structures.c +++ b/data_structures.c @@ -287,7 +287,6 @@ static void str_hash_table_grow(StrHashTable *t) { } arr_cleara(&t->slots, t->allocr); t->slots = new_slots; - slots_cap = new_slots_cap; } } @@ -340,12 +339,16 @@ static void str_hash_table_free(StrHashTable *t) { } static StrHashTableSlot *str_hash_table_get_(StrHashTable *t, const char *str, size_t len) { + size_t nslots = arr_len(t->slots); + if (!nslots) return NULL; size_t slot_index = str_hash(str, len) % arr_len(t->slots); return *str_hash_table_slot_get(t->slots, str, len, slot_index); } static inline void *str_hash_table_get(StrHashTable *t, const char *str, size_t len) { - return str_hash_table_get_(t, str, len)->data; + StrHashTableSlot *slot = str_hash_table_get_(t, str, len); + if (!slot) return NULL; + return slot->data; } #ifdef TOC_DEBUG @@ -367,6 +370,7 @@ static void str_hash_table_test(void) { *s = 123; int *u = str_hash_table_get(&t, "Hello", 5); assert(p == u); + assert(!str_hash_table_get(&t, "Hellopf", 7)); str_hash_table_free(&t); } #endif @@ -18,6 +18,7 @@ static void evalr_create(Evaluator *ev, Typer *tr, Allocator *allocr) { ev->typer = tr; ev->enabled = true; ev->allocr = allocr; + ffmgr_create(&ev->ffmgr, allocr); } static void evalr_free(Evaluator *ev) { @@ -1435,7 +1436,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i])) return false; } - bool success = foreign_call(fn, &e->call.fn->type, args, e->where, v); + bool success = foreign_call(&ev->ffmgr, fn, &e->call.fn->type, args, e->where, v); free(args); if (!success) return false; @@ -222,26 +222,33 @@ static bool arg_list_add(av_alist *arg_list, Value *val, Type *type, Location wh return true; } -static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) { +static void ffmgr_create(ForeignFnManager *ffmgr, Allocator *allocr) { + str_hash_table_create(&ffmgr->libs_loaded, sizeof(Library), allocr); +} + +static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Value *args, Location call_where, Value *ret) { void (*fn_ptr)() = fn->foreign.fn_ptr; if (!fn_ptr) { assert(fn->flags & FN_EXPR_FOREIGN); - const char *lib = fn->foreign.lib; - const char *name = fn->foreign.name; - - /* TODO: IMPORTANT: only open libraries once */ - void *handle = dlopen(lib, RTLD_LAZY); - printf("Load %s\n",lib); - if (!handle) { - err_print(call_where, "Could not open dynamic library: %s.", lib); - return false; + const char *libname = fn->foreign.lib; + Library *lib = str_hash_table_get(&ffmgr->libs_loaded, libname, strlen(libname)); + if (!lib) { + /* TODO: IMPORTANT: only open libraries once */ + void *handle = dlopen(libname, RTLD_LAZY); + printf("Load %s\n",libname); + if (!handle) { + err_print(call_where, "Could not open dynamic library: %s.", lib); + return false; + } + lib = str_hash_table_insert(&ffmgr->libs_loaded, libname, strlen(libname)); + lib->handle = handle; } - + const char *name = fn->foreign.name; #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #endif - fn_ptr = dlsym(handle, name); + fn_ptr = dlsym(lib->handle, name); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif @@ -250,7 +257,7 @@ static bool foreign_call(FnExpr *fn, Type *fn_type, Value *args, Location call_w err_print(call_where, "Could not get function from dynamic library: %s.", name); return false; } - fn->foreign.fn_ptr = fn_ptr; + fn->foreign.fn_ptr = fn_ptr; } av_alist arg_list; @@ -66,6 +66,7 @@ int main(int argc, char **argv) { char *contents = err_malloc(4096); contents[0] = 0; /* put 0 byte at the start of the file. see err.c:err_print_location_text to find out why */ + contents[1] = 0; /* if fgets fails the first time */ long contents_cap = 4095; long contents_len = 1; while (fgets(contents + contents_len, (int)(contents_cap - contents_len), in)) { @@ -24,6 +24,12 @@ foo ::= fn() i32 { puts("Hey") }; +malloc :: fn(u64) &u8 = #foreign "malloc", "libc.so.6"; + +sqrt :: fn(f64) f64 = #foreign "sqrt", "libm.so"; + main ::= fn() { x ::= foo(); + y ::= malloc(10); + sq2 ::= sqrt(2); };
\ No newline at end of file @@ -1476,9 +1476,6 @@ static bool types_expr(Typer *tr, Expression *e) { - i = 0; - - table_index_type.flags = TYPE_IS_RESOLVED; table_index_type.kind = TYPE_TUPLE; table_index_type.tuple = NULL; @@ -813,6 +813,20 @@ typedef enum { DECL_END_LBRACE_COMMA } DeclEndKind; +#if COMPILE_TIME_FOREIGN_FN_SUPPORT +typedef struct { + void *handle; +} Library; +#endif + +typedef struct { +#if COMPILE_TIME_FOREIGN_FN_SUPPORT + StrHashTable libs_loaded; /* of Library */ +#else + char unused; +#endif +} ForeignFnManager; + typedef struct Evaluator { Allocator *allocr; struct Typer *typer; @@ -820,6 +834,7 @@ typedef struct Evaluator { Value ret_val; void **to_free; /* an array of data to free for this scope. */ bool enabled; + ForeignFnManager ffmgr; } Evaluator; typedef struct Package { @@ -887,7 +902,6 @@ typedef struct CGenerator { char *pkg_prefix; } CGenerator; - #ifdef TOC_DEBUG #define add_ident_decls(b, d, flags) add_ident_decls_(__FILE__, __LINE__, b, d, flags) #endif |