diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-30 16:16:32 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-30 16:16:32 -0500 |
commit | db0367b2aa29de32d941cdea9af810b7eef0b74a (patch) | |
tree | a8a65d65633acd609212443e60f5f12c1dfc232a | |
parent | 76ff5d914def4984d5b599177032ded71632a5ec (diff) |
got rid of TYPE_USER!!
-rw-r--r-- | cgen.c | 96 | ||||
-rw-r--r-- | copy.c | 31 | ||||
-rw-r--r-- | decls_cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 112 | ||||
-rw-r--r-- | instance_table.c | 14 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | parse.c | 137 | ||||
-rw-r--r-- | test.toc | 20 | ||||
-rw-r--r-- | toc.c | 24 | ||||
-rw-r--r-- | typedefs_cgen.c | 40 | ||||
-rw-r--r-- | types.c | 111 | ||||
-rw-r--r-- | types.h | 112 |
12 files changed, 295 insertions, 410 deletions
@@ -217,6 +217,7 @@ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) { } static bool cgen_uses_ptr(Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_TUPLE: case TYPE_STRUCT: @@ -230,9 +231,8 @@ static bool cgen_uses_ptr(Type *t) { case TYPE_UNKNOWN: case TYPE_TYPE: return false; - case TYPE_USER: - case TYPE_CALL: - return cgen_uses_ptr(type_user_underlying(t)); + case TYPE_EXPR: + break; } assert(0); return false; @@ -310,50 +310,43 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { err_print(where, "Can't determine type."); return false; case TYPE_STRUCT: - cgen_write(g, "struct {"); - g->indent_lvl++; - cgen_nl(g); - arr_foreach(t->struc.fields, Field, f) { - if (!cgen_type_pre(g, f->type, where)) return false; - cgen_write(g, " "); - cgen_ident(g, f->name); - if (!cgen_type_post(g, f->type, where)) return false; - cgen_write(g, ";"); + cgen_write(g, "struct "); + if (t->struc->c.name) { + cgen_ident(g, t->struc->c.name); + } else if (t->struc->c.id) { + cgen_ident_id(g, t->struc->c.id); + } else { + #if 0 + /* TODO: DELME */ + cgen_write(g, "struct {"); + g->indent_lvl++; cgen_nl(g); + arr_foreach(t->struc.fields, Field, f) { + if (!cgen_type_pre(g, f->type, where)) return false; + cgen_write(g, " "); + cgen_ident(g, f->name); + if (!cgen_type_post(g, f->type, where)) return false; + cgen_write(g, ";"); + cgen_nl(g); + } + g->indent_lvl--; + cgen_write(g, "}"); + #endif + assert(0); } - g->indent_lvl--; - cgen_write(g, "}"); break; case TYPE_TUPLE: case TYPE_TYPE: + case TYPE_EXPR: /* We should never try to generate this type */ assert(0); return false; - case TYPE_USER: { - Type *this = t; - do { - Type *next = type_user_underlying(this); - if (next->kind == TYPE_STRUCT) { - /* use struct tag */ - cgen_write(g, "struct "); - t = this; - break; - } - this = next; - } while (this->kind == TYPE_USER); - - Declaration *d = t->user.decl; - int idx = t->user.index; - if (d->c.ids[idx]) - cgen_ident_id(g, d->c.ids[idx]); - else - cgen_ident(g, d->idents[idx]); - } break; } return true; } static bool cgen_type_post(CGenerator *g, Type *t, Location where) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_PTR: cgen_write(g, ")"); @@ -415,9 +408,11 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) { case TYPE_TUPLE: case TYPE_TYPE: case TYPE_SLICE: - case TYPE_USER: case TYPE_STRUCT: break; + case TYPE_EXPR: + assert(0); + break; } return true; } @@ -521,7 +516,6 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E type = &to_expr->type; where = to_expr->where; } - type = type_inner(type); switch (type->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -578,9 +572,9 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E if (!cgen_set_tuple(g, set_expr->tuple, NULL, NULL, to_expr)) return false; break; - case TYPE_USER: case TYPE_VOID: case TYPE_TYPE: + case TYPE_EXPR: assert(0); return false; } @@ -1227,7 +1221,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { case BINARY_DOT: { cgen_write(g, "("); cgen_expr(g, e->binary.lhs); - bool is_ptr = type_inner(&e->binary.lhs->type)->kind == TYPE_PTR; + bool is_ptr = e->binary.lhs->type.kind == TYPE_PTR; cgen_write(g, is_ptr ? "->" :"."); cgen_ident(g, e->binary.field->name); cgen_write(g, ")"); @@ -1452,6 +1446,7 @@ static bool cgen_block(CGenerator *g, Block *b, const char *ret_name, U16 flags) } static void cgen_zero_value(CGenerator *g, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: cgen_write(g, "0"); @@ -1467,13 +1462,11 @@ static void cgen_zero_value(CGenerator *g, Type *t) { case TYPE_STRUCT: cgen_write(g, "{0}"); break; - case TYPE_USER: - cgen_zero_value(g, type_inner(t)); - break; case TYPE_TYPE: case TYPE_VOID: case TYPE_UNKNOWN: case TYPE_TUPLE: + case TYPE_EXPR: assert(0); break; } @@ -1578,6 +1571,7 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where, U64 instance, Valu } static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_SLICE: { Slice *s = (Slice *)v; @@ -1603,10 +1597,6 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { return false; } break; - case TYPE_USER: - if (!cgen_val_ptr_pre(g, v, type_inner(t), where)) - return false; - break; case TYPE_FN: case TYPE_TYPE: case TYPE_UNKNOWN: @@ -1616,12 +1606,16 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { case TYPE_PTR: case TYPE_STRUCT: break; + case TYPE_EXPR: + assert(0); + return false; } return true; } /* generate a value from a pointer */ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_TUPLE: case TYPE_VOID: @@ -1645,8 +1639,8 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { break; case TYPE_STRUCT: cgen_write(g, "{"); - arr_foreach(t->struc.fields, Field, f) { - if (f != t->struc.fields) + arr_foreach(t->struc->fields, Field, f) { + if (f != t->struc->fields) cgen_write(g, ", "); cgen_val_ptr(g, (char *)v + f->offset, f->type, where); } @@ -1674,10 +1668,9 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break; } break; - case TYPE_USER: - if (!cgen_val_ptr(g, v, type_inner(t), where)) - return false; - break; + case TYPE_EXPR: + assert(0); + return false; } return true; } @@ -1902,6 +1895,7 @@ static bool cgen_defs_block(CGenerator *g, Block *b) { static bool cgen_file(CGenerator *g, ParsedFile *f) { g->block = NULL; + g->fn = NULL; g->file = f; /* TODO: to improve compile times, don't include stdlib.h @@ -11,6 +11,7 @@ static void copy_block(Copier *c, Block *out, Block *in); static void copy_type(Copier *c, Type *out, Type *in); static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -35,10 +36,6 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { out->struc = allocr_malloc(a, bytes); memcpy(out->struc, in->struc, bytes); } break; - case TYPE_USER: - case TYPE_CALL: - copy_val(a, out, in, type_user_underlying(t)); - break; case TYPE_TYPE: /* copy_type(c, out->type = allocr_malloc(c->allocr, sizeof *out->type), in->type); */ /* @@ -51,6 +48,8 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) { */ *out = *in; break; + case TYPE_EXPR: + assert(0); } } @@ -64,16 +63,10 @@ static void copy_type(Copier *c, Type *out, Type *in) { case TYPE_TYPE: case TYPE_VOID: case TYPE_UNKNOWN: - case TYPE_USER: break; - case TYPE_CALL: { - copy_type(c, out->call.calling = allocr_malloc(c->allocr, sizeof *out->call.calling), - in->call.calling); - out->call.args = NULL; - arr_foreach(in->call.args, Expression, arg) { - copy_expr(c, arr_add(&out->call.args), arg); - } - } break; + case TYPE_EXPR: + copy_expr(c, out->expr = allocr_malloc(c->allocr, sizeof *out->expr), in->expr); + break; case TYPE_FN: { size_t ntypes = arr_len(in->fn.types); out->fn.types = NULL; @@ -107,12 +100,14 @@ static void copy_type(Copier *c, Type *out, Type *in) { copy_type(c, out->slice, in->slice); break; case TYPE_STRUCT: { - size_t nfields = arr_len(in->struc.fields); - out->struc.fields = NULL; - arr_set_lena(&out->struc.fields, nfields, c->allocr); + out->struc = allocr_malloc(c->allocr, sizeof *out->struc); + *out->struc = *in->struc; + size_t nfields = arr_len(in->struc->fields); + out->struc->fields = NULL; + arr_set_lena(&out->struc->fields, nfields, c->allocr); for (size_t i = 0; i < nfields; i++) { - Field *fout = &out->struc.fields[i]; - Field *fin = &in->struc.fields[i]; + Field *fout = &out->struc->fields[i]; + Field *fin = &in->struc->fields[i]; *fout = *fin; copy_type(c, fout->type, fin->type); } diff --git a/decls_cgen.c b/decls_cgen.c index f07b17e..40087f5 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -93,7 +93,7 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) { cgen_write(g, "{"); cgen_nl(g); g->indent_lvl++; - arr_foreach(val->type->struc.fields, Field, f) { + arr_foreach(val->type->struc->fields, Field, f) { if (!cgen_type_pre(g, f->type, d->where)) return false; cgen_write(g, " "); cgen_ident(g, f->name); @@ -50,6 +50,7 @@ static size_t compiler_sizeof_builtin(BuiltinType b) { } static size_t compiler_alignof(Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: return compiler_sizeof_builtin(t->builtin); @@ -70,19 +71,17 @@ static size_t compiler_alignof(Type *t) { return sizeof(size_t); case TYPE_TYPE: return sizeof(Type *); - case TYPE_USER: - case TYPE_CALL: - return compiler_alignof(type_user_underlying(t)); case TYPE_STRUCT: { /* assume the align of a struct is (at most) the greatest align out of its children's */ size_t align = 1; - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { size_t falign = compiler_alignof(f->type); if (falign > align) align = falign; } return align; } case TYPE_UNKNOWN: + case TYPE_EXPR: break; } assert(0); @@ -90,12 +89,11 @@ static size_t compiler_alignof(Type *t) { } /* finds offsets and size */ -/* 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_STRUCT_FOUND_OFFSETS)) { + if (!(t->struc->flags & STRUCT_DEF_FOUND_OFFSETS)) { size_t bytes = 0; - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { size_t falign = compiler_alignof(f->type); /* align */ bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */ @@ -107,13 +105,14 @@ static void eval_struct_find_offsets(Type *t) { /* final align */ size_t align = compiler_alignof(t); bytes += ((align - bytes) % align + align) % align; /* = -bytes mod align */ - t->struc.size = bytes; - t->flags |= TYPE_STRUCT_FOUND_OFFSETS; + t->struc->size = bytes; + t->struc->flags |= STRUCT_DEF_FOUND_OFFSETS; } } /* size of a type at compile time */ static size_t compiler_sizeof(Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: return compiler_sizeof_builtin(t->builtin); @@ -129,16 +128,15 @@ static size_t compiler_sizeof(Type *t) { return sizeof(Slice); case TYPE_TYPE: return sizeof(Type *); - case TYPE_USER: - case TYPE_CALL: - return compiler_sizeof(type_user_underlying(t)); case TYPE_STRUCT: { eval_struct_find_offsets(t); - return t->struc.size; + return t->struc->size; } break; case TYPE_VOID: case TYPE_UNKNOWN: return 0; + case TYPE_EXPR: + break; } assert(0); return 0; @@ -163,6 +161,7 @@ static bool builtin_truthiness(Value *v, BuiltinType b) { } static bool val_truthiness(Value *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_VOID: return false; case TYPE_UNKNOWN: assert(0); return false; @@ -171,11 +170,10 @@ static bool val_truthiness(Value *v, Type *t) { case TYPE_FN: return v->fn != NULL; case TYPE_ARR: return t->arr.n > 0; case TYPE_SLICE: return v->slice.n > 0; - case TYPE_CALL: - case TYPE_USER: case TYPE_TYPE: case TYPE_TUPLE: case TYPE_STRUCT: + case TYPE_EXPR: break; } assert(0); @@ -238,6 +236,7 @@ static void u64_to_val(Value *v, BuiltinType v_type, U64 x) { /* rerturns a pointer to the underlying data of v, e.g. an I64 * if t is the builtin BUILTIN_I64 */ static void *val_get_ptr(Value *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_PTR: case TYPE_BUILTIN: @@ -248,19 +247,18 @@ static void *val_get_ptr(Value *v, Type *t) { case TYPE_SLICE: case TYPE_TYPE: return v; - case TYPE_USER: - case TYPE_CALL: - return val_get_ptr(v, type_user_underlying(t)); case TYPE_ARR: return v->arr; case TYPE_STRUCT: return v->struc; + case TYPE_EXPR: break; } assert(0); return NULL; } static void fprint_val_ptr(FILE *f, void *p, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_VOID: fprintf(f, "(void)"); @@ -323,14 +321,10 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { case TYPE_TYPE: fprint_type(f, *(Type **)p); break; - case TYPE_USER: - case TYPE_CALL: - fprint_val_ptr(f, p, type_user_underlying(t)); - break; case TYPE_STRUCT: fprintf(f, "["); /* TODO: change? when struct initializers are added */ - arr_foreach(t->struc.fields, Field, fi) { - if (fi != t->struc.fields) + arr_foreach(t->struc->fields, Field, fi) { + if (fi != t->struc->fields) fprintf(f, ", "); fprint_ident(f, fi->name); fprintf(f, ": "); @@ -338,7 +332,9 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) { } fprintf(f, "]"); break; + case TYPE_EXPR: break; } + assert(0); } static void fprint_val(FILE *f, Value v, Type *t) { @@ -354,6 +350,7 @@ static void fprint_val(FILE *f, Value v, Type *t) { } static void *val_ptr_to_free(Value *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -361,17 +358,17 @@ static void *val_ptr_to_free(Value *v, Type *t) { case TYPE_SLICE: case TYPE_VOID: case TYPE_UNKNOWN: - case TYPE_TYPE: return NULL; + case TYPE_TYPE: + return v->type->was_expr; case TYPE_ARR: return v->arr; case TYPE_TUPLE: return v->tuple; case TYPE_STRUCT: return v->struc; - case TYPE_USER: - case TYPE_CALL: - return val_ptr_to_free(v, type_user_underlying(t)); + case TYPE_EXPR: + break; } assert(0); return NULL; } @@ -454,24 +451,21 @@ static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinT } static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { + assert(from->flags & TYPE_IS_RESOLVED); + assert(to->flags & TYPE_IS_RESOLVED); + if (to->kind == TYPE_BUILTIN && to->builtin == BUILTIN_BOOL) { vout->boolv = val_truthiness(vin, from); return; } - if (from->kind == TYPE_USER || to->kind == TYPE_USER - || from->kind == TYPE_CALL || to->kind == TYPE_CALL) { - *vout = *vin; - return; - } switch (from->kind) { case TYPE_VOID: case TYPE_UNKNOWN: case TYPE_TUPLE: - case TYPE_USER: - case TYPE_CALL: case TYPE_TYPE: case TYPE_STRUCT: + case TYPE_EXPR: assert(0); break; case TYPE_BUILTIN: switch (to->kind) { @@ -491,8 +485,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { default: assert(0); break; } break; - case TYPE_USER: - case TYPE_CALL: + case TYPE_EXPR: case TYPE_STRUCT: case TYPE_SLICE: case TYPE_VOID: @@ -514,8 +507,6 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { case TYPE_FN: vout->fn = vin->fn; break; - case TYPE_USER: - case TYPE_CALL: case TYPE_SLICE: case TYPE_UNKNOWN: case TYPE_TUPLE: @@ -524,6 +515,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { case TYPE_BUILTIN: case TYPE_TYPE: case TYPE_STRUCT: + case TYPE_EXPR: assert(0); break; } break; @@ -549,12 +541,11 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { case TYPE_FN: vout->fn = vin->ptr; break; - case TYPE_USER: - case TYPE_CALL: case TYPE_SLICE: case TYPE_UNKNOWN: case TYPE_TUPLE: case TYPE_VOID: + case TYPE_EXPR: case TYPE_TYPE: case TYPE_STRUCT: assert(0); @@ -570,8 +561,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { case TYPE_ARR: vout->arr = vin->arr; break; - case TYPE_USER: - case TYPE_CALL: + case TYPE_EXPR: case TYPE_SLICE: case TYPE_FN: case TYPE_UNKNOWN: @@ -594,13 +584,12 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { case TYPE_SLICE: vout->slice = vin->slice; break; - case TYPE_USER: - case TYPE_CALL: case TYPE_FN: case TYPE_UNKNOWN: case TYPE_TUPLE: case TYPE_VOID: case TYPE_BUILTIN: + case TYPE_EXPR: case TYPE_TYPE: case TYPE_STRUCT: assert(0); break; @@ -611,6 +600,7 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) { /* type is the underlying type, not the pointer type. */ static void eval_deref(Value *v, void *ptr, Type *type) { + assert(type->flags & TYPE_IS_RESOLVED); switch (type->kind) { case TYPE_PTR: v->ptr = *(void **)ptr; break; case TYPE_ARR: v->arr = ptr; break; /* when we have a pointer to an array, it points directly to the data in that array. */ @@ -639,18 +629,16 @@ static void eval_deref(Value *v, void *ptr, Type *type) { case TYPE_TYPE: v->type = *(Type **)ptr; break; - case TYPE_USER: - case TYPE_CALL: - eval_deref(v, ptr, type_user_underlying(type)); - break; case TYPE_VOID: case TYPE_UNKNOWN: + case TYPE_EXPR: assert(0); break; } } /* inverse of eval_deref */ static void eval_deref_set(void *set, Value *to, Type *type) { + assert(type->flags & TYPE_IS_RESOLVED); switch (type->kind) { case TYPE_PTR: *(void **)set = to->ptr; break; case TYPE_ARR: memcpy(set, to->arr, compiler_sizeof(type)); break; /* TODO: test this */ @@ -679,12 +667,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) { case TYPE_TYPE: *(Type **)set = to->type; break; - case TYPE_USER: - case TYPE_CALL: - eval_deref_set(set, to, type_user_underlying(type)); - break; case TYPE_VOID: case TYPE_UNKNOWN: + case TYPE_EXPR: assert(0); break; } @@ -738,10 +723,10 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ } static void *eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr) { - Type *struct_type = type_inner(&dot_expr->binary.lhs->type); + Type *struct_type = &dot_expr->binary.lhs->type; bool is_ptr = struct_type->kind == TYPE_PTR; if (is_ptr) { - struct_type = type_inner(struct_type->ptr); + struct_type = struct_type->ptr; } eval_struct_find_offsets(struct_type); @@ -991,7 +976,6 @@ static void eval_numerical_bin_op(Value lhs, Type *lhs_type, BinaryOp op, Value static Value val_zero(Type *t) { Value val = {0}; - t = type_inner(t); switch (t->kind) { case TYPE_STRUCT: val.struc = err_calloc(1, compiler_sizeof(t)); @@ -1194,7 +1178,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value from, to; Value stepval; stepval.i64 = 1; - Type i64t; + Type i64t = {0}; i64t.flags = TYPE_IS_RESOLVED; i64t.kind = TYPE_BUILTIN; i64t.builtin = BUILTIN_I64; @@ -1228,7 +1212,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { Value lhs = x; Value rhs = to; assert(ea->type.kind == TYPE_BUILTIN); - Type boolt; + Type boolt = {0}; boolt.flags = TYPE_IS_RESOLVED; boolt.kind = TYPE_BUILTIN; boolt.builtin = BUILTIN_BOOL; @@ -1345,15 +1329,11 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { } int index = ident_index_in_decl(e->ident, d); assert(index != -1); + *v = *decl_val_at_index(d, index); 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_IS_RESOLVED; - v->type->kind = TYPE_USER; - v->type->user.decl = d; - v->type->user.index = index; - } else { - *v = *decl_val_at_index(d, index); + /* make sure was_expr is set */ + /* NOTE: this will be freed (see val_ptr_to_free) */ + v->type->was_expr = err_malloc(sizeof *v->type->was_expr); } } else { char *s = ident_to_str(e->ident); diff --git a/instance_table.c b/instance_table.c index 63879ce..d370a2a 100644 --- a/instance_table.c +++ b/instance_table.c @@ -64,6 +64,7 @@ static void fprint_val(FILE *f, Value v, Type *t); /* DELME */ static void fprint_type(FILE *out, Type *t); /* !! */ /* Note that for these value hashing functions, values of different types may collide */ static U64 val_ptr_hash(void *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_VOID: return 0; case TYPE_UNKNOWN: return 0; @@ -97,9 +98,6 @@ static U64 val_ptr_hash(void *v, Type *t) { } case TYPE_PTR: return (U64)*(void **)v; case TYPE_TYPE: return (U64)*(Type **)v; - case TYPE_USER: - case TYPE_CALL: - return val_ptr_hash(v, type_inner(t)); case TYPE_ARR: { U32 x = 1; U64 hash = 0; @@ -124,12 +122,13 @@ static U64 val_ptr_hash(void *v, Type *t) { case TYPE_STRUCT: { U32 x = 1; U64 hash = 0; - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { hash += (U64)x * val_ptr_hash((char *)v + f->offset, f->type); x = rand_u32(x); } return hash; } + case TYPE_EXPR: break; } assert(0); return 0; @@ -140,6 +139,7 @@ static U64 val_hash(Value v, Type *t) { } static bool val_ptr_eq(void *u, void *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_BUILTIN: switch (t->builtin) { @@ -163,9 +163,6 @@ static bool val_ptr_eq(void *u, void *v, Type *t) { return false; case TYPE_FN: return *(FnExpr **)u == *(FnExpr **)v; - case TYPE_USER: - case TYPE_CALL: - return val_ptr_eq(u, v, type_inner(t)); case TYPE_PTR: return *(void **)u == *(void **)v; case TYPE_TYPE: @@ -205,11 +202,12 @@ static bool val_ptr_eq(void *u, void *v, Type *t) { return true; } case TYPE_STRUCT: - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { if (!val_ptr_eq((char *)u + f->offset, (char *)v + f->offset, f->type)) return false; } return true; + case TYPE_EXPR: break; } assert(0); return false; @@ -1,7 +1,9 @@ /* TODO: -struct parameters -- struct type parameters +get rid of TYPE_USER +- don't do automatic type conversion + +functions returning Types test ArrInt @= Arr(int); packages @@ -167,6 +167,10 @@ static Keyword builtin_type_to_kw(BuiltinType t) { /* returns the number of characters written, not including the null character */ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { + if ((t->flags & TYPE_IS_RESOLVED) && t->was_expr) { + /* TODO: improve this (see also: case TYPE_EXPR) */ + return str_copy(buffer, bufsize, "<type expression>"); + } switch (t->kind) { case TYPE_VOID: return str_copy(buffer, bufsize, "void"); @@ -206,7 +210,7 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { } case TYPE_STRUCT: { size_t written = str_copy(buffer, bufsize, "struct { "); - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { written += type_to_str_(f->type, buffer + written, bufsize - written); written += str_copy(buffer + written, bufsize - written, "; "); } @@ -248,23 +252,9 @@ 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_IS_RESOLVED) - ? t->user.decl->idents[t->user.index] - : t->user.ident); - size_t ret = str_copy(buffer, bufsize, ident_str); - free(ident_str); - return ret; - } - case TYPE_CALL: { - size_t written = 0; - written += type_to_str_(t->call.calling, buffer + written, bufsize - written); - written += str_copy(buffer + written, bufsize - written, "("); - /* TODO: show values if resolved */ - written += str_copy(buffer + written, bufsize - written, "..."); - written += str_copy(buffer + written, bufsize - written, ")"); - return written; - } + case TYPE_EXPR: + /* TODO: improve this... we're gonna need expr_to_str ): */ + return str_copy(buffer, bufsize, "<type expression>"); } assert(0); @@ -390,6 +380,43 @@ static Token *expr_find_end(Parser *p, ExprEndFlags flags, bool *is_vbs) { } } +/* parses, e.g. "(3, 5, foo)" */ +static bool parse_args(Parser *p, Argument **args) { + Tokenizer *t = p->tokr; + Token *start = t->token; + assert(token_is_kw(start, KW_LPAREN)); + *args = NULL; + t->token++; /* move past ( */ + if (!token_is_kw(t->token, KW_RPAREN)) { + /* non-empty arg list */ + while (1) { + if (t->token->kind == TOKEN_EOF) { + tokr_err(t, "Expected argument list to continue."); + info_print(start->where, "This is where the argument list starts."); + return false; + } + Argument *arg = parser_arr_add(p, args); + arg->where = t->token->where; + /* named arguments */ + if (t->token->kind == TOKEN_IDENT && token_is_kw(t->token + 1, KW_EQ)) { + arg->name = t->token->ident; + t->token += 2; + } else { + arg->name = NULL; + } + if (!parse_expr(p, &arg->val, expr_find_end(p, EXPR_CAN_END_WITH_COMMA, NULL))) { + return false; + } + if (token_is_kw(t->token, KW_RPAREN)) + break; + assert(token_is_kw(t->token, KW_COMMA)); + t->token++; /* move past , */ + } + } + t->token++; /* move past ) */ + return true; +} + static bool parse_type(Parser *p, Type *type) { Tokenizer *t = p->tokr; type->where = t->token->where; @@ -525,20 +552,14 @@ static bool parse_type(Parser *p, Type *type) { case KW_STRUCT: /* struct */ type->kind = TYPE_STRUCT; - type->struc.fields = NULL; + type->struc = parser_malloc(p, sizeof *type->struc); + type->struc->flags = 0; + /* help cgen out */ + type->struc->c.name = NULL; + type->struc->c.id = 0; + type->struc->fields = NULL; t->token++; - if (token_is_kw(t->token, KW_LPAREN)) { - /* struct parameters */ - t->token++; - if (token_is_kw(t->token, KW_RPAREN)) { - t->token--; - err_print(t->token->where, "Expected parameters to struct, but found none."); - return false; - } - - if (!parse_decl_list(p, &type->struc.params, DECL_END_RPAREN_COMMA)) - return false; - } else if (!token_is_kw(t->token, KW_LBRACE)) { + if (!token_is_kw(t->token, KW_LBRACE)) { err_print(t->token->where, "Expected { or ( to follow struct."); return false; } @@ -561,7 +582,7 @@ static bool parse_type(Parser *p, Type *type) { long idx = 0; arr_foreach(field_decl.idents, Identifier, fident) { Type *ftype = field_decl.type.kind == TYPE_TUPLE ? &field_decl.type.tuple[idx] : &field_decl.type; - Field *f = parser_arr_add(p, &type->struc.fields); + Field *f = parser_arr_add(p, &type->struc->fields); f->name = *fident; f->type = parser_malloc(p, sizeof *f->type); *f->type = *ftype; @@ -576,15 +597,14 @@ static bool parse_type(Parser *p, Type *type) { return false; } break; - case TOKEN_IDENT: - /* user-defined type */ - type->kind = TYPE_USER; - type->user.ident = t->token->ident; - t->token++; - break; default: - tokr_err(t, "Unrecognized type."); - return false; + /* TYPE_EXPR */ + if (parse_expr(p, type->expr = parser_new_expr(p), expr_find_end(p, 0, NULL))) { + type->kind = TYPE_EXPR; + } else { + tokr_err(t, "Unrecognized type."); + return false; + } } return true; @@ -882,43 +902,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { return ret; } -/* parses, e.g. "(3, 5, foo)" */ -static bool parse_args(Parser *p, Argument **args) { - Tokenizer *t = p->tokr; - Token *start = t->token; - assert(token_is_kw(start, KW_LPAREN)); - *args = NULL; - t->token++; /* move past ( */ - if (!token_is_kw(t->token, KW_RPAREN)) { - /* non-empty arg list */ - while (1) { - if (t->token->kind == TOKEN_EOF) { - tokr_err(t, "Expected argument list to continue."); - info_print(start->where, "This is where the argument list starts."); - return false; - } - Argument *arg = parser_arr_add(p, args); - arg->where = t->token->where; - /* named arguments */ - if (t->token->kind == TOKEN_IDENT && token_is_kw(t->token + 1, KW_EQ)) { - arg->name = t->token->ident; - t->token += 2; - } else { - arg->name = NULL; - } - if (!parse_expr(p, &arg->val, expr_find_end(p, EXPR_CAN_END_WITH_COMMA, NULL))) { - return false; - } - if (token_is_kw(t->token, KW_RPAREN)) - break; - assert(token_is_kw(t->token, KW_COMMA)); - t->token++; /* move past , */ - } - } - t->token++; /* move past ) */ - return true; -} - static void fprint_expr(FILE *out, Expression *e); @@ -7,11 +7,21 @@ // "); // }; -Foo @= struct(x @ int) { - a: [x]float; -}; +// f @= fn(x @ int) Type { +// struct { +// a: [x]float; +// } +// }; + + main @= fn() { - f : Foo(13); -// puti(f.a[12]); + +t @= struct { + A: int; + b: int; +}; +x : t; + y := x; + };
\ No newline at end of file @@ -12,30 +12,6 @@ #include <float.h> #include "types.h" - -/* can be used on TYPE_USERs and TYPE_CALLs */ -static Type *type_user_underlying(Type *t) { - assert(t->flags & TYPE_IS_RESOLVED); - switch (t->kind) { - case TYPE_USER: { - Declaration *d = t->user.decl; - assert(d->flags & DECL_FOUND_VAL); - return (d->type.kind == TYPE_TUPLE ? d->val.tuple[t->user.index] : d->val).type; - } - case TYPE_CALL: - return &t->call.instance->type; - default: assert(0); - } -} - -static Type *type_inner(Type *t) { - assert(t->flags & TYPE_IS_RESOLVED); - while (t->kind == TYPE_USER) { - t = type_user_underlying(t); - } - return t; -} - #include "allocator.c" #include "arr.c" #include "location.c" diff --git a/typedefs_cgen.c b/typedefs_cgen.c index 422e6cd..71b1c5f 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -36,35 +36,33 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) { d->c.ids = allocr_calloc(g->allocr, arr_len(d->idents), sizeof *d->c.ids); /* generate typedef */ IdentID id = 0; - if (g->block != NULL || g->fn != NULL) id = d->c.ids[idx] = g->ident_counter++; + if (g->block != NULL || g->fn != NULL) + id = d->c.ids[idx] = g->ident_counter++; if (val->type->kind == TYPE_STRUCT) { /* we'll actually define the struct later; here we can just declare it */ cgen_write(g, "struct "); - if (g->block == NULL) { - /* we can refer to this by its name */ - cgen_ident(g, i); - } else { - /* we need to use an ID ): */ + if (id) { cgen_ident_id(g, id); + val->type->struc->c.id = id; + } else { + cgen_ident(g, i); + val->type->struc->c.name = i; } cgen_write(g, ";"); - cgen_nl(g); - continue; - } - cgen_write(g, "typedef "); - if (!cgen_type_pre(g, val->type, d->where)) return false; - cgen_write(g, " "); - if (g->block == NULL && g->fn == NULL) { - /* we can refer to this by its name */ - cgen_ident(g, i); } else { - /* we need to use an ID ): */ - cgen_ident_id(g, id); - } - if (val->type->kind != TYPE_STRUCT) { - if (!cgen_type_post(g, val->type, d->where)) return false; + cgen_write(g, "typedef "); + if (!cgen_type_pre(g, val->type, d->where)) return false; + cgen_write(g, " "); + if (id) { + cgen_ident_id(g, id); + } else { + cgen_ident(g, i); + } + if (val->type->kind != TYPE_STRUCT) { + if (!cgen_type_post(g, val->type, d->where)) return false; + } + cgen_write(g, ";"); } - cgen_write(g, ";"); cgen_nl(g); } } @@ -28,11 +28,7 @@ static bool type_eq(Type *a, Type *b) { assert(a->flags & TYPE_IS_RESOLVED); assert(b->flags & TYPE_IS_RESOLVED); - if ((a->kind == TYPE_USER || a->kind == TYPE_CALL) && a->user.is_alias) - return type_eq(type_user_underlying(a), b); - if ((b->kind == TYPE_USER || a->kind == TYPE_CALL) && b->user.is_alias) - return type_eq(a, type_user_underlying(b)); - + /* TODO: deal with was_expr */ if (a->kind != b->kind) return false; if (b->flags & TYPE_IS_FLEXIBLE) { @@ -55,10 +51,6 @@ static bool type_eq(Type *a, Type *b) { case TYPE_VOID: return true; case TYPE_UNKNOWN: assert(0); return false; case TYPE_TYPE: return true; - case TYPE_USER: - return a->user.decl == b->user.decl && a->user.index == b->user.index; - case TYPE_CALL: - return a->call.instance == b->call.instance; case TYPE_BUILTIN: return a->builtin == b->builtin; case TYPE_STRUCT: return false; @@ -97,6 +89,8 @@ static bool type_eq(Type *a, Type *b) { return type_eq(a->slice, b->slice); case TYPE_PTR: return type_eq(a->ptr, b->ptr); + case TYPE_EXPR: + break; } assert(0); return false; @@ -433,6 +427,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) { static bool type_resolve(Typer *tr, Type *t, Location where) { Evaluator *ev = tr->evalr; if (t->flags & TYPE_IS_RESOLVED) return true; + t->was_expr = NULL; switch (t->kind) { case TYPE_ARR: { /* it's an array */ @@ -488,62 +483,39 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { if (!type_resolve(tr, t->slice, where)) return false; break; - case TYPE_USER: { - t->flags |= TYPE_IS_RESOLVED; /* pre-resolve type to avoid infinite recursion */ - /* find declaration */ - Identifier ident = t->user.ident; - IdentDecl *idecl = ident_decl(ident); - if (!idecl) { - char *s = ident_to_str(ident); - err_print(where, "Use of undeclared type %s.", s); - free(s); - return false; - } - assert(idecl->kind == IDECL_DECL); - Declaration *decl = idecl->decl; - /* now, type the declaration (in case we are using it before its declaration) */ - if (!types_decl(tr, decl)) - return false; - int index = ident_index_in_decl(ident, idecl->decl); - /* make sure it's actually a type */ - if (decl_type_at_index(decl, index)->kind != TYPE_TYPE) { - char *s = ident_to_str(ident); - err_print(where, "Use of non-type identifier %s as type.", s); - info_print(decl->where, "%s is declared here.", s); - free(s); - return false; - } - /* finally, set decl and index */ - t->user.decl = decl; - t->user.index = index; - if (decl->flags & DECL_IS_PARAM) { - t->user.is_alias = true; /* type parameters are aliases */ - } - } break; case TYPE_STRUCT: - arr_foreach(t->struc.fields, Field, f) { + arr_foreach(t->struc->fields, Field, f) { if (!type_resolve(tr, f->type, where)) return false; } break; + case TYPE_EXPR: { + Value typeval; + if (!types_expr(tr, t->expr)) + return false; + t->was_expr = t->expr; + if (!eval_expr(tr->evalr, t->expr, &typeval)) + return false; + *t = *typeval.type; + } break; case TYPE_UNKNOWN: case TYPE_VOID: case TYPE_TYPE: case TYPE_BUILTIN: break; } + assert(t->kind != TYPE_EXPR); t->flags |= TYPE_IS_RESOLVED; return true; } static bool type_can_be_truthy(Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); switch (t->kind) { case TYPE_VOID: case TYPE_TUPLE: case TYPE_ARR: case TYPE_TYPE: - case TYPE_USER: - case TYPE_CALL: case TYPE_STRUCT: return false; case TYPE_FN: @@ -552,6 +524,8 @@ static bool type_can_be_truthy(Type *t) { case TYPE_PTR: case TYPE_SLICE: return true; + case TYPE_EXPR: + break; } assert(0); return false; @@ -564,20 +538,11 @@ typedef enum { } Status; static Status type_cast_status(Type *from, Type *to) { + assert(from->flags & TYPE_IS_RESOLVED); + assert(to->flags & TYPE_IS_RESOLVED); + if (to->kind == TYPE_UNKNOWN) return STATUS_NONE; - if (from->kind == TYPE_USER || from->kind == TYPE_CALL) { - if (from->user.is_alias) { - return type_cast_status(type_user_underlying(from), to); - } - return type_eq(type_user_underlying(from), to) ? STATUS_NONE : STATUS_ERR; - } - if (to->kind == TYPE_USER || to->kind == TYPE_CALL) { - if (to->user.is_alias) { - return type_cast_status(from, type_user_underlying(to)); - } - return type_eq(from, type_user_underlying(to)) ? STATUS_NONE : STATUS_ERR; - } switch (from->kind) { case TYPE_UNKNOWN: return STATUS_NONE; case TYPE_STRUCT: @@ -607,8 +572,9 @@ static Status type_cast_status(Type *from, Type *to) { case TYPE_STRUCT: case TYPE_ARR: case TYPE_VOID: - case TYPE_USER: case TYPE_CALL: /* handled above */ return STATUS_ERR; + case TYPE_EXPR: + assert(0); } break; case BUILTIN_F32: @@ -644,8 +610,7 @@ static Status type_cast_status(Type *from, Type *to) { if (to->kind == TYPE_PTR && type_eq(from->slice, to->ptr)) return STATUS_NONE; return STATUS_ERR; - case TYPE_USER: - case TYPE_CALL: + case TYPE_EXPR: break; } assert(0); @@ -739,6 +704,7 @@ static bool types_expr(Typer *tr, Expression *e) { if (e->flags & EXPR_FOUND_TYPE) return true; Type *t = &e->type; t->flags = 0; + t->was_expr = NULL; t->kind = TYPE_UNKNOWN; /* default to unknown type (in the case of an error) */ e->flags |= EXPR_FOUND_TYPE; /* even if failed, pretend we found the type */ switch (e->kind) { @@ -873,7 +839,7 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } } - Type ptr_type; + Type ptr_type = {0}; if (uses_ptr) { ptr_type.flags = TYPE_IS_RESOLVED; ptr_type.kind = TYPE_PTR; @@ -992,6 +958,7 @@ static bool types_expr(Typer *tr, Expression *e) { } else { next_type->kind = TYPE_VOID; next_type->flags = TYPE_IS_RESOLVED; + next_type->was_expr = NULL; } if (!type_eq(curr_type, next_type)) { char *currstr = type_to_str(curr_type); @@ -1184,11 +1151,12 @@ static bool types_expr(Typer *tr, Expression *e) { copy_fn_expr(&cop, &fn_copy, fn, true); fn = &fn_copy; - Type table_index_type; + Type table_index_type = {0}; table_index_type.flags = TYPE_IS_RESOLVED; table_index_type.kind = TYPE_TUPLE; table_index_type.tuple = NULL; Type *u64t = arr_add(&table_index_type.tuple); + u64t->was_expr = NULL; u64t->flags = TYPE_IS_RESOLVED; u64t->kind = TYPE_BUILTIN; u64t->builtin = BUILTIN_U64; @@ -1447,19 +1415,6 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } } else { - while (rhs_type->kind == TYPE_USER) { - if (rhs_type->user.is_alias) - rhs_type = type_user_underlying(rhs_type); - else - break; - } - while (lhs_type->kind == TYPE_USER) { - if (lhs_type->user.is_alias) - lhs_type = type_user_underlying(lhs_type); - else - break; - } - /* numerical binary ops */ if (lhs_type->kind == TYPE_BUILTIN && type_eq(lhs_type, rhs_type)) { /* int + int, etc. */ @@ -1562,16 +1517,15 @@ static bool types_expr(Typer *tr, Expression *e) { break; case BINARY_DOT: { if (!types_expr(tr, lhs)) return false; - Type *struct_type = type_inner(lhs_type); + Type *struct_type = lhs_type; if (struct_type->kind == TYPE_PTR) struct_type = struct_type->ptr; - struct_type = type_inner(struct_type); if (struct_type->kind == TYPE_STRUCT) { bool is_field = false; if (rhs->kind == EXPR_IDENT) { /* maybe accessing a field? */ - arr_foreach(struct_type->struc.fields, Field, f) { + arr_foreach(struct_type->struc->fields, Field, f) { if (f->name == rhs->ident) { is_field = true; *t = *f->type; @@ -1600,7 +1554,7 @@ static bool types_expr(Typer *tr, Expression *e) { } if (!eval_expr(tr->evalr, rhs, &field_name)) return false; - arr_foreach(struct_type->struc.fields, Field, f) { + arr_foreach(struct_type->struc->fields, Field, f) { if (ident_eq_str(f->name, field_name.slice.data)) { is_field = true; *t = *f->type; @@ -1818,6 +1772,7 @@ static bool types_decl(Typer *tr, Declaration *d) { if (!success) { /* use unknown type if we didn't get the type */ d->type.flags = TYPE_IS_RESOLVED; + d->type.was_expr = NULL; d->type.kind = TYPE_UNKNOWN; tr->evalr->enabled = false; /* disable evaluator completely so that it doesn't accidentally try to access this declaration */ } @@ -68,25 +68,32 @@ typedef struct Page { MaxAlign data[]; } Page; -typedef struct { +typedef struct Allocator { Page *first; Page *last; } Allocator; -typedef struct { +typedef struct ArrBlock { void *data; size_t n; /* number of things in this block so far */ void *last; /* last one of them */ } ArrBlock; -typedef struct { +typedef struct BlockArr { size_t item_sz; int lg_block_sz; /* NOTE: dynamic array tends to over-allocate, so we're using our own */ ArrBlock *blocks; } BlockArr; -typedef struct { +typedef struct HashTable { + void *data; + bool *occupied; + U64 n; + U64 cap; +} HashTable; + +typedef struct Slice { I64 n; void *data; } Slice; @@ -122,7 +129,7 @@ typedef enum { IDECL_EXPR } IdentDeclKind; -typedef struct { +typedef struct IdentDecl { union { struct Declaration *decl; struct Expression *expr; /* for example, this identifier is declared in an each expression */ @@ -152,7 +159,7 @@ typedef struct IdentTree { typedef IdentTree *Identifier; -typedef struct { +typedef struct Identifiers { BlockArr trees; IdentTree *root; } Identifiers; @@ -242,7 +249,7 @@ typedef enum { NUM_LITERAL_FLOAT } NumLiteralKind; -typedef struct { +typedef struct NumLiteral { NumLiteralKind kind; union { UInteger intval; @@ -250,13 +257,13 @@ typedef struct { }; } NumLiteral; -typedef struct { +typedef struct StrLiteral { char *str; size_t len; } StrLiteral; /* NOTE: Location is typedef'd in util/err.c */ -typedef struct { +typedef struct Token { TokenKind kind; Location where; union { @@ -269,7 +276,7 @@ typedef struct { }; } Token; -typedef struct { +typedef struct Tokenizer { Allocator *allocr; Token *tokens; char *s; /* string being parsed */ @@ -290,9 +297,8 @@ typedef enum { TYPE_PTR, TYPE_SLICE, TYPE_TYPE, - TYPE_USER, /* user-defined type */ - TYPE_STRUCT, - TYPE_CALL /* "calling" a type function, e.g. Arr(int) */ + TYPE_EXPR, /* just use this expression as the type. this kind of type doesn't exist after resolving. */ + TYPE_STRUCT } TypeKind; typedef enum { @@ -311,17 +317,12 @@ typedef enum { } BuiltinType; /* field of a struct */ -typedef struct { +typedef struct Field { Identifier name; struct Type *type; size_t offset; /* offset during compile time */ } Field; -enum { - TYPE_IS_FLEXIBLE = 0x01, - TYPE_IS_RESOLVED = 0x02, - TYPE_STRUCT_FOUND_OFFSETS = 0x04, -}; typedef U8 Constness; @@ -329,15 +330,34 @@ typedef U8 Constness; #define CONSTNESS_SEMI ((Constness)1) #define CONSTNESS_YES ((Constness)2) -typedef struct { +typedef struct FnType { struct Type *types; /* dynamic array [0] = ret_type, [1:] = param_types */ Constness *constness; /* [i] = constness of param #i. iff no parameters are constant, this is NULL. don't use it as a dynamic array, because eventually it might not be. */ } FnType; +enum { + STRUCT_DEF_FOUND_OFFSETS = 0x00, +}; + +typedef struct { + Field *fields; + U16 flags; + size_t size; /* size of this struct during compile time */ + struct { + Identifier name; + IdentID id; + } c; +} StructDef; + +enum { + TYPE_IS_FLEXIBLE = 0x01, + TYPE_IS_RESOLVED = 0x02, +}; typedef struct Type { Location where; TypeKind kind; uint16_t flags; + struct Expression *was_expr; /* if non-NULL, indicates that this type used to be an expression (TYPE_EXPR) */ union { BuiltinType builtin; FnType fn; @@ -351,27 +371,8 @@ typedef struct Type { } arr; struct Type *ptr; struct Type *slice; - struct { - union { - struct { - struct Declaration *decl; - int index; /* index in decl */ - }; - Identifier ident; - }; - bool is_alias; /* is this an alias for a type, rather than a new type */ - } user; - struct { - Field *fields; - size_t size; /* size of this struct during compile time */ - struct Declaration *params; /* parameters to struct, NULL if this struct has no parameters */ - - } struc; - struct { - struct Type *calling; - struct Expression *args; - struct Instance *instance; /* instance of struct. set during type resolution. */ - } call; /* "calling" a function returning a type */ + StructDef *struc; /* it's a pointer so that multiple Types can reference the same struct definition */ + struct Expression *expr; }; } Type; @@ -448,7 +449,7 @@ typedef enum { BINARY_DOT } BinaryOp; -typedef struct { +typedef struct CallExpr { struct Expression *fn; union { struct Argument *args; @@ -460,7 +461,7 @@ typedef struct { } c; } CallExpr; -typedef struct { +typedef struct IfExpr { struct Expression *cond; /* NULL = this is an else */ struct Expression *next_elif; /* next elif/else of this statement */ struct { @@ -469,7 +470,7 @@ typedef struct { Block body; } IfExpr; -typedef struct { +typedef struct WhileExpr { struct Expression *cond; struct { IdentID id; @@ -506,13 +507,6 @@ typedef struct EachExpr { }; } EachExpr; -typedef struct { - void *data; - bool *occupied; /* OPTIM: use bits instead of bytes for bools */ - U64 n; - U64 cap; -} HashTable; - typedef struct FnExpr { struct Declaration *params; /* declarations of the parameters to this function */ struct Declaration *ret_decls; /* array of decls, if this has named return values. otherwise, NULL */ @@ -540,17 +534,17 @@ typedef struct Instance { } c; } Instance; -typedef struct { +typedef struct CastExpr { Type type; struct Expression *expr; } CastExpr; -typedef struct { +typedef struct NewExpr { Type type; struct Expression *n; /* e.g. for new(int, 5) */ } NewExpr; -typedef struct { +typedef struct SliceExpr { struct Expression *of; struct Expression *from; struct Expression *to; @@ -661,7 +655,7 @@ typedef enum { enum { RET_HAS_EXPR = 0x01, }; -typedef struct { +typedef struct Return { uint16_t flags; Expression expr; } Return; @@ -681,11 +675,11 @@ typedef struct Statement { }; } Statement; -typedef struct { +typedef struct ParsedFile { Statement *stmts; } ParsedFile; -typedef struct { +typedef struct Parser { Tokenizer *tokr; Allocator *allocr; Block *block; /* which block are we in? NULL = file scope */ @@ -697,7 +691,7 @@ typedef enum { DECL_END_LBRACE_COMMA } DeclEndKind; -typedef struct { +typedef struct Evaluator { Allocator *allocr; struct Typer *typer; bool returning; @@ -715,7 +709,7 @@ typedef struct Typer { FnExpr *fn; /* the function we're currently parsing. */ } Typer; -typedef struct { +typedef struct CGenerator { Allocator *allocr; FILE *outc; IdentID ident_counter; |