summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-30 16:16:32 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-30 16:16:32 -0500
commitdb0367b2aa29de32d941cdea9af810b7eef0b74a (patch)
treea8a65d65633acd609212443e60f5f12c1dfc232a
parent76ff5d914def4984d5b599177032ded71632a5ec (diff)
got rid of TYPE_USER!!
-rw-r--r--cgen.c96
-rw-r--r--copy.c31
-rw-r--r--decls_cgen.c2
-rw-r--r--eval.c112
-rw-r--r--instance_table.c14
-rw-r--r--main.c6
-rw-r--r--parse.c137
-rw-r--r--test.toc20
-rw-r--r--toc.c24
-rw-r--r--typedefs_cgen.c40
-rw-r--r--types.c111
-rw-r--r--types.h112
12 files changed, 295 insertions, 410 deletions
diff --git a/cgen.c b/cgen.c
index 44222b3..db44b76 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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
diff --git a/copy.c b/copy.c
index 3062115..f691d18 100644
--- a/copy.c
+++ b/copy.c
@@ -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);
diff --git a/eval.c b/eval.c
index e06dd9e..4150527 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/main.c b/main.c
index 1866e5f..e07c049 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/parse.c b/parse.c
index df47ee9..68e1652 100644
--- a/parse.c
+++ b/parse.c
@@ -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);
diff --git a/test.toc b/test.toc
index 8693412..0ee769f 100644
--- a/test.toc
+++ b/test.toc
@@ -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
diff --git a/toc.c b/toc.c
index cd931ed..203fddd 100644
--- a/toc.c
+++ b/toc.c
@@ -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);
}
}
diff --git a/types.c b/types.c
index f5b8e5e..5dac5e7 100644
--- a/types.c
+++ b/types.c
@@ -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 */
}
diff --git a/types.h b/types.h
index 599ca67..3d17f0a 100644
--- a/types.h
+++ b/types.h
@@ -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;