diff options
-rw-r--r-- | archive/arr.c | 69 | ||||
-rw-r--r-- | archive/base_cgen.c | 295 | ||||
-rw-r--r-- | archive/cgen.c | 463 | ||||
-rw-r--r-- | archive/decls_cgen.c | 106 | ||||
-rw-r--r-- | cgen.c | 28 | ||||
-rw-r--r-- | decls_cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 30 | ||||
-rw-r--r-- | identifiers.c | 4 | ||||
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | parse.c | 34 | ||||
-rw-r--r-- | scope.c | 6 | ||||
-rw-r--r-- | toc.c | 4 | ||||
-rw-r--r-- | typedefs_cgen.c | 2 | ||||
-rw-r--r-- | types.c | 94 | ||||
-rw-r--r-- | types.h | 27 |
15 files changed, 118 insertions, 1051 deletions
diff --git a/archive/arr.c b/archive/arr.c deleted file mode 100644 index 2a055b1..0000000 --- a/archive/arr.c +++ /dev/null @@ -1,69 +0,0 @@ - -static void arr_create(Array *arr, size_t item_sz) { - arr->len = arr->cap = 0; - arr->item_sz = item_sz; - arr->data = NULL; -} - -static inline void arr_reserve(Array *arr, size_t n) { - arr->cap = n; - arr->data = err_realloc(arr->data, arr->item_sz * arr->cap); -} - -static inline void arr_reservea(Array *arr, size_t n, Allocator *a) { - arr->cap = n; - arr->data = allocr_realloc(a, arr->data, arr->item_sz * arr->cap); -} - -/* like arr_reserve, but sets the length of the array too */ -static inline void arr_set_len(Array *arr, size_t n) { - arr_reserve(arr, n); - arr->len = n; -} - -static inline void arr_set_lena(Array *arr, size_t n, Allocator *a) { - arr_reservea(arr, n, a); - arr->len = n; -} - -static inline void *arr_last(Array *arr) { - if (arr->data) - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); - else - return NULL; -} - -static void *arr_add(Array *arr) { - if (arr->len >= arr->cap) { - arr_reserve(arr, (arr->cap + 1) * 2); - } - arr->len++; - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); -} - -static void *arr_adda(Array *arr, Allocator *a) { - if (arr->len >= arr->cap) { - arr_reservea(arr, (arr->cap + 1) * 2, a); - } - arr->len++; - return (void*)((char*)arr->data + arr->item_sz * (arr->len - 1)); -} - -static void arr_clear(Array *arr) { - free(arr->data); - arr->len = arr->cap = 0; - arr->data = NULL; -} - -static void arr_remove_last(Array *arr) { - /* OPTIM (memory): Shorten array. */ - arr->len--; -} - -static void arr_free(Array *arr) { - free(arr->data); -} - -/* NOTE: this will not work if type is a pointer! */ -#define arr_foreach(arr, type, var) for (type *var = (arr)->data, *var##_foreach_last = arr_last(arr); var; var == var##_foreach_last ? var = NULL : var++) -#define arr_foreach_reverse(arr, type, var) for (type *var = arr_last(arr); var; var == (arr)->data ? var = NULL : var--) diff --git a/archive/base_cgen.c b/archive/base_cgen.c deleted file mode 100644 index d773ba9..0000000 --- a/archive/base_cgen.c +++ /dev/null @@ -1,295 +0,0 @@ -/* figures out types and writes function prototypes */ -/* TODO: check ferror */ -typedef enum { - CGEN_WRITING_TO_H, - CGEN_WRITING_TO_C -} CGenWritingTo; -typedef struct { - FILE *c_out; - FILE *h_out; - unsigned long anon_fn_count; - unsigned long anon_var_count; - Block *block; - int indent_level; - bool indent_next; /* should the next thing written be indented? */ - CGenWritingTo writing_to; - Identifier main_ident; -} CGenerator; - -static FILE *cgen_writing_to(CGenerator *g) { - switch (g->writing_to) { - case CGEN_WRITING_TO_H: - return g->h_out; - case CGEN_WRITING_TO_C: - return g->c_out; - } - assert(0); - return NULL; -} - -static void cgen_indent(CGenerator *g) { - if (g->indent_next) { - for (int i = 0; i < g->indent_level; i++) - fprintf(cgen_writing_to(g), "\t"); - g->indent_next = false; - } -} - -static void cgen_vwrite(CGenerator *g, const char *fmt, va_list args) { - cgen_indent(g); - vfprintf(cgen_writing_to(g), fmt, args); -} - -static void cgen_write(CGenerator *g, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); -} - -/* Used to write an UNNECESSARY space */ -static void cgen_space(CGenerator *g) { - cgen_write(g, " "); -} - -/* Used to write something followed by an UNNECESSARY newline */ -static void cgen_writeln(CGenerator *g, const char *fmt, ...) { - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); - cgen_write(g, "\n"); - g->indent_next = true; -} - -/* static void cgen_write_comment(CGenerator *g, const char *fmt, ...) { */ -/* cgen_write(g, "/\* "); */ -/* va_list args; */ -/* va_start(args, fmt); */ -/* cgen_vwrite(g, fmt, args); */ -/* va_end(args); */ -/* cgen_write(g, " *\/"); */ -/* } */ - -static void cgen_write_line_comment(CGenerator *g, const char *fmt, ...) { - /* could switch to // for c99 */ - cgen_write(g, "/* "); - va_list args; - va_start(args, fmt); - cgen_vwrite(g, fmt, args); - va_end(args); - cgen_write(g, " */\n"); -} - - -/* Pass NULL for where if you don't want to check if it's declared */ -static bool cgen_fn_name(CGenerator *g, FnExpr *f, Location *where); -static bool cgen_ident(CGenerator *g, Identifier i, Location *where) { - if (where) { - IdentDecl *id_decl = ident_decl(i); - if (!id_decl) { - err_print(*where, "Identifier undeclared: %s", ident_to_str(i)); - return false; - } - Declaration *decl = id_decl->decl; - if ((decl->flags & DECL_FLAG_HAS_EXPR) && (decl->flags & DECL_FLAG_CONST)) { - if (decl->expr.kind == EXPR_FN) { - cgen_fn_name(g, decl->expr.fn, NULL); - return true; - } - } - } - cgen_indent(g); - fprint_ident_reduced_charset(cgen_writing_to(g), i); - return true; -} - -static const char *builtin_type_to_str(BuiltinType b) { - /* TODO: make this return int/long/etc. if stdint.h is not available */ - switch (b) { - case BUILTIN_I8: return "int8_t"; - case BUILTIN_I16: return "int16_t"; - case BUILTIN_I32: return "int32_t"; - case BUILTIN_I64: return "int64_t"; - case BUILTIN_U8: return "uint8_t"; - case BUILTIN_U16: return "uint16_t"; - case BUILTIN_U32: return "uint32_t"; - case BUILTIN_U64: return "uint64_t"; - case BUILTIN_FLOAT: return "float"; - case BUILTIN_DOUBLE: return "double"; - case BUILTIN_TYPE_COUNT: break; - } - assert(0); - return NULL; -} - -/* will this function use a pointer parameter for output? (e.g. fn()[3]int => void(int (*x)[3]) */ -static bool cgen_fn_uses_out_param(Type *fn_ret_type) { - switch (fn_ret_type->kind) { - case TYPE_TUPLE: - case TYPE_ARR: - return true; - default: - return false; - } -} - - -static void cgen_anon_var(CGenerator *g, unsigned long v) { - cgen_write(g, "av___%lu", v); -} - -static void cgen_anon_fn(CGenerator *g, unsigned long f) { - cgen_write(g, "af___%lu", f); -} - -static void cgen_type_pre(CGenerator *g, Type *t) { - switch (t->kind) { - case TYPE_VOID: - cgen_write(g, "void "); - break; - case TYPE_BUILTIN: - cgen_write(g, "%s ", builtin_type_to_str(t->builtin)); - break; - case TYPE_FN: { - Type *types = t->fn.types.data; - Type *ret_type = &types[0]; - if (cgen_fn_uses_out_param(ret_type)) { - cgen_write(g, "void "); - } else { - cgen_type_pre(g, ret_type); - } - cgen_write(g, "(*"); - } break; - case TYPE_TUPLE: - assert(0); - return; - case TYPE_UNKNOWN: - err_print(t->where, "Type of unknown-typed expression required (x := #C(\"...\") will not work; you need to annotate the type of x)."); - abort(); - case TYPE_ARR: - cgen_type_pre(g, t->arr.of); - break; - } -} - -static void cgen_type_post(CGenerator *g, Type *t); -/* either pass NULL for param_types (x)or for params */ -static void cgen_fn_params(CGenerator *g, Type *param_types, Param *params, size_t nparams, Type *ret_type) { - bool uses_out_param = cgen_fn_uses_out_param(ret_type); - - cgen_write(g, "("); - if (nparams) { - for (size_t i = 0; i < nparams; i++) { - if (i) { - cgen_write(g, ","); - cgen_space(g); - } - if (param_types) { - cgen_type_pre(g, ¶m_types[i]); - cgen_type_post(g, ¶m_types[i]); - } else { - Param *p = ¶ms[i]; - cgen_type_pre(g, &p->type); - cgen_ident(g, p->name, NULL); - cgen_type_post(g, &p->type); - } - } - } else { - if (!uses_out_param) - cgen_write(g, "void"); - } - if (uses_out_param) { - if (nparams) { - cgen_write(g, ","); - cgen_space(g); - } - /* write out param */ - cgen_type_pre(g, ret_type); - cgen_write(g, "(*out__)"); /* TODO: fix this for named return values */ - cgen_type_post(g, ret_type); - - } - cgen_write(g, ")"); -} - -static void cgen_type_post(CGenerator *g, Type *t) { - switch (t->kind) { - case TYPE_VOID: - case TYPE_BUILTIN: - break; - case TYPE_FN: { - Type *types = t->fn.types.data; - Type *ret_type = &types[0]; - Type *param_types = types + 1; - assert(t->fn.types.len > 0); - size_t nparams = t->fn.types.len-1; - bool uses_out_param = cgen_fn_uses_out_param(ret_type); - cgen_write(g, ")"); - cgen_fn_params(g, param_types, NULL, nparams, ret_type); - if (!uses_out_param) { - cgen_type_post(g, ret_type); - } - cgen_space(g); - } break; - case TYPE_TUPLE: - assert(0); - return; - case TYPE_ARR: - cgen_write(g, "[%lu]", t->arr.n); - cgen_type_post(g, t->arr.of); - break; - case TYPE_UNKNOWN: /* we should always do pre first */ - assert(0); - break; - } -} - -static bool cgen_fn_name(CGenerator *g, FnExpr *f, Location *where) { - if (f->name) { - /* TODO: check block */ - if (f->name == g->main_ident) { - cgen_write(g, "main__"); - return true; - } else { - return cgen_ident(g, f->name, where); - } - } else { - cgen_anon_fn(g, f->id); - return true; - } -} - -static bool cgen_fn_header(CGenerator *g, FnExpr *f) { - if (!f->name || g->block != NULL) { - cgen_write(g, "static "); /* anonymous functions only exist in this translation unit */ - } - - bool uses_out_param = cgen_fn_uses_out_param(&f->ret_type); - size_t nparams = f->params.len; - if (uses_out_param) { - cgen_write(g, "void "); - cgen_fn_name(g, f, NULL); - cgen_fn_params(g, NULL, (Param*)f->params.data, nparams, &f->ret_type); - - } else { - cgen_type_pre(g, &f->ret_type); - cgen_fn_name(g, f, NULL); - cgen_fn_params(g, NULL, (Param*)f->params.data, nparams, &f->ret_type); - cgen_type_post(g, &f->ret_type); - } - - return true; -} - -static bool cgen_block_enter(CGenerator *g, Block *b) { - g->block = b; - return block_enter(b, &b->stmts); -} - -static bool cgen_block_exit(CGenerator *g, Block *into) { - Block *b = g->block; - g->block = into; - return block_exit(b, &b->stmts); -} - diff --git a/archive/cgen.c b/archive/cgen.c deleted file mode 100644 index 7ff2308..0000000 --- a/archive/cgen.c +++ /dev/null @@ -1,463 +0,0 @@ -static void cgen_create(CGenerator *g, Identifiers *ids, FILE *c_out, FILE *h_out, const char *h_filename) { - g->c_out = c_out; - g->h_out = h_out; - g->anon_fn_count = 0; - g->anon_var_count = 0; - g->indent_level = 0; - g->block = NULL; - g->indent_next = true; - g->main_ident = ident_get(ids, "main"); - - g->writing_to = CGEN_WRITING_TO_H; - cgen_write(g, "#include <stddef.h>\n" - "#include <stdint.h>\n" - "#include <string.h>\n"); - - g->writing_to = CGEN_WRITING_TO_C; - cgen_write(g, "#include \"%s\"\n", h_filename); - cgen_writeln(g, ""); /* extra newline between includes and code */ -} - -static bool cgen_direct(CGenerator *g, DirectExpr *direct, Location where) { - switch (direct->which) { - case DIRECT_C: { - Expression *args = direct->args.data; - size_t nargs = direct->args.len; - if (nargs != 1) { - err_print(where, "Expected 1 argument to #C directive, but got %lu.", nargs); - } - /* TODO: compile-time constants */ - if (args[0].kind != EXPR_STR_LITERAL) { - err_print(args[0].where, "Argument to #C directive must be a string literal."); - } - cgen_write(g, "%s", args[0].strl.str); - } break; - case DIRECT_COUNT: - assert(0); - return false; - } - return true; -} - - -/* generates C statements which must go before an expression. */ -static bool cgen_expr_pre(CGenerator *g, Expression *e) { - switch (e->kind) { - case EXPR_BINARY_OP: - if (!cgen_expr_pre(g, e->binary.lhs)) return false; - if (!cgen_expr_pre(g, e->binary.rhs)) return false; - /* TODO(eventually): Short-circuiting operators will need some work */ - break; - case EXPR_UNARY_OP: - if (!cgen_expr_pre(g, e->unary.of)) return false; - break; - case EXPR_CALL: { - if (!cgen_expr_pre(g, e->call.fn)) return false; - arr_foreach(&e->call.args, Expression, arg) - if (!cgen_expr_pre(g, arg)) - return false; - Type *fn_types = e->call.fn->type.fn.types.data; - Type *ret_type = &fn_types[0]; - if (cgen_fn_uses_out_param(ret_type)) { - /* generate out call */ - e->call.out_var = g->anon_var_count++; - - /* declaration of out variable */ - cgen_type_pre(g, ret_type); - cgen_anon_var(g, e->call.out_var); - cgen_type_post(g, ret_type); - cgen_writeln(g, ";"); - - cgen_expr(g, e->call.fn); - - cgen_write(g, "("); - arr_foreach(&e->call.args, Expression, arg) { - if (arg != e->call.args.data) { - cgen_write(g, ","); - cgen_space(g); - } - if (!cgen_expr(g, arg)) return false; - } - if (e->call.args.len) { - cgen_write(g, ","); - cgen_space(g); - } - cgen_write(g, "&"); - cgen_anon_var(g, e->call.out_var); - cgen_writeln(g, ");"); - } - } break; - default: break; - } - return true; -} - -static bool cgen_expr(CGenerator *g, Expression *e) { - switch (e->kind) { - case EXPR_INT_LITERAL: - cgen_write(g, "%lld", e->intl); - break; - case EXPR_FLOAT_LITERAL: - /* TODO: more precision */ - cgen_write(g, "%f", (double)e->floatl); - break; - case EXPR_STR_LITERAL: - cgen_write(g, "\""); - /* OPTIM: Maybe don't use i? this will probably be optimized by the compiler though... */ - for (size_t i = 0; i < e->strl.len; i++) { - /* TODO: Print ordinary characters nicely */ - cgen_write(g, "\\x%02x", e->strl.str[i]); - } - cgen_write(g, "\""); - break; - case EXPR_IDENT: - if (!cgen_ident(g, e->ident, &e->where)) return false; - break; - case EXPR_BINARY_OP: - cgen_write(g, "("); - if (!cgen_expr(g, e->binary.lhs)) return false; - switch (e->binary.op) { - case BINARY_PLUS: - cgen_write(g, "+"); - break; - case BINARY_MINUS: - cgen_write(g, "-"); - break; - case BINARY_SET: - cgen_write(g, "="); - break; - case BINARY_AT_INDEX: - cgen_write(g, "["); - break; - case BINARY_COMMA: - assert(0); - return false; - } - if (!cgen_expr(g, e->binary.rhs)) return false; - if (e->binary.op == BINARY_AT_INDEX) { - cgen_write(g, "]"); - } - cgen_write(g, ")"); - break; - case EXPR_UNARY_OP: - cgen_write(g, "("); - switch (e->unary.op) { - case UNARY_MINUS: - cgen_write(g, "-"); - break; - } - if (!cgen_expr(g, e->unary.of)) return false; - cgen_write(g, ")"); - break; - case EXPR_FN: - if (!cgen_fn_name(g, &e->fn, &e->where)) return false; - break; - case EXPR_CALL: { - Type *fn_types = e->call.fn->type.fn.types.data; - Type *ret_type = &fn_types[0]; - if (cgen_fn_uses_out_param(ret_type)) { /* if there's an out parameter, */ - cgen_anon_var(g, e->call.out_var); /* just use the variable we made earlier */ - } else { - if (!cgen_expr(g, e->call.fn)) return false; - cgen_write(g, "("); - arr_foreach(&e->call.args, Expression, arg) { - if (arg != e->call.args.data) { - cgen_write(g, ","); - cgen_space(g); - } - if (!cgen_expr(g, arg)) return false; - } - cgen_write(g, ")"); - } - } break; - case EXPR_DIRECT: - if (!cgen_direct(g, &e->direct, e->where)) return false; - break; - } - return true; -} - -static bool cgen_stmt(CGenerator *g, Statement *s); - -static void cgen_zero_value(CGenerator *g, Type *t) { - switch (t->kind) { - case TYPE_VOID: /* we should never need this */ - assert(0); - break; - case TYPE_FN: - cgen_write(g, "NULL"); - break; - case TYPE_ARR: - cgen_write(g, "{"); - cgen_zero_value(g, t->arr.of); - cgen_write(g, "}"); - break; - case TYPE_TUPLE: - assert(0); - break; - case TYPE_BUILTIN: - if (type_builtin_is_numerical(t->builtin)) { - cgen_write(g, "0"); - } else { - assert(0); - } - break; - case TYPE_UNKNOWN: - assert(0); - break; - } -} - -static bool cgen_decl(CGenerator *g, Declaration *d) { - size_t i = d->idents.len; - if (d->flags & DECL_FLAG_HAS_EXPR) { - if (!cgen_expr_pre(g, &d->expr)) - return false; - } - /* because , is left-associative, we want to go backwards */ - arr_foreach_reverse(&d->idents, Identifier, ident) { - Type *type; - if (d->idents.len > 1) { - /* it's a tuple! */ - type = &(((Type*)d->type.tuple.data)[--i]); - } else { - type = &d->type; - if (type->kind == TYPE_TUPLE) { - /* TODO */ - err_print(d->where, "Direct declaration of tuples is not supported yet."); - return false; - } - } - if (type->kind == TYPE_ARR) { - /* if you do a : [3]int; translates into int64_t av___23[3] = {0}; int64_t *a = av___23; */ - int has_expr = d->flags & DECL_FLAG_HAS_EXPR; - unsigned long var; - if (!has_expr) { - /* int64_t av___23[3] = {0}; */ - var = g->anon_var_count++; - cgen_type_pre(g, type); - cgen_anon_var(g, var); - cgen_type_post(g, type); - cgen_space(g); - cgen_write(g, "="); - cgen_space(g); - cgen_zero_value(g, type); - cgen_writeln(g, ";"); - } - /* int64_t *a = av___23; */ - cgen_type_pre(g, type->arr.of); - cgen_write(g, "(*"); - cgen_ident(g, *ident, NULL); - cgen_write(g, ")"); - cgen_type_post(g, type->arr.of); - cgen_space(g); - cgen_write(g, "="); - cgen_space(g); - if (has_expr) { - if (!cgen_expr(g, &d->expr)) return false; - } else { - cgen_anon_var(g, var); - } - cgen_writeln(g, ";"); - return true; - } - - cgen_type_pre(g, type); - if (d->flags & DECL_FLAG_CONST) { /* TODO: remove this (never actually produce constants) */ - cgen_space(g); - cgen_write(g, "const"); - cgen_space(g); - } - cgen_ident(g, *ident, NULL); - cgen_type_post(g, type); - cgen_space(g); - cgen_write(g, "="); - cgen_space(g); - if (d->flags & DECL_FLAG_HAS_EXPR) { - Expression *expr = &d->expr; - if (d->idents.len > 1) { - if (expr->kind == EXPR_BINARY_OP && expr->binary.op == BINARY_COMMA) { - if (!cgen_expr(g, expr->binary.rhs)) return false; - expr = expr->binary.lhs; /* ((3,4),5),6 => (3,4),5 */ - } else { - /* last iteration */ - if (!cgen_expr(g, expr)) return false; - } - - } else { - if (!cgen_expr(g, expr)) return false; - } - } else { - cgen_zero_value(g, type); - } - cgen_write(g, "; "); - } - cgen_writeln(g, ""); - return true; -} - -static bool cgen_stmt(CGenerator *g, Statement *s) { - switch (s->kind) { - case STMT_EXPR: - if (!cgen_expr(g, &s->expr)) - return false; - cgen_writeln(g, ";"); - break; - case STMT_DECL: { - Declaration *d = &s->decl; - if ((d->flags & DECL_FLAG_HAS_EXPR) && (d->flags & DECL_FLAG_CONST)) - if (d->expr.kind == EXPR_FN) - return true; /* already dealt with below */ - - return cgen_decl(g, &s->decl); - } - } - return true; -} - -static bool cgen_fns_in_stmt(CGenerator *g, Statement *s); - -typedef struct { - bool is_return; /* true => this is a function return */ - unsigned long var_no; /* if is_return = false, set the anonymous variable with this number to the return value. */ - const char *exit_with; /* how to exit this block in C, e.g. "break" (not needed if is_return = true). */ -} BlockExitKind; - -/* generates a block but not the functions, etc. inside it */ -static bool cgen_block(CGenerator *g, Block *b, BlockExitKind *exit_kind) { - bool success = true; - cgen_writeln(g, "{"); - g->indent_level++; - arr_foreach(&b->stmts, Statement, s) { - if (!cgen_stmt(g, s)) - success = false; - } - if (exit_kind->is_return) { - /* generate return from function */ - Expression *ret = b->ret_expr; - if (ret && cgen_fn_uses_out_param(&ret->type)) { - if (ret->type.kind == TYPE_ARR) { - /* returning possibly multi-dimensional arrays */ - size_t total_size = 1; /* product of all dimensions */ - Type *type; - for (type = &ret->type; type->kind == TYPE_ARR; type = type->arr.of) - total_size *= type->arr.n; - /* type is now the base type of the array, e.g. [3][3][3]fn() => fn() */ - cgen_write(g, "memcpy(*out__, "); - if (!cgen_expr(g, b->ret_expr)) return false; - cgen_write(g, ", %lu * sizeof(", total_size); - cgen_type_pre(g, type); - cgen_type_post(g, type); - cgen_writeln(g, ")); return;"); - } else { - cgen_write(g, "*out__ = "); - if (!cgen_expr(g, b->ret_expr)) return false; - cgen_writeln(g, ";"); - cgen_writeln(g, "return;"); - } - } else { - cgen_write(g, "return"); - if (b->ret_expr) { - cgen_write(g, " "); - if (!cgen_expr(g, b->ret_expr)) return false; - } - cgen_writeln(g, ";"); - } - } else { - err_print(b->ret_expr->where, "TODO"); - return false; - } - if (success) { - g->indent_level--; - cgen_writeln(g, "}"); - } - return success; -} - -/* Generates function definition, and the definitions of all functions inside this */ -static bool cgen_fn(CGenerator *g, FnExpr *f) { - if (!cgen_fn_header(g, f)) return false; - Block *prev_block = g->block; - cgen_block_enter(g, &f->body); - cgen_space(g); - BlockExitKind e_kind; - e_kind.is_return = 1; - if (!cgen_block(g, &f->body, &e_kind)) return false; - - bool ret = true; - arr_foreach(&f->body.stmts, Statement, stmt) { - if (!cgen_fns_in_stmt(g, stmt)) ret = false; - } - cgen_block_exit(g, prev_block); - return ret; -} - -static bool cgen_fns_in_expr(CGenerator *g, Expression *e) { - switch (e->kind) { - case EXPR_FN: - return cgen_fn(g, &e->fn); - case EXPR_CALL: - return cgen_fns_in_expr(g, e->call.fn); - default: return true; - } -} - -static bool cgen_fns_in_stmt(CGenerator *g, Statement *s) { - switch (s->kind) { - case STMT_EXPR: - if (s->expr.kind == EXPR_FN) { - warn_print(s->where, "Statement of function has no effect (try assigning the function to a variable)."); - } else { - return cgen_fns_in_expr(g, &s->expr); - } - break; - case STMT_DECL: { - Declaration *d = &s->decl; - if (d->flags & DECL_FLAG_HAS_EXPR) - return cgen_fns_in_expr(g, &d->expr); - } break; - } - return true; -} - -/* generate a statement at top level, including any functions in it. */ -static bool cgen_stmt_top(CGenerator *g, Statement *s) { - if (!cgen_fns_in_stmt(g, s)) return false; - switch (s->kind) { - case STMT_EXPR: { - Expression *e = &s->expr; - bool ignored = true; - switch (e->kind) { - case EXPR_DIRECT: - switch (e->direct.which) { - case DIRECT_C: - ignored = false; - cgen_direct(g, &e->direct, e->where); - break; - case DIRECT_COUNT: assert(0); break; - } - default: break; - } - if (ignored) - warn_print(e->where, "Expression at top level currently ignored."); /* TODO */ - } break; - case STMT_DECL: break; - } - return true; -} - -static bool cgen_file(CGenerator *g, ParsedFile *f) { - cgen_write_line_comment(g, "toc"); - bool ret = true; - if (!cgen_decls_file(g, f)) return false; - arr_foreach(&f->stmts, Statement, s) { - if (!cgen_stmt_top(g, s)) return false; - } - g->writing_to = CGEN_WRITING_TO_C; - /* write actual main function */ - cgen_write(g, "\nint main(void) {\n" - "\tmain__();\n" - "\treturn 0;\n" - "}\n"); - return ret; -} diff --git a/archive/decls_cgen.c b/archive/decls_cgen.c deleted file mode 100644 index a596f53..0000000 --- a/archive/decls_cgen.c +++ /dev/null @@ -1,106 +0,0 @@ -/* C declarations of functions and global variables. e must be a function expression */ -static bool cgen_decl_fn(CGenerator *g, FnExpr *f) { - /* assign an ID to the function */ - if (f->name && g->block == NULL) { - f->id = f->name->c_fn_reps++; - } else { - f->id = g->anon_fn_count++; - } - - if (!cgen_fn_header(g, f)) return false; - cgen_writeln(g, ";"); - return true; -} - -static bool cgen_decls_stmt(CGenerator *g, Statement *s); - -static bool cgen_decls_expr(CGenerator *g, Expression *e) { - switch (e->kind) { - case EXPR_FN: { - FnExpr *f = &e->fn; - if (f->name && g->block == NULL) { /* write named function prototypes in global scope to header file */ - g->writing_to = CGEN_WRITING_TO_H; - } else { - g->writing_to = CGEN_WRITING_TO_C; - } - if (!cgen_decl_fn(g, f)) - return false; - g->writing_to = CGEN_WRITING_TO_C; - - - bool ret = true; - Block *prev_block = g->block; - cgen_block_enter(g, &f->body); - arr_foreach(&f->body.stmts, Statement, s) { - if (!cgen_decls_stmt(g, s)) - ret = false; - } - cgen_block_exit(g, prev_block); - return ret; - } - case EXPR_CALL: - if (!cgen_decls_expr(g, e->call.fn)) - return false; - arr_foreach(&e->call.args, Expression, arg) { - if (!cgen_decls_expr(g, arg)) - return false; - } - break; - default: break; - } - return true; -} - - -static bool cgen_expr(CGenerator *g, Expression *e); -static bool cgen_decls_stmt(CGenerator *g, Statement *s) { - switch (s->kind) { - case STMT_EXPR: - return cgen_decls_expr(g, &s->expr); - case STMT_DECL: { - Declaration *d = &s->decl; - bool is_const_fn = (d->flags & DECL_FLAG_HAS_EXPR) && (d->flags & DECL_FLAG_CONST) - && d->expr.kind == EXPR_FN; - - if (is_const_fn) { - /* e.g. foo @= fn() {}; (we want to set the function's name to "foo") */ - d->expr.fn.name = *(Identifier*)d->idents.data; - } - - if (d->flags & DECL_FLAG_HAS_EXPR) { - cgen_decls_expr(g, &d->expr); - } - - if (!is_const_fn) { - if (g->block == NULL) { - /* declare this/these global variable(s) */ - arr_foreach(&d->idents, Identifier, i) { - cgen_type_pre(g, &d->type); - cgen_ident(g, *i, NULL); - cgen_type_post(g, &d->type); - if (d->flags & DECL_FLAG_HAS_EXPR) { /* TODO: check if expr is const */ - cgen_space(g); - cgen_write(g, "="); - cgen_space(g); - if (!cgen_expr(g, &d->expr)) - return false; - } - cgen_write(g, ";"); - cgen_space(g); - } - cgen_writeln(g, ""); - } - } - - } break; - } - return true; -} - -static bool cgen_decls_file(CGenerator *g, ParsedFile *f) { - arr_foreach(&f->stmts, Statement, s) { - if (!cgen_decls_stmt(g, s)) - return false; - } - return true; -} @@ -187,7 +187,7 @@ static void cgen_ident_id(CGenerator *g, IdentID id) { /* should declaration be a direct function declaration C (as opposed to using a function pointer or not being a function) */ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) { - return g->block == NULL && (d->flags & DECL_FLAG_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1; + return g->block == NULL && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1; } static bool cgen_uses_ptr(Type *t) { @@ -239,7 +239,7 @@ static inline Identifier cgen_ident_id_to_ident(CGenerator *g, IdentID id) { } static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { - assert(t->flags & TYPE_FLAG_RESOLVED); + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: switch (t->builtin) { @@ -334,7 +334,7 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) { return false; break; case TYPE_ARR: - assert(t->flags & TYPE_FLAG_RESOLVED); + assert(t->flags & TYPE_IS_RESOLVED); cgen_write(g, "[%lu])", (unsigned long)t->arr.n); if (!cgen_type_post(g, t->arr.of, where)) return false; @@ -655,7 +655,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, /* generates the C code for new'ing a slice of array type t (e.g. [5]int) and putting it in the given ident id. */ static bool cgen_new_slice(CGenerator *g, Type *t, IdentID id, Location where) { Expression *n_expr = t->arr.n_expr; - assert(!(t->flags & TYPE_FLAG_RESOLVED)); /* we don't want this to be resolved, because the size might only be known at runtime. */ + assert(!(t->flags & TYPE_IS_RESOLVED)); /* we don't want this to be resolved, because the size might only be known at runtime. */ if (!cgen_expr_pre(g, n_expr)) return false; cgen_write(g, "size_t s"); cgen_ident_id(g, id); @@ -805,7 +805,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { if (!cgen_type_post(g, &ea->type, e->where)) return false; cgen_write(g, "; "); Expression val_expr; - val_expr.flags = EXPR_FLAG_FOUND_TYPE; + val_expr.flags = EXPR_FOUND_TYPE; val_expr.kind = EXPR_IDENT; val_expr.ident = ea->value; val_expr.type = ea->type; @@ -944,7 +944,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) { set_expr.kind = EXPR_IDENT; set_expr.ident = ea->value; set_expr.type = ea->type; - set_expr.flags = EXPR_FLAG_FOUND_TYPE; + set_expr.flags = EXPR_FOUND_TYPE; if (!cgen_set(g, &set_expr, NULL, NULL, "(*p_)")) return false; @@ -1581,11 +1581,11 @@ static bool cgen_val(CGenerator *g, Value *v, Type *t, Location where) { static bool cgen_decl(CGenerator *g, Declaration *d) { - int has_expr = d->flags & DECL_FLAG_HAS_EXPR; + int has_expr = d->flags & DECL_HAS_EXPR; bool is_tuple = d->type.kind == TYPE_TUPLE; if (cgen_fn_is_direct(g, d)) { /* definition already generated by cgen_defs_decl */ - } else if ((d->flags & DECL_FLAG_CONST) || g->block == NULL) { + } else if ((d->flags & DECL_IS_CONST) || g->block == NULL) { /* declarations where we use a value */ for (size_t idx = 0; idx < arr_len(d->idents); idx++) { Identifier i = d->idents[idx]; @@ -1743,7 +1743,7 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d) { if (!cgen_defs_block(g, &d->expr.fn.body)) return false; } else { - if (d->flags & DECL_FLAG_HAS_EXPR) { + if (d->flags & DECL_HAS_EXPR) { if (!cgen_defs_expr(g, &d->expr)) return false; } @@ -1782,6 +1782,10 @@ static bool cgen_defs_block(CGenerator *g, Block *b) { static bool cgen_file(CGenerator *g, ParsedFile *f) { g->block = NULL; g->file = f; + /* + TODO: to improve compile times, don't include stdlib.h + (you can even get away with not including stdio.h with posix file descriptors) + */ cgen_write(g, "#include <stdint.h>\n" "#include <stdlib.h>\n" "#include <stdio.h>\n" @@ -1797,10 +1801,10 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) { "typedef double f64;\n" "typedef u8 bool;\n" "typedef struct { void *data; i64 n; } slice_;\n" - "static slice_ mkslice_(void *data, i64 n) { slice_ ret; ret.data = data; ret.n = n; return ret; }\n" - "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"); + "#define true ((bool)1)\n" + "static inline slice_ mkslice_(void *data, i64 n) { slice_ ret; ret.data = data; ret.n = n; return ret; }\n" + "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\n\n"); if (!typedefs_file(g, f)) return false; if (!cgen_decls_file(g, f)) diff --git a/decls_cgen.c b/decls_cgen.c index 7ac286d..3a9cdf0 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -52,7 +52,7 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) { if (!cgen_decls_block(g, &d->expr.fn.body)) return false; fn_exit(&d->expr.fn); - } else if (d->flags & DECL_FLAG_HAS_EXPR) { + } else if (d->flags & DECL_HAS_EXPR) { if (!cgen_decls_expr(g, &d->expr)) return false; } @@ -92,7 +92,7 @@ static size_t compiler_alignof(Type *t) { /* OPTIM: don't do this once per Type, but once per struct */ static void eval_struct_find_offsets(Type *t) { assert(t->kind == TYPE_STRUCT); - if (!(t->flags & TYPE_FLAG_STRUCT_FOUND_OFFSETS)) { + if (!(t->flags & TYPE_STRUCT_FOUND_OFFSETS)) { size_t bytes = 0; arr_foreach(t->struc.fields, Field, f) { size_t falign = compiler_alignof(f->type); @@ -107,7 +107,7 @@ static void eval_struct_find_offsets(Type *t) { size_t align = compiler_alignof(t); bytes += ((align - bytes) % align + align) % align; /* = -bytes mod align */ t->struc.size = bytes; - t->flags |= TYPE_FLAG_STRUCT_FOUND_OFFSETS; + t->flags |= TYPE_STRUCT_FOUND_OFFSETS; } } @@ -949,7 +949,7 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value eval_binary_bool_op_one(charv, CHAR, op); #define eval_binary_bool_op_nums_only(op) \ - {Type *cast_to = lhs_type->flags & TYPE_FLAG_FLEXIBLE ? \ + {Type *cast_to = lhs_type->flags & TYPE_IS_FLEXIBLE ? \ rhs_type : lhs_type; \ val_cast(&lhs, lhs_type, &lhs, cast_to); \ val_cast(&rhs, rhs_type, &rhs, cast_to); \ @@ -1194,7 +1194,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value stepval; stepval.i64 = 1; Type i64t; - i64t.flags = TYPE_FLAG_RESOLVED; + i64t.flags = TYPE_IS_RESOLVED; i64t.kind = TYPE_BUILTIN; i64t.builtin = BUILTIN_I64; if (!eval_expr(ev, ea->range.from, &from)) return false; @@ -1228,7 +1228,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value rhs = to; assert(ea->type.kind == TYPE_BUILTIN); Type boolt; - boolt.flags = TYPE_FLAG_RESOLVED; + boolt.flags = TYPE_IS_RESOLVED; boolt.kind = TYPE_BUILTIN; boolt.builtin = BUILTIN_BOOL; Value cont; @@ -1289,7 +1289,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { default: assert(0); return false; } Type i64t; - i64t.flags = TYPE_FLAG_RESOLVED; + i64t.flags = TYPE_IS_RESOLVED; i64t.kind = TYPE_BUILTIN; i64t.builtin = BUILTIN_I64; index_val->i64 = 0; @@ -1336,21 +1336,21 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { if (is_decl) { d = idecl->decl; if (!types_decl(ev->typer, d)) return false; - assert(d->type.flags & TYPE_FLAG_RESOLVED); + assert(d->type.flags & TYPE_IS_RESOLVED); } if (idecl->flags & IDECL_HAS_VAL) { *v = idecl->val; - } else if (is_decl && (d->flags & DECL_FLAG_CONST)) { - if (!(d->flags & DECL_FLAG_FOUND_VAL)) { + } else if (is_decl && (d->flags & DECL_IS_CONST)) { + if (!(d->flags & DECL_FOUND_VAL)) { if (!eval_expr(ev, &d->expr, &d->val)) return false; - d->flags |= DECL_FLAG_FOUND_VAL; + d->flags |= DECL_FOUND_VAL; } int index = ident_index_in_decl(e->ident, d); assert(index != -1); if (e->type.kind == TYPE_TYPE) { /* set v to a user type, not the underlying type */ v->type = evalr_malloc(ev, sizeof *v->type); /* TODO: fix this (free eventually) */ - v->type->flags = TYPE_FLAG_RESOLVED; + v->type->flags = TYPE_IS_RESOLVED; v->type->kind = TYPE_USER; v->type->user.decl = d; v->type->user.index = index; @@ -1504,16 +1504,16 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } static bool eval_decl(Evaluator *ev, Declaration *d) { - int has_expr = d->flags & DECL_FLAG_HAS_EXPR; - int is_const = d->flags & DECL_FLAG_CONST; + int has_expr = d->flags & DECL_HAS_EXPR; + int is_const = d->flags & DECL_IS_CONST; Value val = {0}; if (has_expr) { if (is_const) { - if (!(d->flags & DECL_FLAG_FOUND_VAL)) { + if (!(d->flags & DECL_FOUND_VAL)) { if (!eval_expr(ev, &d->expr, &d->val)) return false; - d->flags |= DECL_FLAG_FOUND_VAL; + d->flags |= DECL_FOUND_VAL; } } else { /* TODO: tuples allocated here will never be freed! */ diff --git a/identifiers.c b/identifiers.c index 3cce0d1..cc9315f 100644 --- a/identifiers.c +++ b/identifiers.c @@ -193,9 +193,9 @@ static Type *ident_typeval(Identifier i) { IdentDecl *idecl = ident_decl(i); if (!idecl) return NULL; Declaration *d = idecl->decl; - if (!(d->flags & DECL_FLAG_CONST)) + if (!(d->flags & DECL_IS_CONST)) return NULL; - assert(d->flags & DECL_FLAG_FOUND_TYPE); + assert(d->flags & DECL_FOUND_TYPE); if (d->type.kind == TYPE_TUPLE) { size_t idx; for (idx = 0; idx < arr_len(d->idents); idx++) { @@ -7,8 +7,7 @@ compile-time arguments for functions returning tuples don't allow pointers to functions with compile-time arguments don't allow while {3; 5} (once break is added) any odd number of "s for a string -modifiable strings: -s := ["sakjdfhkjh ksjdahfkjsd ahs ahdf hsdaf khsadkjfh"]; +modifiable string literals unicode variable names (cgen support) make sure futurely/currently-declared types are only used by pointer/slice allow omission of trailing ; in foo @= fn() {}? @@ -92,7 +91,7 @@ int main(int argc, char **argv) { evalr_create(&ev, &tr); typer_create(&tr, &ev); - if (!block_enter(NULL, f.stmts, SCOPE_FLAG_CHECK_REDECL)) /* enter global scope */ + if (!block_enter(NULL, f.stmts, SCOPE_CHECK_REDECL)) /* enter global scope */ return false; if (!types_file(&tr, &f)) { @@ -190,7 +190,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { } case TYPE_ARR: { size_t written = str_copy(buffer, bufsize, "["); - if (t->flags & TYPE_FLAG_RESOLVED) { + if (t->flags & TYPE_IS_RESOLVED) { snprintf(buffer + written, bufsize - written, UINTEGER_FMT, t->arr.n); written += strlen(buffer + written); } else { @@ -224,7 +224,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { case TYPE_TYPE: return str_copy(buffer, bufsize, "<type>"); case TYPE_USER: { - char *ident_str = ident_to_str((t->flags & TYPE_FLAG_RESOLVED) + char *ident_str = ident_to_str((t->flags & TYPE_IS_RESOLVED) ? t->user.decl->idents[t->user.index] : t->user.ident); size_t ret = str_copy(buffer, bufsize, ident_str); @@ -498,12 +498,12 @@ static bool parse_type(Parser *p, Type *type) { if (!parse_decl(p, &field_decl, DECL_END_SEMICOLON, 0)) { return false; } - if (field_decl.flags & DECL_FLAG_CONST) { + if (field_decl.flags & DECL_IS_CONST) { /* TODO */ err_print(field_decl.where, "Constant struct members are not supported (yet)."); return false; } - if (field_decl.flags & DECL_FLAG_HAS_EXPR) { + if (field_decl.flags & DECL_HAS_EXPR) { err_print(field_decl.where, "struct members cannot have initializers."); return false; } @@ -712,7 +712,7 @@ static bool parse_block(Parser *p, Block *b) { if (token_is_kw(t->token, KW_RBRACE)) { if (success && stmt->kind == STMT_EXPR) { - if (!(stmt->flags & STMT_FLAG_VOIDED_EXPR)) { + if (!(stmt->flags & STMT_VOIDED_EXPR)) { b->ret_expr = parser_new_expr(p); *b->ret_expr = stmt->expr; arr_remove_last(&b->stmts); /* only keep this expression in the return value */ @@ -722,7 +722,7 @@ static bool parse_block(Parser *p, Block *b) { } if (success) { - if (stmt->kind == STMT_EXPR && !(stmt->flags & STMT_FLAG_VOIDED_EXPR)) { + if (stmt->kind == STMT_EXPR && !(stmt->flags & STMT_VOIDED_EXPR)) { /* in theory, this should never happen right now */ err_print(stmt->where, "Non-voided expression is not the last statement in a block (you might want to add a ';' to the end of this statement)."); return false; @@ -786,8 +786,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { } else { if (!parse_decl_list(p, &f->params, DECL_END_RPAREN_COMMA)) return false; - arr_foreach(f->params, Declaration, pdecl) - pdecl->flags |= DECL_FLAG_PARAM; } if (t->token->kind == TOKEN_EOF) { @@ -824,7 +822,7 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { } if (!parse_block(p, &f->body)) ret = false; - f->body.flags |= BLOCK_FLAG_FN; + f->body.flags |= BLOCK_IS_FN; return ret; } @@ -1715,7 +1713,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ break; } if (token_is_kw(t->token, KW_AT)) { - d->flags |= DECL_FLAG_CONST; + d->flags |= DECL_IS_CONST; t->token++; break; } @@ -1731,7 +1729,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ bool annotates_type = !token_is_kw(t->token, KW_EQ) && !token_is_kw(t->token, KW_COMMA); if (annotates_type) { - d->flags |= DECL_FLAG_ANNOTATES_TYPE; + d->flags |= DECL_ANNOTATES_TYPE; Type type; if (!parse_type(p, &type)) { goto ret_false; @@ -1751,7 +1749,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ if (token_is_kw(t->token, KW_EQ)) { t->token++; - d->flags |= DECL_FLAG_HAS_EXPR; + d->flags |= DECL_HAS_EXPR; uint16_t expr_flags = 0; if (ends_with == DECL_END_RPAREN_COMMA) expr_flags |= EXPR_CAN_END_WITH_COMMA; @@ -1777,7 +1775,7 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_ goto ret_false; } - if ((d->flags & DECL_FLAG_CONST) && !(d->flags & DECL_FLAG_HAS_EXPR) && !(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; */ tokr_err(t, "You must have an expression at the end of this constant declaration."); @@ -1852,7 +1850,7 @@ static bool parse_stmt(Parser *p, Statement *s) { return false; } if (is_vbs || token_is_kw(end, KW_SEMICOLON)) { - s->flags |= STMT_FLAG_VOIDED_EXPR; + s->flags |= STMT_VOIDED_EXPR; } bool success = parse_expr(p, &s->expr, end); @@ -2130,15 +2128,15 @@ static void fprint_decl(FILE *out, Declaration *d) { if (ident != d->idents) fprintf(out, ", "); fprint_ident(out, *ident); } - if (d->flags & DECL_FLAG_CONST) { + if (d->flags & DECL_IS_CONST) { fprintf(out, "@"); } else { fprintf(out, ":"); } - if ((d->flags & DECL_FLAG_FOUND_TYPE) || (d->flags & DECL_FLAG_ANNOTATES_TYPE)) { + if ((d->flags & DECL_FOUND_TYPE) || (d->flags & DECL_ANNOTATES_TYPE)) { fprint_type(out, &d->type); } - if (d->flags & DECL_FLAG_HAS_EXPR) { + if (d->flags & DECL_HAS_EXPR) { fprintf(out, "="); fprint_expr(out, &d->expr); } @@ -2146,7 +2144,7 @@ static void fprint_decl(FILE *out, Declaration *d) { static void fprint_stmt(FILE *out, Statement *s) { PARSE_PRINT_LOCATION(s->where); - if (s->flags & STMT_FLAG_VOIDED_EXPR) + if (s->flags & STMT_VOIDED_EXPR) fprintf(out, "(void)"); switch (s->kind) { case STMT_DECL: @@ -1,4 +1,4 @@ -#define SCOPE_FLAG_CHECK_REDECL 0x0001 +#define SCOPE_CHECK_REDECL 0x0001 static void val_free(Value *v, Type *t); @@ -7,7 +7,7 @@ static bool add_ident_decls(Block *b, Declaration *d, U32 flags) { bool ret = true; arr_foreach(d->idents, Identifier, ident) { IdentDecl *decls = (*ident)->decls; - if ((flags & SCOPE_FLAG_CHECK_REDECL) && arr_len(decls)) { + if ((flags & SCOPE_CHECK_REDECL) && arr_len(decls)) { /* check that it hasn't been declared in this block */ IdentDecl *prev = arr_last(decls); if (prev->scope == b) { @@ -32,7 +32,7 @@ static void remove_ident_decls(Block *b, Declaration *d) { if (last_decl && last_decl->scope == b) { if ((last_decl->flags & IDECL_HAS_VAL) /* don't free const vals (there's only one per decl) */ - && !(last_decl->decl->flags & DECL_FLAG_CONST)) { + && !(last_decl->decl->flags & DECL_IS_CONST)) { val_free(&last_decl->val, is_tuple ? &d->type.tuple[i++] : &d->type); } arr_remove_last(decls); /* remove that declaration */ @@ -26,12 +26,12 @@ static Type *type_user_underlying(Type *t) { assert(t->kind == TYPE_USER); Declaration *d = t->user.decl; - assert(d->flags & DECL_FLAG_FOUND_VAL); + assert(d->flags & DECL_FOUND_VAL); return (d->type.kind == TYPE_TUPLE ? d->val.tuple[t->user.index] : d->val).type; } static Type *type_inner(Type *t) { - assert(t->flags & TYPE_FLAG_RESOLVED); + assert(t->flags & TYPE_IS_RESOLVED); while (t->kind == TYPE_USER) { t = type_user_underlying(t); } diff --git a/typedefs_cgen.c b/typedefs_cgen.c index 46c629b..a068c74 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -46,7 +46,7 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) { cgen_nl(g); } } - if (d->flags & DECL_FLAG_HAS_EXPR) + if (d->flags & DECL_HAS_EXPR) if (!typedefs_expr(g, &d->expr)) return false; return true; @@ -25,11 +25,11 @@ static inline bool type_is_builtin(Type *t, BuiltinType b) { static bool type_eq(Type *a, Type *b) { if (a->kind == TYPE_UNKNOWN || b->kind == TYPE_UNKNOWN) return true; /* allow things such as 3 + #C("5") */ - assert(a->flags & TYPE_FLAG_RESOLVED); - assert(b->flags & TYPE_FLAG_RESOLVED); + assert(a->flags & TYPE_IS_RESOLVED); + assert(b->flags & TYPE_IS_RESOLVED); if (a->kind != b->kind) return false; - if (a->flags & TYPE_FLAG_FLEXIBLE) { - if (b->flags & TYPE_FLAG_FLEXIBLE) return true; + if (a->flags & TYPE_IS_FLEXIBLE) { + if (b->flags & TYPE_IS_FLEXIBLE) return true; assert(a->kind == TYPE_BUILTIN); if (type_builtin_is_float(a->builtin)) { @@ -38,7 +38,7 @@ static bool type_eq(Type *a, Type *b) { assert(a->builtin == BUILTIN_I64); return type_builtin_is_numerical(b->builtin); } - if (b->flags & TYPE_FLAG_FLEXIBLE) { + if (b->flags & TYPE_IS_FLEXIBLE) { Type *tmp = a; a = b; b = tmp; @@ -104,7 +104,7 @@ static bool expr_arr_must_mut(Expression *e) { IdentDecl *idecl = ident_decl(e->ident); if (idecl->kind == IDECL_DECL) { Declaration *d = idecl->decl; - if (d->flags & DECL_FLAG_CONST) { + if (d->flags & DECL_IS_CONST) { err_print(e->where, "Cannot modify a constant array."); return false; } @@ -163,7 +163,7 @@ static bool expr_must_lval(Expression *e) { assert(id_decl); if (id_decl->kind == IDECL_DECL) { Declaration *d = id_decl->decl; - if (d->flags & DECL_FLAG_CONST) { + if (d->flags & DECL_IS_CONST) { char *istr = ident_to_str(e->ident); err_print(e->where, "Use of constant %s as a non-constant expression.", istr); info_print(d->where, "%s was declared here.", istr); @@ -268,12 +268,12 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { bool captured = false; if (decl->scope != NULL) for (Block *block = tr->block; block != decl->scope; block = block->parent) { - if (block->flags & BLOCK_FLAG_FN) { + if (block->flags & BLOCK_IS_FN) { captured = true; break; } } - if (captured && !(d->flags & DECL_FLAG_CONST)) { + if (captured && !(d->flags & DECL_IS_CONST)) { err_print(where, "Variables cannot be captured into inner functions (but constants can)."); return false; } @@ -281,22 +281,22 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { typedef Declaration *DeclarationPtr; arr_foreach(tr->in_decls, DeclarationPtr, in_decl) { if (d == *in_decl) { - assert(d->flags & DECL_FLAG_HAS_EXPR); /* we can only be in decls with an expr */ + assert(d->flags & DECL_HAS_EXPR); /* we can only be in decls with an expr */ if (d->expr.kind != EXPR_FN) { /* it's okay if a function references itself */ /* if we've complained about it before when we were figuring out the type, don't complain again */ - if (!(d->flags & DECL_FLAG_ERRORED_ABOUT_SELF_REFERENCE)) { + if (!(d->flags & DECL_ERRORED_ABOUT_SELF_REFERENCE)) { char *s = ident_to_str(i); err_print(where, "Use of identifier %s in its own declaration.", s); free(s); info_print(d->where, "Declaration was here."); - d->flags |= DECL_FLAG_ERRORED_ABOUT_SELF_REFERENCE; + d->flags |= DECL_ERRORED_ABOUT_SELF_REFERENCE; } return false; } } } - if (d->flags & DECL_FLAG_FOUND_TYPE) { + if (d->flags & DECL_FOUND_TYPE) { if (d->type.kind == TYPE_TUPLE) { /* get correct item in tuple */ long index = 0; @@ -313,7 +313,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { } return true; } else { - if ((d->flags & DECL_FLAG_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { + if ((d->flags & DECL_HAS_EXPR) && (d->expr.kind == EXPR_FN)) { /* allow using a function before declaring it */ if (!type_of_fn(tr, &d->expr, t)) return false; return true; @@ -365,7 +365,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { /* fixes the type (replaces [5+3]int with [8]int, etc.) */ static bool type_resolve(Typer *tr, Type *t, Location where) { Evaluator *ev = tr->evalr; - if (t->flags & TYPE_FLAG_RESOLVED) return true; + if (t->flags & TYPE_IS_RESOLVED) return true; switch (t->kind) { case TYPE_ARR: { /* it's an array */ @@ -422,7 +422,7 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { return false; break; case TYPE_USER: { - t->flags |= TYPE_FLAG_RESOLVED; /* pre-resolve type to avoid infinite recursion */ + t->flags |= TYPE_IS_RESOLVED; /* pre-resolve type to avoid infinite recursion */ /* find declaration */ Identifier ident = t->user.ident; IdentDecl *idecl = ident_decl(ident); @@ -465,7 +465,7 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { case TYPE_BUILTIN: break; } - t->flags |= TYPE_FLAG_RESOLVED; + t->flags |= TYPE_IS_RESOLVED; return true; } @@ -578,11 +578,11 @@ static Status type_cast_status(Type *from, Type *to) { } static bool types_expr(Typer *tr, Expression *e) { - if (e->flags & EXPR_FLAG_FOUND_TYPE) return true; + if (e->flags & EXPR_FOUND_TYPE) return true; Type *t = &e->type; t->flags = 0; t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */ - e->flags |= EXPR_FLAG_FOUND_TYPE; /* even if failed, pretend we found the type */ + e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ bool success = true; switch (e->kind) { case EXPR_FN: { @@ -602,7 +602,7 @@ static bool types_expr(Typer *tr, Expression *e) { tr->ret_type = t->fn.types[0]; } tr->can_ret = true; - if (!fn_enter(f, SCOPE_FLAG_CHECK_REDECL)) + if (!fn_enter(f, SCOPE_CHECK_REDECL)) return false; bool block_success = true; block_success = types_block(tr, &e->fn.body); @@ -656,20 +656,20 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_LITERAL_INT: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_I64; - t->flags |= TYPE_FLAG_FLEXIBLE; + t->flags |= TYPE_IS_FLEXIBLE; break; case EXPR_LITERAL_STR: t->kind = TYPE_SLICE; t->slice = typer_malloc(tr, sizeof *t->slice); - t->slice->flags = TYPE_FLAG_RESOLVED; + t->slice->flags = TYPE_IS_RESOLVED; t->slice->kind = TYPE_BUILTIN; t->slice->builtin = BUILTIN_CHAR; - t->flags |= TYPE_FLAG_RESOLVED; + t->flags |= TYPE_IS_RESOLVED; break; case EXPR_LITERAL_FLOAT: t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_F32; - t->flags |= TYPE_FLAG_FLEXIBLE; + t->flags |= TYPE_IS_FLEXIBLE; break; case EXPR_LITERAL_BOOL: t->kind = TYPE_BUILTIN; @@ -682,7 +682,7 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_EACH: { EachExpr *ea = &e->each; *(Expression **)arr_add(&tr->in_expr_decls) = e; - if (!each_enter(e, SCOPE_FLAG_CHECK_REDECL)) return false; + if (!each_enter(e, SCOPE_CHECK_REDECL)) return false; if (ea->flags & EACH_IS_RANGE) { /* TODO: allow user-defined numerical types */ if (!types_expr(tr, ea->range.from)) return false; @@ -733,7 +733,7 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } - if ((ea->type.flags & TYPE_FLAG_FLEXIBLE) && ea->range.step) + if ((ea->type.flags & TYPE_IS_FLEXIBLE) && ea->range.step) ea->type = ea->range.step->type; if (ea->range.to && !type_eq(&ea->type, &ea->range.to->type)) { @@ -744,7 +744,7 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } - if ((ea->type.flags & TYPE_FLAG_FLEXIBLE) && ea->range.to) + if ((ea->type.flags & TYPE_IS_FLEXIBLE) && ea->range.to) ea->type = ea->range.to->type; } else { @@ -773,7 +773,7 @@ static bool types_expr(Typer *tr, Expression *e) { } Type ptr_type; if (uses_ptr) { - ptr_type.flags = TYPE_FLAG_RESOLVED; + ptr_type.flags = TYPE_IS_RESOLVED; ptr_type.kind = TYPE_PTR; ptr_type.ptr = iter_type; iter_type = &ptr_type; @@ -960,7 +960,7 @@ static bool types_expr(Typer *tr, Expression *e) { IdentDecl *decl = ident_decl(f->ident); assert(decl); if (decl->kind == IDECL_DECL) { - if (decl->decl->flags & DECL_FLAG_HAS_EXPR) { + if (decl->decl->flags & DECL_HAS_EXPR) { Expression *expr = &decl->decl->expr; if (expr->kind == EXPR_FN) fn_decl = &decl->decl->expr.fn; @@ -1025,7 +1025,7 @@ static bool types_expr(Typer *tr, Expression *e) { assert(fn_decl); /* we can only miss an arg if we're using named/optional args */ arr_foreach(fn_decl->params, Declaration, param) { - bool is_required = !(param->flags & DECL_FLAG_HAS_EXPR); + bool is_required = !(param->flags & DECL_HAS_EXPR); arr_foreach(param->idents, Identifier, ident) { if (index == i) { if (is_required) { @@ -1046,7 +1046,7 @@ static bool types_expr(Typer *tr, Expression *e) { /* evaluate compile-time arguments */ size_t i = 0; arr_foreach(fn_decl->params, Declaration, param) { - if (param->flags & DECL_FLAG_CONST) { + if (param->flags & DECL_IS_CONST) { arr_foreach(param->idents, Identifier, ident) { Value arg_val; if (!eval_expr(tr->evalr, &new_args[i], &arg_val)) { @@ -1272,8 +1272,8 @@ static bool types_expr(Typer *tr, Expression *e) { t->builtin = BUILTIN_BOOL; break; default: { - int lhs_is_flexible = lhs_type->flags & TYPE_FLAG_FLEXIBLE; - int rhs_is_flexible = rhs_type->flags & TYPE_FLAG_FLEXIBLE; + int lhs_is_flexible = lhs_type->flags & TYPE_IS_FLEXIBLE; + int rhs_is_flexible = rhs_type->flags & TYPE_IS_FLEXIBLE; if (lhs_is_flexible && rhs_is_flexible) { /* both flexible */ *t = *lhs_type; @@ -1469,17 +1469,17 @@ static bool types_expr(Typer *tr, Expression *e) { assert(0); return false; } - e->type.flags |= TYPE_FLAG_RESOLVED; + e->type.flags |= TYPE_IS_RESOLVED; return true; } static bool types_block(Typer *tr, Block *b) { - if (b->flags & BLOCK_FLAG_FOUND_TYPES) + if (b->flags & BLOCK_FOUND_TYPES) return true; bool success = true; Block *prev_block = tr->block; tr->block = b; - if (!block_enter(b, b->stmts, SCOPE_FLAG_CHECK_REDECL)) return false; + if (!block_enter(b, b->stmts, SCOPE_CHECK_REDECL)) return false; arr_foreach(b->stmts, Statement, s) { if (!types_stmt(tr, s)) success = false; @@ -1494,16 +1494,16 @@ static bool types_block(Typer *tr, Block *b) { } block_exit(b, b->stmts); tr->block = prev_block; - b->flags |= BLOCK_FLAG_FOUND_TYPES; + b->flags |= BLOCK_FOUND_TYPES; return success; } static bool types_decl(Typer *tr, Declaration *d) { bool success = true; - if (d->flags & DECL_FLAG_FOUND_TYPE) return true; + if (d->flags & DECL_FOUND_TYPE) return true; Declaration **dptr = typer_arr_add(tr, &tr->in_decls); *dptr = d; - if (d->flags & DECL_FLAG_ANNOTATES_TYPE) { + if (d->flags & DECL_ANNOTATES_TYPE) { /* type supplied */ assert(d->type.kind != TYPE_VOID); /* there's no way to annotate void */ if (!type_resolve(tr, &d->type, d->where)) { @@ -1511,12 +1511,12 @@ static bool types_decl(Typer *tr, Declaration *d) { goto ret; } } - if (d->flags & DECL_FLAG_HAS_EXPR) { + if (d->flags & DECL_HAS_EXPR) { if (!types_expr(tr, &d->expr)) { success = false; goto ret; } - if (d->flags & DECL_FLAG_ANNOTATES_TYPE) { + if (d->flags & DECL_ANNOTATES_TYPE) { if (!type_must_eq(d->expr.where, &d->type, &d->expr.type)) { success = false; goto ret; @@ -1529,22 +1529,22 @@ static bool types_decl(Typer *tr, Declaration *d) { goto ret; } d->type = d->expr.type; - d->type.flags &= (uint16_t)~(uint16_t)TYPE_FLAG_FLEXIBLE; /* x := 5; => x is not flexible */ + d->type.flags &= (uint16_t)~(uint16_t)TYPE_IS_FLEXIBLE; /* x := 5; => x is not flexible */ } - if ((d->flags & DECL_FLAG_CONST) || tr->block == NULL) { - if (!(d->flags & DECL_FLAG_FOUND_VAL)) { + if ((d->flags & DECL_IS_CONST) || tr->block == NULL) { + if (!(d->flags & DECL_FOUND_VAL)) { if (!eval_expr(tr->evalr, &d->expr, &d->val)) { success = false; goto ret; } - d->flags |= DECL_FLAG_FOUND_VAL; + d->flags |= DECL_FOUND_VAL; } } 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)) { + if (!(d->flags & DECL_IS_CONST)) { err_print(d->where, "Cannot declare non-constant type."); success = false; goto ret; @@ -1570,7 +1570,7 @@ static bool types_decl(Typer *tr, Declaration *d) { } ret: /* pretend we found the type even if we didn't to prevent too many errors */ - d->flags |= DECL_FLAG_FOUND_TYPE; + d->flags |= DECL_FOUND_TYPE; if (!success) { /* use unknown type if we didn't get the type */ d->type.flags = 0; @@ -294,9 +294,9 @@ typedef struct { size_t offset; /* offset during compile time */ } Field; -#define TYPE_FLAG_FLEXIBLE 0x01 -#define TYPE_FLAG_RESOLVED 0x02 -#define TYPE_FLAG_STRUCT_FOUND_OFFSETS 0x04 +#define TYPE_IS_FLEXIBLE 0x01 +#define TYPE_IS_RESOLVED 0x02 +#define TYPE_STRUCT_FOUND_OFFSETS 0x04 typedef struct Type { Location where; @@ -334,8 +334,8 @@ typedef struct Type { }; } Type; -#define BLOCK_FLAG_FN 0x01 -#define BLOCK_FLAG_FOUND_TYPES 0x02 +#define BLOCK_IS_FN 0x01 +#define BLOCK_FOUND_TYPES 0x02 typedef struct Block { U16 flags; Location start; @@ -485,7 +485,7 @@ typedef struct { } c; } SliceExpr; -#define EXPR_FLAG_FOUND_TYPE 0x01 +#define EXPR_FOUND_TYPE 0x01 typedef struct Expression { Type type; @@ -549,13 +549,12 @@ typedef struct Argument { Expression val; } Argument; -#define DECL_FLAG_ANNOTATES_TYPE 0x01 -#define DECL_FLAG_CONST 0x02 -#define DECL_FLAG_HAS_EXPR 0x04 -#define DECL_FLAG_FOUND_TYPE 0x08 -#define DECL_FLAG_ERRORED_ABOUT_SELF_REFERENCE 0x10 /* has there been an error about this decl referencing itself? */ -#define DECL_FLAG_FOUND_VAL 0x20 -#define DECL_FLAG_PARAM 0x40 /* is this a parameter declaration? (needed because parameters are immutable) */ +#define DECL_ANNOTATES_TYPE 0x01 +#define DECL_IS_CONST 0x02 +#define DECL_HAS_EXPR 0x04 +#define DECL_FOUND_TYPE 0x08 +#define DECL_ERRORED_ABOUT_SELF_REFERENCE 0x10 /* has there been an error about this decl referencing itself? */ +#define DECL_FOUND_VAL 0x20 /* OPTIM: Instead of using dynamic arrays, do two passes. */ typedef struct Declaration { @@ -583,7 +582,7 @@ typedef struct { Expression expr; } Return; -#define STMT_FLAG_VOIDED_EXPR 0x01 /* the "4;" in fn () { 4; } is a voided expression, but the "4" in fn () int { 4 } is not */ +#define STMT_VOIDED_EXPR 0x01 /* the "4;" in fn () { 4; } is a voided expression, but the "4" in fn () int { 4 } is not */ typedef struct Statement { Location where; StatementKind kind; |