diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-28 13:17:44 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-28 13:17:44 -0500 |
commit | 7d90b03b3d698a633582305a0e584919d5bb3f53 (patch) | |
tree | 95990bf8456aee41cea1e940483684025a754d86 | |
parent | 982d900343b8a7d9405c68d3ab176ad180858c4c (diff) |
started new #foreign system
-rw-r--r-- | cgen.c | 29 | ||||
-rw-r--r-- | decls_cgen.c | 83 | ||||
-rw-r--r-- | eval.c | 13 | ||||
-rw-r--r-- | parse.c | 333 | ||||
-rw-r--r-- | sdecls_cgen.c | 4 | ||||
-rw-r--r-- | test.toc | 14 | ||||
-rw-r--r-- | types.c | 66 | ||||
-rw-r--r-- | types.h | 43 |
8 files changed, 348 insertions, 237 deletions
@@ -1206,21 +1206,19 @@ static void cgen_expr(CGenerator *g, Expression *e) { if (i->decl_kind == IDECL_DECL) { Declaration *d = i->decl; if (d->flags & DECL_IS_CONST) { - if (!(d->flags & DECL_FOREIGN) || d->foreign.lib) { - int index = decl_ident_index(d, i); - Value fn_val = *decl_val_at_index(d, index); - FnExpr *fn = fn_val.fn; - Expression fn_expr; + int index = decl_ident_index(d, i); + Value fn_val = *decl_val_at_index(d, index); + FnExpr *fn = fn_val.fn; + Expression fn_expr; - fn_expr.kind = EXPR_FN; - fn_expr.fn = allocr_malloc(g->allocr, sizeof *fn_expr.fn); - *fn_expr.fn = *fn; - fn_expr.flags = EXPR_FOUND_TYPE; - fn_expr.type = *decl_type_at_index(d, index); + fn_expr.kind = EXPR_FN; + fn_expr.fn = allocr_malloc(g->allocr, sizeof *fn_expr.fn); + *fn_expr.fn = *fn; + fn_expr.flags = EXPR_FOUND_TYPE; + fn_expr.type = *decl_type_at_index(d, index); - cgen_expr(g, &fn_expr); - handled = true; - } + cgen_expr(g, &fn_expr); + handled = true; } } } @@ -1732,8 +1730,6 @@ static void cgen_val(CGenerator *g, Value v, Type *t, Location where) { } static void cgen_decl(CGenerator *g, Declaration *d) { - if (d->flags & DECL_FOREIGN) - return; /* already dealt with */ if (g->block == NULL && g->fn == NULL) return; /* already dealt with */ int has_expr = d->flags & DECL_HAS_EXPR; @@ -1947,9 +1943,6 @@ static void cgen_defs_expr(CGenerator *g, Expression *e) { } static void cgen_defs_decl(CGenerator *g, Declaration *d) { - if (d->flags & DECL_FOREIGN) { - return; /* dealt with by decls_cgen */ - } if (d->flags & DECL_HAS_EXPR) { cgen_defs_expr(g, &d->expr); } diff --git a/decls_cgen.c b/decls_cgen.c index c04e433..44fa436 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -3,6 +3,45 @@ This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever. You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>. */ + +/* TODO */ +#if 0 + if (d->flags & DECL_FOREIGN) { + cgen_write(g, "extern "); + if ((d->flags & DECL_IS_CONST) && (d->type.kind == TYPE_FN) && arr_len(d->idents) == 1) { + /* foreign function declaration */ + Type *fn_types = d->type.fn.types; + const char *foreign_name = (d->flags & DECL_FOUND_VAL) + ? d->val.fn->foreign.name + : d->foreign.name_str; + cgen_type_pre(g, &fn_types[0], d->where); + cgen_write(g, " %s", foreign_name); + cgen_write(g, "("); + arr_foreach(fn_types, Type, t) { + if (t == fn_types) continue; + if (t != fn_types+1) + cgen_write(g, ", "); + cgen_type_pre(g, t, d->where); + cgen_type_post(g, t, d->where); + } + cgen_write(g, ")"); + cgen_type_post(g, &fn_types[0], d->where); + cgen_write(g, ";"); + if (!ident_eq_str(d->idents[0], foreign_name)) { + cgen_write(g, "static "); + cgen_type_pre(g, &d->type, d->where); + cgen_write(g, " const "); + cgen_ident(g, d->idents[0]); + cgen_type_post(g, &d->type, d->where); + cgen_write(g, " = %s;", foreign_name); + } + cgen_nl(g); + if (d->flags & DECL_FOUND_VAL) + d->val.fn->c.name = d->idents[0]; + return; + +#endif + static void cgen_decls_stmt(CGenerator *g, Statement *s); static void cgen_decls_block(CGenerator *g, Block *b); static void cgen_decls_decl(CGenerator *g, Declaration *d); @@ -108,50 +147,6 @@ static void cgen_decls_block(CGenerator *g, Block *b) { } static void cgen_decls_decl(CGenerator *g, Declaration *d) { - if (d->flags & DECL_FOREIGN) { - cgen_write(g, "extern "); - if ((d->flags & DECL_IS_CONST) && (d->type.kind == TYPE_FN) && arr_len(d->idents) == 1) { - /* foreign function declaration */ - Type *fn_types = d->type.fn.types; - const char *foreign_name = (d->flags & DECL_FOUND_VAL) - ? d->val.fn->foreign.name - : d->foreign.name_str; - cgen_type_pre(g, &fn_types[0], d->where); - cgen_write(g, " %s", foreign_name); - cgen_write(g, "("); - arr_foreach(fn_types, Type, t) { - if (t == fn_types) continue; - if (t != fn_types+1) - cgen_write(g, ", "); - cgen_type_pre(g, t, d->where); - cgen_type_post(g, t, d->where); - } - cgen_write(g, ")"); - cgen_type_post(g, &fn_types[0], d->where); - cgen_write(g, ";"); - if (!ident_eq_str(d->idents[0], foreign_name)) { - cgen_write(g, "static "); - cgen_type_pre(g, &d->type, d->where); - cgen_write(g, " const "); - cgen_ident(g, d->idents[0]); - cgen_type_post(g, &d->type, d->where); - cgen_write(g, " = %s;", foreign_name); - } - cgen_nl(g); - if (d->flags & DECL_FOUND_VAL) - d->val.fn->c.name = d->idents[0]; - return; - } else { - /* foreign non-function */ - const char *foreign_name = d->foreign.name_str; - cgen_type_pre(g, &d->type, d->where); - cgen_write(g, " %s", foreign_name); - cgen_type_post(g, &d->type, d->where); - cgen_write(g, ";"); - cgen_nl(g); - } - return; - } cgen_decls_type(g, &d->type); if (cgen_fn_is_direct(g, d)) { cgen_fn_decl(g, d->expr.fn, &d->expr.type); @@ -986,19 +986,6 @@ static Status eval_ident(Evaluator *ev, Identifier ident, Value *v, Location whe Declaration *d = NULL; if (is_decl) { d = ident->decl; - if (d->flags & DECL_FOREIGN) { - if (!(d->flags & DECL_FOUND_VAL)) { -#if COMPILE_TIME_FOREIGN_FN_SUPPORT - err_print(where, "Cannot access foreign declaration at compile time. " - "If you are calling a function, you need to provide the library it's in."); -#else - err_print(where, "Cannot access foreign declaration at compile time."); -#endif - return false; - } - v->fn = d->val.fn; - return true; - } if ((d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_TYPE && d->expr.typeval.kind == TYPE_STRUCT) { v->type = allocr_malloc(ev->allocr, sizeof *v->type); v->type->flags = TYPE_IS_RESOLVED; @@ -645,11 +645,6 @@ static Status parse_type(Parser *p, Type *type) { err_print(field_decl.where, "Constant struct members are not supported (yet)."); goto struct_fail; } - if ((field_decl.flags & DECL_FOREIGN) && !(field_decl.flags & DECL_IS_CONST)) { - err_print(field_decl.where, "Non-constant struct members cannot be foreign."); - goto struct_fail; - } - if (field_decl.flags & DECL_HAS_EXPR) { err_print(field_decl.where, "struct members cannot have initializers."); goto struct_fail; @@ -948,11 +943,6 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { if (!parse_decl_list(p, &f->params, DECL_END_RPAREN_COMMA)) return false; arr_foreach(f->params, Declaration, param) { - if (param->flags & DECL_FOREIGN) { - err_print(param->where, "Parameters cannot be foreign."); - success = false; - goto ret; - } param->flags |= DECL_IS_PARAM; } } @@ -978,10 +968,6 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) { err_print(d->where, "Can't infer the value of a named return value!"); success = false; goto ret; } - if (d->flags & DECL_FOREIGN) { - err_print(d->where, "Named return values can't be foreign."); - success = false; goto ret; - } } --t->token; /* move back to { */ /* just set return type to void. the actual return type will be set by types.c:type_of_fn */ @@ -1057,6 +1043,85 @@ static Status check_ident_redecl(Parser *p, Identifier i) { return true; } +static BuiltinType int_with_size(size_t size) { + switch (size) { + case 1: return BUILTIN_I8; + case 2: return BUILTIN_I16; + case 4: return BUILTIN_I32; + case 8: return BUILTIN_I64; + } + return BUILTIN_F32; +} + +static BuiltinType uint_with_size(size_t size) { + switch (size) { + case 1: return BUILTIN_U8; + case 2: return BUILTIN_U16; + case 4: return BUILTIN_U32; + case 8: return BUILTIN_U64; + } + return BUILTIN_F32; +} + +static Status ctype_to_type(Allocator *a, CType *ctype, Type *type, Location where) { + memset(type, 0, sizeof *type); + type->kind = TYPE_BUILTIN; + size_t size = 0; + switch (ctype->kind) { + case CTYPE_NONE: + type->kind = TYPE_UNKNOWN; + break; + case CTYPE_CHAR: + type->builtin = BUILTIN_CHAR; + break; + case CTYPE_SIGNED_CHAR: + case CTYPE_UNSIGNED_CHAR: + size = 1; + break; + case CTYPE_SHORT: + case CTYPE_UNSIGNED_SHORT: + size = sizeof(short); + break; + case CTYPE_INT: + case CTYPE_UNSIGNED_INT: + size = sizeof(int); + break; + case CTYPE_LONG: + case CTYPE_UNSIGNED_LONG: + size = sizeof(long); + break; + case CTYPE_LONGLONG: + case CTYPE_UNSIGNED_LONGLONG: +#if HAVE_LONGLONG + size = sizeof(longlong); +#else + err_print(where, "long long is not supported. Did you compile toc with a pre-C99 compiler?"); + return false; +#endif + break; + case CTYPE_FLOAT: + type->builtin = BUILTIN_F32; + break; + case CTYPE_DOUBLE: + type->builtin = BUILTIN_F64; + break; + case CTYPE_PTR: + type->kind = TYPE_PTR; + type->ptr = allocr_calloc(a, 1, sizeof *type->ptr); + type->ptr->kind = TYPE_UNKNOWN; + break; + case CTYPE_UNSIGNED: assert(0); break; + } + if (size != 0) { + type->builtin = ((ctype->kind & CTYPE_UNSIGNED) ? uint_with_size : int_with_size)(size); + if (type->builtin == BUILTIN_F32) { + err_print(where, "This C type is not representable by a toc type, because it is %lu bytes (not 1, 2, 4, or 8).", size); + return false; + } + } + return true; +} + static Status parse_expr(Parser *p, Expression *e, Token *end) { Tokenizer *t = p->tokr; @@ -1680,6 +1745,148 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } else { not_an_op:; /* function calls, array accesses, etc. */ + + if (t->token->kind == TOKEN_DIRECT) { + /* it's a directive */ + Expression *single_arg = NULL; /* points to an expr if this is a directive with one expression argument */ + + switch (t->token->direct) { + case DIRECT_C: + e->kind = EXPR_C; + single_arg = e->c.code = parser_new_expr(p); + break; + case DIRECT_BUILTIN: + e->kind = EXPR_BUILTIN; + single_arg = e->builtin.which.expr = parser_new_expr(p); + break; + case DIRECT_SIZEOF: + e->kind = EXPR_UNARY_OP; + e->unary.op = UNARY_DSIZEOF; + single_arg = e->unary.of = parser_new_expr(p); + break; + case DIRECT_ALIGNOF: + e->kind = EXPR_UNARY_OP; + e->unary.op = UNARY_DALIGNOF; + single_arg = e->unary.of = parser_new_expr(p); + break; + case DIRECT_FOREIGN: { + /* foreign function */ + e->kind = EXPR_FN; + e->type.kind = TYPE_FN; + FnExpr *fn = e->fn = parser_calloc(p, 1, sizeof *e->fn); + fn->flags |= FN_EXPR_FOREIGN; + FnType *fn_type = &e->type.fn; + fn_type->constness = NULL; + fn_type->types = NULL; + ++t->token; + if (!token_is_kw(t->token, KW_FN)) { + tokr_err(t, "Expected fn to follow #foreign."); + return false; + } + ++t->token; + if (!token_is_kw(t->token, KW_LPAREN)) { + tokr_err(t, "Expected ( after #foreign fn"); + } + ++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; + } + if (token_is_kw(t->token, KW_COMMA)) { + ++t->token; + } else if (token_is_kw(t->token, KW_RPAREN)) { + ++t->token; + break; + } else { + tokr_err(t, "Expected , or ) following #foreign fn type."); + return false; + } + } + return true; + } + case DIRECT_EXPORT: + case DIRECT_INCLUDE: + case DIRECT_FORCE: + tokr_err(t, "Unrecognized expression."); + return false; + case DIRECT_COUNT: assert(0); break; + } + if (single_arg) { + ++t->token; + if (!token_is_kw(t->token, KW_LPAREN)) { + tokr_err(t, "Expected ( to follow #%s.", directives[t->token->direct]); + return false; + } + ++t->token; + Token *arg_end = expr_find_end(p, 0); + if (!token_is_kw(arg_end, KW_RPAREN)) { + err_print(token_location(p->file, arg_end), "Expected ) at end of #%s directive.", directives[t->token->direct]); + return false; + } + if (!parse_expr(p, single_arg, arg_end)) + return false; + ++t->token; + goto success; + } + } /* try a function call or array access */ Token *token = t->token; @@ -1827,56 +2034,6 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } } - if (t->token->kind == TOKEN_DIRECT) { - /* it's a directive */ - Expression *single_arg = NULL; /* points to an expr if this is a directive with one expression argument */ - - switch (t->token->direct) { - case DIRECT_C: - e->kind = EXPR_C; - single_arg = e->c.code = parser_new_expr(p); - break; - case DIRECT_BUILTIN: - e->kind = EXPR_BUILTIN; - single_arg = e->builtin.which.expr = parser_new_expr(p); - break; - case DIRECT_SIZEOF: - e->kind = EXPR_UNARY_OP; - e->unary.op = UNARY_DSIZEOF; - single_arg = e->unary.of = parser_new_expr(p); - break; - case DIRECT_ALIGNOF: - e->kind = EXPR_UNARY_OP; - e->unary.op = UNARY_DALIGNOF; - single_arg = e->unary.of = parser_new_expr(p); - break; - case DIRECT_FOREIGN: - case DIRECT_EXPORT: - case DIRECT_INCLUDE: - case DIRECT_FORCE: - tokr_err(t, "Unrecognized expression."); - return false; - case DIRECT_COUNT: assert(0); break; - } - if (single_arg) { - ++t->token; - if (!token_is_kw(t->token, KW_LPAREN)) { - tokr_err(t, "Expected ( to follow #%s.", directives[t->token->direct]); - return false; - } - ++t->token; - Token *arg_end = expr_find_end(p, 0); - if (!token_is_kw(arg_end, KW_RPAREN)) { - err_print(token_location(p->file, arg_end), "Expected ) at end of #%s directive.", directives[t->token->direct]); - return false; - } - if (!parse_expr(p, single_arg, arg_end)) - return false; - ++t->token; - goto success; - } - } - if (token_is_kw(t->token, KW_LBRACE)) { /* it's a block */ e->kind = EXPR_BLOCK; @@ -2012,39 +2169,7 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f if (token_is_kw(t->token, KW_EQ)) { ++t->token; - if (token_is_direct(t->token, DIRECT_FOREIGN)) { - if (!(d->flags & DECL_ANNOTATES_TYPE)) { - tokr_err(t, "Foreign declaration must have a type."); - goto ret_false; - } - d->flags |= DECL_FOREIGN; - /* foreign name */ - ++t->token; - d->foreign.name = parser_new_expr(p); - if (!parse_expr(p, d->foreign.name, expr_find_end(p, EXPR_CAN_END_WITH_COMMA))) { - goto ret_false; - } - d->foreign.lib = NULL; - if (!ends_decl(t->token, ends_with)) { - if (!token_is_kw(t->token, KW_COMMA)) { - tokr_err(t, "Expected comma, followed by foreign library."); - goto ret_false; - } - ++t->token; - /* foreign library */ - d->foreign.lib = parser_new_expr(p); - if (!parse_expr(p, d->foreign.lib, expr_find_end(p, 0))) { - goto ret_false; - } - } - - if (!ends_decl(t->token, ends_with)) { - tokr_err(t, "Expected declaration to stop after #foreign, but it continues."); - goto ret_false; - } - ++t->token; - - } else if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) { + if ((flags & PARSE_DECL_ALLOW_INFER) && ends_decl(t->token, ends_with)) { /* inferred expression */ d->flags |= DECL_INFER; if (!(d->flags & DECL_IS_CONST)) { @@ -2084,9 +2209,9 @@ static Status parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 f } } - if ((d->flags & DECL_IS_CONST) && !(d->flags & (DECL_HAS_EXPR | DECL_FOREIGN)) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) { + if ((d->flags & DECL_IS_CONST) && !(d->flags & DECL_HAS_EXPR) && !(flags & PARSE_DECL_ALLOW_CONST_WITH_NO_EXPR)) { --t->token; - /* disallowed constant without an expression, e.g. x :: int; */ + /* disallow constant without an expression, e.g. x :: int; */ tokr_err(t, "You must have an expression at the end of this constant declaration."); goto ret_false; } @@ -2644,14 +2769,8 @@ static bool ident_is_definitely_const(Identifier i) { Declaration *decl = i->decl; if (i->decl_kind != IDECL_DECL || !(decl->flags & DECL_IS_CONST)) return false; - if (i->decl->flags & DECL_FOREIGN) { - if (decl->foreign.lib && COMPILE_TIME_FOREIGN_FN_SUPPORT) - return true; - else - return false; - } else { - return true; - } + + return true; } diff --git a/sdecls_cgen.c b/sdecls_cgen.c index 7eec064..52795f7 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -101,10 +101,6 @@ static void cgen_sdecls_expr(CGenerator *g, Expression *e) { static void cgen_sdecls_decl(CGenerator *g, Declaration *d) { - if (d->flags & DECL_FOREIGN) { - /* handled by cgen_decls */ - return; - } cgen_sdecls_type(g, &d->type); if (cgen_fn_is_direct(g, d)) { d->expr.fn->c.name = d->idents[0]; @@ -1,18 +1,6 @@ -#include #force "std/io.toc", io; -#include #force "std/io.toc", foo; -#include #force "std/io.toc"; -a ::= nms { - b ::= nms { - x := 3; - }; - f ::= fn() { b.x += 1; io.puti(b.x); foo.puti(b.x); puti(b.x); - }; -}; +puts ::= #foreign fn (#C int); main ::= fn() { - a.f(); - a.f(); - a.f(); };
\ No newline at end of file @@ -370,7 +370,40 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) { FnExpr *prev_fn = tr->fn; FnExpr fn_copy = {0}; - +#if 0 + /* TODO */ + if (!type_resolve(tr, &d->type, d->where)) { + success = false; + goto ret; + } + char *name_cstr = eval_expr_as_cstr(tr, d->foreign.name, "foreign name"); + if (!name_cstr) { + success = false; + goto ret; + } + if (d->foreign.lib) { + char *lib_cstr = eval_expr_as_cstr(tr, d->foreign.lib, "foreign library name"); + if (!lib_cstr) { + success = false; + goto ret; + } + /* make sure no one tries to use these */ + d->foreign.name = NULL; + d->foreign.lib = NULL; + + FnExpr *f = d->val.fn = typer_calloc(tr, 1, sizeof *d->expr.fn); + f->flags = FN_EXPR_FOREIGN; + f->where = d->expr.where = d->where; + f->foreign.name = name_cstr; + f->foreign.lib = lib_cstr; + f->foreign.fn_ptr = NULL; + + d->flags |= DECL_FOUND_VAL; + } else { + d->foreign.name_str = name_cstr; + } +#endif + /* f has compile time params, but it's not an instance! */ bool generic = !(flags & TYPE_OF_FN_IS_INSTANCE) && fn_has_any_const_params(f); if (generic) { @@ -2710,37 +2743,6 @@ static Status types_decl(Typer *tr, Declaration *d) { } } - } else if (d->flags & DECL_FOREIGN) { - if (!type_resolve(tr, &d->type, d->where)) { - success = false; - goto ret; - } - char *name_cstr = eval_expr_as_cstr(tr, d->foreign.name, "foreign name"); - if (!name_cstr) { - success = false; - goto ret; - } - if (d->foreign.lib) { - char *lib_cstr = eval_expr_as_cstr(tr, d->foreign.lib, "foreign library name"); - if (!lib_cstr) { - success = false; - goto ret; - } - /* make sure no one tries to use these */ - d->foreign.name = NULL; - d->foreign.lib = NULL; - - FnExpr *f = d->val.fn = typer_calloc(tr, 1, sizeof *d->expr.fn); - f->flags = FN_EXPR_FOREIGN; - f->where = d->expr.where = d->where; - f->foreign.name = name_cstr; - f->foreign.lib = lib_cstr; - f->foreign.fn_ptr = NULL; - - d->flags |= DECL_FOUND_VAL; - } else { - d->foreign.name_str = name_cstr; - } } for (size_t i = 0; i < arr_len(d->idents); ++i) { @@ -27,15 +27,24 @@ For more information, please refer to <http://unlicense.org/> typedef long double Floating; /* OPTIM: Switch to double, but make sure floating-point literals are right */ + +#if __STDC_VERSION__ >= 199901 +#define HAVE_LONGLONG 1 +typedef long long longlong; +#else +#define HAVE_LONGLONG 0 +typedef long longlong; +#endif + + #if __STDC_VERSION__ < 201112 /* try to find the type with the strictest alignment */ typedef union { long double floating; void *ptr; - #if __STDC_VERSION__ >= 199901 - long + #if HAVE_LONGLONG + longlong integer; #endif - long integer; void (*fn_ptr)(void); } MaxAlign; #else @@ -629,6 +638,29 @@ enum { FN_EXPR_EXPORT = 0x02 /* set by sdecls_cgen.c */ }; +typedef enum { + CTYPE_NONE = 0x00, + CTYPE_CHAR = 0x01, + CTYPE_SHORT = 0x02, + CTYPE_INT = 0x03, + CTYPE_LONG = 0x04, + CTYPE_LONGLONG = 0x05, + CTYPE_SIGNED_CHAR = 0x06, + CTYPE_UNSIGNED = 0x08, + CTYPE_UNSIGNED_CHAR = CTYPE_UNSIGNED|CTYPE_CHAR, + CTYPE_UNSIGNED_SHORT = CTYPE_UNSIGNED|CTYPE_SHORT, + CTYPE_UNSIGNED_INT = CTYPE_UNSIGNED|CTYPE_INT, + CTYPE_UNSIGNED_LONG = CTYPE_UNSIGNED|CTYPE_LONG, + CTYPE_UNSIGNED_LONGLONG = CTYPE_UNSIGNED|CTYPE_LONGLONG, + CTYPE_PTR = 0x10, + CTYPE_FLOAT = 0x11, + CTYPE_DOUBLE = 0x12 +} CTypeKind; +typedef struct { + CTypeKind kind; + char *points_to; /* if kind == CTYPE_PTR, ident string of C type which it points to */ +} CType; + typedef struct FnExpr { struct Declaration *params; /* declarations of the parameters to this function */ struct Declaration *ret_decls; /* array of decls, if this has named return values. otherwise, NULL */ @@ -637,6 +669,7 @@ typedef struct FnExpr { union { Block body; struct { + CType *ctypes; /* ctypes[i] = CTYPE_NONE if this isn't a ctype, or the specified CType. don't use this as a dynamic array. */ const char *name; const char *lib; void (*fn_ptr)(); @@ -742,7 +775,6 @@ typedef struct Expression { } cgen; union { Floating floatl; - /* Floating floatl; */ U64 intl; StrLiteral strl; bool booll; @@ -805,8 +837,7 @@ enum { DECL_FOUND_VAL = 0x0040, DECL_INFER = 0x0080, /* infer the value (e.g. fn(t::Type=, x:t)) */ DECL_EXPORT = 0x0100, - DECL_FOREIGN = 0x0200, - DECL_IS_PARAM = 0x0400 + DECL_IS_PARAM = 0x0200 }; typedef U16 DeclFlags; |