summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-29 11:32:42 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-29 11:32:42 -0500
commit7cced2c313c94d1fb8736581840dff00708aabf1 (patch)
treee4a29cac17f46f03a57addc14d049dff32927692
parenta970f5f91b6f90acab60d05d1f5f92d059248e95 (diff)
new foreign system working like old one did now
-rw-r--r--allocator.c2
-rw-r--r--decls_cgen.c4
-rw-r--r--foreign.c5
-rw-r--r--parse.c151
-rw-r--r--test.toc9
-rw-r--r--toc.c1
-rw-r--r--types.c2
7 files changed, 102 insertions, 72 deletions
diff --git a/allocator.c b/allocator.c
index cf747ab..fae828a 100644
--- a/allocator.c
+++ b/allocator.c
@@ -25,7 +25,7 @@ static void *err_malloc(size_t bytes);
static void *err_calloc(size_t n, size_t sz);
static void *err_realloc(void *prev, size_t new_size);
#ifdef TOC_DEBUG
-/* #define NO_ALLOCATOR 1 /\* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator *\/ */
+#define NO_ALLOCATOR 1 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */
#endif
/* number of bytes a page hold, not including the header */
#define PAGE_BYTES (16384 - sizeof(Page))
diff --git a/decls_cgen.c b/decls_cgen.c
index 0753616..8d56444 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -76,8 +76,8 @@ static void cgen_fn_decl(CGenerator *g, FnExpr *f, Type *t) {
if (sub == fn_types) continue;
if (sub != fn_types+1)
cgen_write(g, ", ");
- cgen_type_pre(g, t, f->where);
- cgen_type_post(g, t, f->where);
+ cgen_type_pre(g, sub, f->where);
+ cgen_type_post(g, sub, f->where);
}
cgen_write(g, ")");
cgen_type_post(g, &fn_types[0], f->where);
diff --git a/foreign.c b/foreign.c
index 2a61aca..cbceba4 100644
--- a/foreign.c
+++ b/foreign.c
@@ -273,6 +273,11 @@ static bool foreign_call(ForeignFnManager *ffmgr, FnExpr *fn, Type *fn_type, Val
if (!fn_ptr) {
assert(fn->flags & FN_EXPR_FOREIGN);
const char *libname = fn->foreign.lib;
+ if (!libname) {
+ err_print(call_where, "Attempt to call function at compile time which does not have an associated library.");
+ info_print(fn->where, "Function was declared here.");
+ return false;
+ }
Library *lib = str_hash_table_get(&ffmgr->libs_loaded, libname, strlen(libname));
if (!lib) {
void *handle = dlopen(libname, RTLD_LAZY);
diff --git a/parse.c b/parse.c
index f2d5540..2aa3da0 100644
--- a/parse.c
+++ b/parse.c
@@ -1122,6 +1122,68 @@ static Status ctype_to_type(Allocator *a, CType *ctype, Type *type, Location whe
return true;
}
+static Status parse_c_type(Parser *p, CType *ctype, Type *type) {
+ Tokenizer *t = p->tokr;
+ if (token_is_direct(t->token, DIRECT_C)) {
+ ++t->token;
+ ctype->kind = CTYPE_NONE;
+ if (token_is_kw(t->token, KW_INT)) {
+ ctype->kind = CTYPE_INT;
+ ++t->token;
+ } else if (token_is_kw(t->token, KW_AMPERSAND)) {
+ ctype->kind = CTYPE_PTR;
+ ++t->token;
+ if (t->token->kind != TOKEN_IDENT) {
+ tokr_err(t, "Expected type to follow &");
+ return false;
+ }
+ ctype->points_to = t->token->ident;
+ ++t->token;
+ } else if (t->token->kind == TOKEN_IDENT) {
+ char *id = t->token->ident;
+ CTypeKind kind = 0;
+ if (ident_str_len(id) > 9 && strncmp(id, "unsigned_", 9)) {
+ kind |= CTYPE_UNSIGNED;
+ id += 9;
+ }
+ if (ident_str_eq_str(id, "char"))
+ ctype->kind |= CTYPE_CHAR;
+ else if (ident_str_eq_str(id, "signed_char"))
+ ctype->kind = CTYPE_SIGNED_CHAR;
+ else if (ident_str_eq_str(id, "short"))
+ ctype->kind |= CTYPE_SHORT;
+ else if (ident_str_eq_str(id, "int"))
+ ctype->kind |= CTYPE_INT;
+ else if (ident_str_eq_str(id, "long"))
+ ctype->kind |= CTYPE_LONG;
+ else if (ident_str_eq_str(id, "long_long"))
+ ctype->kind |= CTYPE_CHAR;
+ else if (ident_str_eq_str(id, "float"))
+ ctype->kind = CTYPE_FLOAT;
+ else if (ident_str_eq_str(id, "double"))
+ ctype->kind = CTYPE_DOUBLE;
+ else if (ident_str_eq_str(id, "long_double")) {
+ tokr_err(t, "long double is not supported for #foreign functions.");
+ return false;
+ } else {
+ tokr_err(t, "Unrecognized C type.");
+ return false;
+ }
+ ++t->token;
+ } else {
+ tokr_err(t, "Unrecognized C type.");
+ return false;
+ }
+ if (!ctype_to_type(p->allocr, ctype, type, token_location(p->file, t->token)))
+ return false;
+ } else {
+ ctype->kind = CTYPE_NONE;
+ if (!parse_type(p, type))
+ return false;
+ }
+ return true;
+}
+
static Status parse_expr(Parser *p, Expression *e, Token *end) {
Tokenizer *t = p->tokr;
@@ -1770,22 +1832,26 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
single_arg = e->unary.of = parser_new_expr(p);
break;
case DIRECT_FOREIGN: {
+
+ e->kind = EXPR_FN;
+ FnExpr *fn = e->fn = parser_calloc(p, 1, sizeof *e->fn);
+ fn->flags |= FN_EXPR_FOREIGN;
+ fn->foreign.fn_ptr = 0;
+ fn->where.start = t->token;
+ fn->where.file = p->file;
++t->token;
if (!token_is_kw(t->token, KW_LPAREN)) {
tokr_err(t, "Expected ( following #foreign.");
return false;
}
++t->token;
-
- e->kind = EXPR_FN;
- FnExpr *fn = e->fn = parser_calloc(p, 1, sizeof *e->fn);
- fn->flags |= FN_EXPR_FOREIGN;
- fn->foreign.fn_ptr = 0;
Type *fn_t = &fn->foreign.type;
fn_t->kind = TYPE_FN;
FnType *fn_type = &fn_t->fn;
fn_type->constness = NULL;
fn_type->types = NULL;
+ Type *ret_type = parser_arr_add(p, &fn_type->types);
+ CType *ret_ctype = parser_arr_add(p, &fn->foreign.ctypes);
Expression *name = fn->foreign.name_expr = parser_new_expr(p);
if (!parse_expr(p, name, expr_find_end(p, EXPR_CAN_END_WITH_COMMA)))
@@ -1819,66 +1885,10 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
}
++t->token;
while (!token_is_kw(t->token, KW_RPAREN)) {
- if (token_is_direct(t->token, DIRECT_C)) {
- CType ctype = {0};
- ++t->token;
- if (token_is_kw(t->token, KW_INT)) {
- ctype.kind = CTYPE_INT;
- ++t->token;
- } else if (token_is_kw(t->token, KW_AMPERSAND)) {
- ctype.kind = CTYPE_PTR;
- ++t->token;
- if (t->token->kind != TOKEN_IDENT) {
- tokr_err(t, "Expected type to follow &");
- return false;
- }
- ctype.points_to = t->token->ident;
- ++t->token;
- } else if (t->token->kind == TOKEN_IDENT) {
- char *id = t->token->ident;
- CTypeKind kind = 0;
- if (ident_str_len(id) > 9 && strncmp(id, "unsigned_", 9)) {
- kind |= CTYPE_UNSIGNED;
- id += 9;
- }
- if (ident_str_eq_str(id, "char"))
- ctype.kind |= CTYPE_CHAR;
- else if (ident_str_eq_str(id, "signed_char"))
- ctype.kind = CTYPE_SIGNED_CHAR;
- else if (ident_str_eq_str(id, "short"))
- ctype.kind |= CTYPE_SHORT;
- else if (ident_str_eq_str(id, "int"))
- ctype.kind |= CTYPE_INT;
- else if (ident_str_eq_str(id, "long"))
- ctype.kind |= CTYPE_LONG;
- else if (ident_str_eq_str(id, "long_long"))
- ctype.kind |= CTYPE_CHAR;
- else if (ident_str_eq_str(id, "float"))
- ctype.kind = CTYPE_FLOAT;
- else if (ident_str_eq_str(id, "double"))
- ctype.kind = CTYPE_DOUBLE;
- else if (ident_str_eq_str(id, "long_double")) {
- tokr_err(t, "long double is not supported for #foreign functions.");
- return false;
- } else {
- tokr_err(t, "Unrecognized C type.");
- return false;
- }
- ++t->token;
- } else {
- tokr_err(t, "Unrecognized C type.");
- return false;
- }
- *(CType *)parser_arr_add(p, &fn->foreign.ctypes) = ctype;
- Type *type = parser_arr_add(p, &fn_type->types);
- if (!ctype_to_type(p->allocr, &ctype, type, token_location(p->file, t->token)))
- return false;
- } else {
- CType *ctype = parser_arr_add(p, &fn->foreign.ctypes);
- ctype->kind = CTYPE_NONE;
- Type *type = parser_arr_add(p, &fn_type->types);
- if (!parse_type(p, type))
- return false;
+ Type *type = parser_arr_add(p, &fn_type->types);
+ CType *ctype = parser_arr_add(p, &fn->foreign.ctypes);
+ if (!parse_c_type(p, ctype, type)) {
+ return false;
}
if (token_is_kw(t->token, KW_COMMA)) {
++t->token;
@@ -1890,6 +1900,17 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
return false;
}
}
+ if (t->token == end) {
+ /* void */
+ ret_ctype->kind = CTYPE_NONE;
+ ret_type->kind = TYPE_VOID;
+ ret_type->flags = 0;
+ ret_type->was_expr = NULL;
+ } else {
+ if (!parse_c_type(p, ret_ctype, ret_type))
+ return false;
+ }
+ fn->where.end = t->token;
return true;
}
case DIRECT_EXPORT:
diff --git a/test.toc b/test.toc
index 825da51..66560f8 100644
--- a/test.toc
+++ b/test.toc
@@ -1,6 +1,9 @@
-puts ::= #foreign("puts", "libc.so.6") fn (#C int);
+putchar ::= #foreign("putchar", "libc.so.6") fn (#C int) #C int;
+
main ::= fn() {
- puts("Hello!");
-}; \ No newline at end of file
+ putchar(97);
+ putchar('\n' as i32);
+};
+main(); \ No newline at end of file
diff --git a/toc.c b/toc.c
index ac52363..4033181 100644
--- a/toc.c
+++ b/toc.c
@@ -91,6 +91,7 @@
/* forward declarations for debugging */
static void print_val(Value v, Type *t);
static void print_token(Token *t);
+static void print_type(Type *t);
static void print_block(Block *b);
static void print_decl(Declaration *d);
static void print_block_location(Block *b);
diff --git a/types.c b/types.c
index fa5d60b..54a28ae 100644
--- a/types.c
+++ b/types.c
@@ -1832,7 +1832,7 @@ static Status types_expr(Typer *tr, Expression *e) {
arr_set_lena(&arg_exprs, nparams, tr->allocr);
I16 *order = NULL;
- if (fn_decl) {
+ if (fn_decl && !(fn_decl->flags & FN_EXPR_FOREIGN)) {
if (!call_arg_param_order(fn_decl, &f->type, c->args, e->where, &order)) {
free(order);
return false;