summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archive/arr.c69
-rw-r--r--archive/base_cgen.c295
-rw-r--r--archive/cgen.c463
-rw-r--r--archive/decls_cgen.c106
-rw-r--r--cgen.c28
-rw-r--r--decls_cgen.c2
-rw-r--r--eval.c30
-rw-r--r--identifiers.c4
-rw-r--r--main.c5
-rw-r--r--parse.c34
-rw-r--r--scope.c6
-rw-r--r--toc.c4
-rw-r--r--typedefs_cgen.c2
-rw-r--r--types.c94
-rw-r--r--types.h27
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, &param_types[i]);
- cgen_type_post(g, &param_types[i]);
- } else {
- Param *p = &params[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;
-}
diff --git a/cgen.c b/cgen.c
index 9bae62d..60346fd 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
}
diff --git a/eval.c b/eval.c
index aa60c7b..e03fe7c 100644
--- a/eval.c
+++ b/eval.c
@@ -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++) {
diff --git a/main.c b/main.c
index 6c413f7..bc803a3 100644
--- a/main.c
+++ b/main.c
@@ -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)) {
diff --git a/parse.c b/parse.c
index f14cc89..c3cf7fb 100644
--- a/parse.c
+++ b/parse.c
@@ -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:
diff --git a/scope.c b/scope.c
index 35721d0..b0ebbeb 100644
--- a/scope.c
+++ b/scope.c
@@ -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 */
diff --git a/toc.c b/toc.c
index c7dc473..bbfce6a 100644
--- a/toc.c
+++ b/toc.c
@@ -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;
diff --git a/types.c b/types.c
index f84d9a8..9b8629f 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index 84ae982..fad82e5 100644
--- a/types.h
+++ b/types.h
@@ -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;