diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-29 11:32:42 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-29 11:32:42 -0500 |
commit | 7cced2c313c94d1fb8736581840dff00708aabf1 (patch) | |
tree | e4a29cac17f46f03a57addc14d049dff32927692 | |
parent | a970f5f91b6f90acab60d05d1f5f92d059248e95 (diff) |
new foreign system working like old one did now
-rw-r--r-- | allocator.c | 2 | ||||
-rw-r--r-- | decls_cgen.c | 4 | ||||
-rw-r--r-- | foreign.c | 5 | ||||
-rw-r--r-- | parse.c | 151 | ||||
-rw-r--r-- | test.toc | 9 | ||||
-rw-r--r-- | toc.c | 1 | ||||
-rw-r--r-- | types.c | 2 |
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); @@ -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); @@ -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: @@ -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 @@ -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); @@ -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; |