summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arr.c2
-rw-r--r--cgen.c89
-rw-r--r--decls_cgen.c11
-rw-r--r--eval.c3
-rw-r--r--main.c19
-rw-r--r--parse.c15
-rw-r--r--test.toc23
-rw-r--r--toc.c3
-rw-r--r--typedefs_cgen.c143
-rw-r--r--types.c30
-rw-r--r--types.h10
11 files changed, 270 insertions, 78 deletions
diff --git a/arr.c b/arr.c
index 0e67eb3..8f63a44 100644
--- a/arr.c
+++ b/arr.c
@@ -139,7 +139,7 @@ You shouldn't rely on this, though, e.g. by doing
#define arr_last(arr) arr_last_((void *)(arr), sizeof *(arr))
#define arr_foreach(arr, type, var) for (type *var = arr_len(arr) ? arr : NULL, *var##_foreach_end = arr_last(arr); var; var == var##_foreach_end ? var = NULL : var++)
#define arr_remove_last(arr) arr_remove_last_((void **)(arr), sizeof **(arr))
-
+
#ifdef TOC_DEBUG
static void arr_test(void) {
int *foos = NULL;
diff --git a/cgen.c b/cgen.c
index 947ad0d..aa21857 100644
--- a/cgen.c
+++ b/cgen.c
@@ -13,7 +13,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
- g->ident_counter = 0;
+ g->ident_counter = 1; /* some places use 0 to mean no id */
g->main_ident = ident_get(ids, "main");
g->evalr = ev;
g->will_indent = true;
@@ -185,9 +185,15 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
/* We should never try to generate this type */
assert(0);
return false;
- case TYPE_USER:
- cgen_ident(g, t->user.name);
- break;
+ case TYPE_USER: {
+ Declaration *d = ident_decl(t->user.name)->decl;
+ assert(d->c.ids);
+ long i = decl_ident_index(d, t->user.name);
+ if (d->c.ids[i])
+ cgen_ident_id(g, d->c.ids[i]);
+ else
+ cgen_ident(g, t->user.name);
+ } break;
}
return true;
}
@@ -200,14 +206,8 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
return false;
break;
case TYPE_ARR:
- if (t->flags & TYPE_FLAG_RESOLVED)
- cgen_write(g, "[%lu])", (unsigned long)t->arr.n);
- else {
- cgen_write(g, "[");
- if (!cgen_expr(g, t->arr.n_expr))
- return false;
- cgen_write(g, "])");
- }
+ assert(t->flags & TYPE_FLAG_RESOLVED);
+ cgen_write(g, "[%lu])", (unsigned long)t->arr.n);
if (!cgen_type_post(g, t->arr.of, where))
return false;
break;
@@ -644,11 +644,36 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!cgen_block(g, &e->block, ret_name, 0))
return false;
break;
- case EXPR_CALL:
+ case EXPR_CALL: {
if (!cgen_expr_pre(g, e->call.fn)) return false;
arr_foreach(e->call.arg_exprs, Expression, arg)
if (!cgen_expr_pre(g, arg)) return false;
- break;
+ if (cgen_uses_ptr(&e->type)) {
+ e->call.c.id = g->ident_counter++;
+ if (!cgen_type_pre(g, &e->type, e->where)) return false;
+ cgen_write(g, " ");
+ cgen_ident_id(g, e->call.c.id);
+ if (!cgen_type_post(g, &e->type, e->where)) return false;
+ cgen_write(g, ";"); cgen_nl(g);
+ if (!cgen_expr(g, e->call.fn)) return false;
+ cgen_write(g, "(");
+ bool any_args = false;
+ arr_foreach(e->call.arg_exprs, Expression, arg) {
+ any_args = true;
+ if (arg != e->call.arg_exprs)
+ cgen_write(g, ", ");
+ if (!cgen_expr(g, arg))
+ return false;
+ }
+ if (any_args) {
+ cgen_write(g, ", ");
+ }
+ cgen_write(g, "&");
+ cgen_ident_id(g, e->call.c.id);
+ cgen_write(g, ");");
+ cgen_nl(g);
+ }
+ } break;
case EXPR_UNARY_OP:
if (!cgen_expr_pre(g, e->unary.of)) return false;
break;
@@ -895,17 +920,21 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
cgen_ident_id(g, e->block_ret_id);
break;
case EXPR_CALL:
- cgen_write(g, "(");
- if (!cgen_expr(g, e->call.fn))
- return false;
- cgen_write(g, "(");
- arr_foreach(e->call.arg_exprs, Expression, arg) {
- if (arg != e->call.arg_exprs)
- cgen_write(g, ", ");
- if (!cgen_expr(g, arg))
+ if (cgen_uses_ptr(&e->type)) {
+ cgen_ident_id(g, e->call.c.id);
+ } else {
+ cgen_write(g, "(");
+ if (!cgen_expr(g, e->call.fn))
return false;
+ cgen_write(g, "(");
+ arr_foreach(e->call.arg_exprs, Expression, arg) {
+ if (arg != e->call.arg_exprs)
+ cgen_write(g, ", ");
+ if (!cgen_expr(g, arg))
+ return false;
+ }
+ cgen_write(g, "))");
}
- cgen_write(g, "))");
break;
case EXPR_DIRECT:
switch (e->direct.which) {
@@ -1174,13 +1203,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
Type *type = is_tuple ? &d->type.tuple[idx] : &d->type;
Value *val = is_tuple ? &d->val.tuple[idx] : &d->val;
if (type->kind == TYPE_TYPE) {
- cgen_write(g, "typedef ");
- if (!cgen_type_pre(g, val->type, d->where)) return false;
- cgen_write(g, " ");
- cgen_ident(g, i);
- if (!cgen_type_post(g, val->type, d->where)) return false;
- cgen_write(g, ";");
- cgen_nl(g);
+ /* handled in decls_cgen */
continue;
}
if (!cgen_val_pre(g, val, type, d->where))
@@ -1285,15 +1308,13 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
cgen_nl(g);
break;
case STMT_RET:
- if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL))
+ if (!cgen_ret(g, s->ret.flags & RET_HAS_EXPR ? &s->ret.expr : NULL))
return false;
break;
}
return true;
}
-static bool cgen_decls_file(CGenerator *g, ParsedFile *f);
-
static bool cgen_file(CGenerator *g, ParsedFile *f) {
g->block = NULL;
g->file = f;
@@ -1316,6 +1337,8 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
"static void *e__calloc(size_t n, size_t sz) { void *ret = calloc(n, sz); if (!ret) { fprintf(stderr, \"Out of memory.\\n\"); abort(); } return ret; }\n"
"#define false ((bool)0)\n"
"#define true ((bool)1)\n\n\n");
+ if (!typedefs_file(g, f))
+ return false;
if (!cgen_decls_file(g, f))
return false;
cgen_write(g, "/* code */\n");
diff --git a/decls_cgen.c b/decls_cgen.c
index 58383f7..dcf5629 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -115,8 +115,13 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) {
return false;
break;
case STMT_EXPR:
+ if (!cgen_decls_expr(g, &s->expr))
+ return false;
break;
case STMT_RET:
+ if (s->ret.flags & RET_HAS_EXPR)
+ if (!cgen_decls_expr(g, &s->ret.expr))
+ return false;
break;
}
return true;
@@ -125,6 +130,12 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) {
static bool cgen_decls_file(CGenerator *g, ParsedFile *f) {
cgen_write(g, "/* declarations */\n");
arr_foreach(f->stmts, Statement, s) {
+ /* if only (you need to recurse!) */
+ /* OPTIM?? */
+ if (s->kind == STMT_DECL) {
+ }
+ }
+ arr_foreach(f->stmts, Statement, s) {
if (!cgen_decls_stmt(g, s))
return false;
}
diff --git a/eval.c b/eval.c
index de3d1ac..ad38f1d 100644
--- a/eval.c
+++ b/eval.c
@@ -20,6 +20,9 @@ static void evalr_free(Evaluator *ev) {
static inline void *evalr_malloc(Evaluator *ev, size_t bytes) {
return allocr_malloc(&ev->allocr, bytes);
}
+static inline void *evalr_calloc(Evaluator *ev, size_t n, size_t bytes) {
+ return allocr_calloc(&ev->allocr, n, bytes);
+}
static size_t compiler_sizeof_builtin(BuiltinType b) {
switch (b) {
diff --git a/main.c b/main.c
index c7094ce..624dcce 100644
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
/*
TODO:
-resolve user-defined types
+don't cast in C for user types
+fix [4]User
make sure user defined types work
structs
length of slice/arr with .len
@@ -65,12 +66,12 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
- arr_foreach(t.tokens, Token, token) {
- if (token != t.tokens)
- printf(" ");
- fprint_token(stdout, token);
- }
- printf("\n");
+ /* arr_foreach(t.tokens, Token, token) { */
+ /* if (token != t.tokens) */
+ /* printf(" "); */
+ /* fprint_token(stdout, token); */
+ /* } */
+ /* printf("\n"); */
Parser p;
parser_from_tokenizer(&p, &t);
ParsedFile f;
@@ -79,9 +80,9 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
tokr_free_tokens(&t);
- fprint_parsed_file(stdout, &f);
+ /* fprint_parsed_file(stdout, &f); */
- printf("\n\n-----\n\n");
+ /* printf("\n\n-----\n\n"); */
Typer tr;
Evaluator ev;
diff --git a/parse.c b/parse.c
index 8b7f7fd..b9671ae 100644
--- a/parse.c
+++ b/parse.c
@@ -463,7 +463,6 @@ static bool parse_type(Parser *p, Type *type, U16 flags) {
case TOKEN_IDENT:
if (!(flags & PARSE_TYPE_EXPR)) {
/* user-defined type */
- puts("user-defined type");
type->kind = TYPE_USER;
type->user.name = t->token->ident;
t->token++;
@@ -1454,7 +1453,7 @@ static bool parse_stmt(Parser *p, Statement *s) {
t->token++;
return true;
}
- s->ret.flags |= RET_FLAG_EXPR;
+ s->ret.flags |= RET_HAS_EXPR;
Token *end = expr_find_end(p, 0, NULL);
if (!end) {
while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */
@@ -1735,7 +1734,7 @@ static void fprint_stmt(FILE *out, Statement *s) {
break;
case STMT_RET:
fprintf(out, "return ");
- if (s->ret.flags & RET_FLAG_EXPR)
+ if (s->ret.flags & RET_HAS_EXPR)
fprint_expr(out, &s->ret.expr);
fprintf(out, ";\n");
break;
@@ -1747,3 +1746,13 @@ static void fprint_parsed_file(FILE *out, ParsedFile *f) {
fprint_stmt(out, stmt);
}
}
+
+static long decl_ident_index(Declaration *d, Identifier i) {
+ long idx = 0;
+ arr_foreach(d->idents, Identifier, j) {
+ if (i == *j)
+ return idx;
+ idx++;
+ }
+ return -1;
+}
diff --git a/test.toc b/test.toc
index 5cc4f17..20df7b6 100644
--- a/test.toc
+++ b/test.toc
@@ -3,30 +3,17 @@ puti @= fn(x: int) {
");
};
-putch @= fn(x: char) {
- #C("printf(\"%c\\n\", x);
-");
-};
-
-putf @= fn(x: float) {
- #C("printf(\"%f\\n\", (double)x);
-");
-};
-
Foo @= [3]int;
f @= fn() Foo {
a : Foo;
- p := &(a as [3]int)[0];
- *p = 1;
- *(p + 1) = 2;
- *(p + 2) = 3;
a
};
main @= fn() {
- foo := f();
- puti((foo as [3]int)[0]);
- puti((foo as [3]int)[1]);
- puti((foo as [3]int)[2]);
+ foo : Foo;
+ foo = f();
+ // Bar @= int;
+ // x: Bar = 18 as Bar;
+ // puti(x as int);
};
diff --git a/toc.c b/toc.c
index c25c489..62ffc0b 100644
--- a/toc.c
+++ b/toc.c
@@ -24,7 +24,10 @@
#include "scope.c"
#include "eval.c"
#include "types.c"
+static bool cgen_decls_file(CGenerator *g, ParsedFile *f);
+static bool typedefs_file(CGenerator *g, ParsedFile *f);
#include "cgen.c"
+#include "typedefs_cgen.c"
#include "decls_cgen.c"
#ifdef TOC_DEBUG
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
new file mode 100644
index 0000000..d6a3f5e
--- /dev/null
+++ b/typedefs_cgen.c
@@ -0,0 +1,143 @@
+static bool typedefs_stmt(CGenerator *g, Statement *s);
+
+static bool typedefs_block(CGenerator *g, Block *b) {
+ Block *prev = g->block;
+ if (!cgen_block_enter(g, b))
+ return false;
+ arr_foreach(b->stmts, Statement, s)
+ typedefs_stmt(g, s);
+ cgen_block_exit(g, prev);
+ return true;
+}
+
+static bool typedefs_expr(CGenerator *g, Expression *e) {
+ switch (e->kind) {
+ case EXPR_UNARY_OP:
+ if (!typedefs_expr(g, e->unary.of))
+ return false;
+ break;
+ case EXPR_BINARY_OP:
+ if (!typedefs_expr(g, e->binary.lhs)
+ || !typedefs_expr(g, e->binary.rhs))
+ return false;
+ break;
+ case EXPR_CAST:
+ if (!typedefs_expr(g, e->cast.expr))
+ return false;
+ break;
+ case EXPR_CALL:
+ if (!typedefs_expr(g, e->call.fn))
+ return false;
+ arr_foreach(e->call.arg_exprs, Expression, a)
+ if (!typedefs_expr(g, a))
+ return false;
+ break;
+ case EXPR_BLOCK:
+ if (!typedefs_block(g, &e->block))
+ return false;
+ break;
+ case EXPR_IF:
+ if (e->if_.cond)
+ if (!typedefs_expr(g, e->if_.cond))
+ return false;
+ if (!typedefs_block(g, &e->if_.body))
+ return false;
+ if (e->if_.next_elif)
+ if (!typedefs_expr(g, e->if_.next_elif))
+ return false;
+ break;
+ case EXPR_WHILE:
+ if (e->while_.cond)
+ if (!typedefs_expr(g, e->while_.cond))
+ return false;
+ if (!typedefs_block(g, &e->while_.body))
+ return false;
+ break;
+ case EXPR_TUPLE:
+ arr_foreach(e->tuple, Expression, x)
+ if (!typedefs_expr(g, x))
+ return false;
+ break;
+ case EXPR_SLICE:
+ if (!typedefs_expr(g, e->slice.of)) return false;
+ if (e->slice.from && !typedefs_expr(g, e->slice.from)) return false;
+ if (e->slice.to && !typedefs_expr(g, e->slice.to)) return false;
+ break;
+ case EXPR_FN:
+ fn_enter(&e->fn, 0);
+ if (!typedefs_block(g, &e->fn.body))
+ return false;
+ fn_exit(&e->fn);
+ break;
+ case EXPR_TYPE:
+ case EXPR_DIRECT:
+ case EXPR_NEW:
+ case EXPR_IDENT:
+ case EXPR_LITERAL_BOOL:
+ case EXPR_LITERAL_INT:
+ case EXPR_LITERAL_STR:
+ case EXPR_LITERAL_CHAR:
+ case EXPR_LITERAL_FLOAT:
+ break;
+ }
+ return true;
+
+}
+
+static bool typedefs_decl(CGenerator *g, Declaration *d) {
+ d->c.ids = NULL;
+ for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
+ Identifier i = d->idents[idx];
+ Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
+ Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[idx] : &d->val;
+ if (type->kind == TYPE_TYPE) {
+ /* generate typedef */
+ cgen_write(g, "typedef ");
+ if (!cgen_type_pre(g, val->type, d->where)) return false;
+ cgen_write(g, " ");
+ /* can we use the name directly? */
+ if (!d->c.ids)
+ d->c.ids = evalr_calloc(g->evalr, arr_len(d->idents), sizeof *d->c.ids);
+ if (g->block == NULL) {
+ d->c.ids[idx] = 0; /* yes! */
+ cgen_ident(g, i);
+ } else {
+ cgen_ident_id(g, d->c.ids[idx] = g->ident_counter++); /* no ): */
+ }
+ if (!cgen_type_post(g, val->type, d->where)) return false;
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ }
+ if (d->flags & DECL_FLAG_HAS_EXPR)
+ if (!typedefs_expr(g, &d->expr))
+ return false;
+ return true;
+}
+
+static bool typedefs_stmt(CGenerator *g, Statement *s) {
+ switch (s->kind) {
+ case STMT_DECL:
+ if (!typedefs_decl(g, &s->decl))
+ return false;
+ break;
+ case STMT_EXPR:
+ if (!typedefs_expr(g, &s->expr))
+ return false;
+ break;
+ case STMT_RET:
+ if (s->ret.flags & RET_HAS_EXPR)
+ if (!typedefs_expr(g, &s->ret.expr))
+ return false;
+ break;
+ }
+ return true;
+}
+
+static bool typedefs_file(CGenerator *g, ParsedFile *f) {
+ arr_foreach(f->stmts, Statement, s) {
+ if (!typedefs_stmt(g, s))
+ return false;
+ }
+ return true;
+}
diff --git a/types.c b/types.c
index a03a476..76f5101 100644
--- a/types.c
+++ b/types.c
@@ -1147,24 +1147,30 @@ static bool types_decl(Typer *tr, Declaration *d) {
}
if ((d->flags & DECL_FLAG_CONST) || tr->block == NULL) {
if (!(d->flags & DECL_FLAG_FOUND_VAL)) {
- if (!eval_expr(tr->evalr, &d->expr, &d->val))
- return false;
+ if (!eval_expr(tr->evalr, &d->expr, &d->val)) {
+ success = false;
+ goto ret;
+ }
d->flags |= DECL_FLAG_FOUND_VAL;
}
}
- if (d->type.kind == TYPE_TUPLE) {
- arr_foreach(d->type.tuple, Type, t) {
- if (t->kind == TYPE_TYPE && !(d->flags & DECL_FLAG_CONST)) {
+ for (size_t i = 0; i < arr_len(d->idents); i++) {
+ Type *t = d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type;
+ Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[i] : &d->val;
+ if (t->kind == TYPE_TYPE) {
+ if (!(d->flags & DECL_FLAG_CONST)) {
err_print(d->where, "Cannot declare non-constant type.");
- return false;
+ success = false;
+ goto ret;
+ }
+ if (!type_resolve(tr, val->type)) {
+ success = false;
+ goto ret;
}
- }
- } else {
- if (d->type.kind == TYPE_TYPE && !(d->flags & DECL_FLAG_CONST)) {
- err_print(d->where, "Cannot declare non-constant type.");
- return false;
}
}
+
+
}
size_t n_idents = arr_len(d->idents);
if (d->type.kind == TYPE_TUPLE) {
@@ -1206,7 +1212,7 @@ static bool types_stmt(Typer *tr, Statement *s) {
err_print(s->where, "return outside of a function.");
return false;
}
- if (s->ret.flags & RET_FLAG_EXPR) {
+ if (s->ret.flags & RET_HAS_EXPR) {
if (tr->ret_type.kind == TYPE_VOID) {
err_print(s->where, "Return value in function which should not return a value.");
return false;
diff --git a/types.h b/types.h
index f7e0658..573d5c9 100644
--- a/types.h
+++ b/types.h
@@ -113,7 +113,6 @@ root.children[low part of 1st char].children[high part of 1st char]
typedef struct IdentTree {
/* zero value is an empty trie */
uint16_t depth;
- uint16_t flags;
unsigned char index_in_parent; /* index of this in .parent.children */
struct IdentTree *parent;
struct IdentTree *children[TREE_NCHILDREN];
@@ -364,6 +363,9 @@ typedef struct {
struct Argument *args;
struct Expression *arg_exprs;
};
+ struct {
+ IdentID id;
+ } c;
} CallExpr;
typedef struct {
@@ -480,6 +482,10 @@ typedef struct Declaration {
uint16_t flags;
Expression expr;
Value val; /* only for constant decls. */
+
+ struct {
+ IdentID *ids; /* array of IDs used in place of ident names. unfortunately needed for user defined types. this is NOT a dynamic array, but is of length arr_len(idents). */
+ } c;
} Declaration;
typedef enum {
@@ -488,7 +494,7 @@ typedef enum {
STMT_RET
} StatementKind;
-#define RET_FLAG_EXPR 0x01
+#define RET_HAS_EXPR 0x01
typedef struct {
uint16_t flags;
Expression expr;