summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-28 13:17:44 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-28 13:17:44 -0500
commit7d90b03b3d698a633582305a0e584919d5bb3f53 (patch)
tree95990bf8456aee41cea1e940483684025a754d86
parent982d900343b8a7d9405c68d3ab176ad180858c4c (diff)
started new #foreign system
-rw-r--r--cgen.c29
-rw-r--r--decls_cgen.c83
-rw-r--r--eval.c13
-rw-r--r--parse.c333
-rw-r--r--sdecls_cgen.c4
-rw-r--r--test.toc14
-rw-r--r--types.c66
-rw-r--r--types.h43
8 files changed, 348 insertions, 237 deletions
diff --git a/cgen.c b/cgen.c
index 1bef91b..6e91d21 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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);
diff --git a/eval.c b/eval.c
index 52bd874..5c687b2 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/parse.c b/parse.c
index a9d7ba9..4ccf19b 100644
--- a/parse.c
+++ b/parse.c
@@ -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];
diff --git a/test.toc b/test.toc
index 2a4b107..086de07 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/types.c b/types.c
index 017e23c..1da876d 100644
--- a/types.c
+++ b/types.c
@@ -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) {
diff --git a/types.h b/types.h
index fb848f9..027a89e 100644
--- a/types.h
+++ b/types.h
@@ -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;