summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-07-10 15:53:56 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-07-10 15:54:00 -0400
commitec25b66e85765bafe7a944d805669c931026a5be (patch)
tree5c15ed5f09140ea3006d354bacc092c73771cde7
parent7196bd82bbeae548db7c4eb548023d79d169539f (diff)
made types 16 bytes
-rw-r--r--allocator.c2
-rw-r--r--cgen.c74
-rw-r--r--copy.c40
-rw-r--r--eval.c24
-rw-r--r--infer.c14
-rw-r--r--instance_table.c20
-rw-r--r--main.c4
-rw-r--r--parse.c32
-rw-r--r--types.c82
-rw-r--r--types.h20
10 files changed, 162 insertions, 150 deletions
diff --git a/allocator.c b/allocator.c
index 6573914..98005ef 100644
--- a/allocator.c
+++ b/allocator.c
@@ -25,7 +25,7 @@ static void *err_malloc(size_t bytes);
static void *err_calloc(size_t n, size_t sz);
static void *err_realloc(void *prev, size_t new_size);
#ifdef TOC_DEBUG
-#define NO_ALLOCATOR 0 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */
+#define NO_ALLOCATOR 1 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */
#endif
/* number of bytes a page hold, not including the header */
#define PAGE_BYTES (16384 - sizeof(Page))
diff --git a/cgen.c b/cgen.c
index 30a9703..88225be 100644
--- a/cgen.c
+++ b/cgen.c
@@ -186,14 +186,14 @@ static void cgen_type_pre(CGenerator *g, Type *t) {
cgen_write(g, "(*");
break;
case TYPE_ARR:
- cgen_type_pre(g, t->arr.of);
+ cgen_type_pre(g, t->arr->of);
cgen_write(g, "(");
break;
case TYPE_FN:
- if (cgen_uses_ptr(&t->fn.types[0])) {
+ if (cgen_uses_ptr(&t->fn->types[0])) {
cgen_write(g, "void");
} else {
- cgen_type_pre(g, &t->fn.types[0]);
+ cgen_type_pre(g, &t->fn->types[0]);
}
cgen_write(g, " (*");
break;
@@ -222,23 +222,26 @@ static void cgen_type_post(CGenerator *g, Type *t) {
break;
case TYPE_ARR:
assert(t->flags & TYPE_IS_RESOLVED);
- cgen_write(g, "[%lu])", (unsigned long)t->arr.n);
- cgen_type_post(g, t->arr.of);
+ cgen_write(g, "[%lu])", (unsigned long)t->arr->n);
+ cgen_type_post(g, t->arr->of);
break;
case TYPE_FN: {
- bool out_param = cgen_uses_ptr(&t->fn.types[0]);
+ Type *types = t->fn->types;
+ size_t ntypes = arr_len(types);
+ bool out_param = cgen_uses_ptr(&types[0]);
cgen_write(g, ")(");
- for (size_t i = 1; i < arr_len(t->fn.types); ++i) {
+ for (size_t i = 1; i < ntypes; ++i) {
+ Type *type = &types[i];
if (i != 1)
cgen_write(g, ", ");
- cgen_type_pre(g, &t->fn.types[i]);
- if (cgen_uses_ptr(&t->fn.types[i]))
+ cgen_type_pre(g, type);
+ if (cgen_uses_ptr(type))
cgen_write(g, "(*)");
- cgen_type_post(g, &t->fn.types[i]);
+ cgen_type_post(g, type);
}
if (out_param) {
- Type *ret_type = &t->fn.types[0];
- if (arr_len(t->fn.types) > 1)
+ Type *ret_type = &types[0];
+ if (ntypes > 1)
cgen_write(g, ", ");
if (ret_type->kind == TYPE_TUPLE) {
arr_foreach(ret_type->tuple, Type, x) {
@@ -255,11 +258,11 @@ static void cgen_type_post(CGenerator *g, Type *t) {
cgen_type_post(g, ret_type);
}
}
- if (arr_len(t->fn.types) == 1 && !out_param)
+ if (ntypes == 1 && !out_param)
cgen_write(g, "void");
cgen_write(g, ")");
if (!out_param)
- cgen_type_post(g, &t->fn.types[0]);
+ cgen_type_post(g, &types[0]);
} break;
case TYPE_BUILTIN:
case TYPE_UNKNOWN:
@@ -375,8 +378,8 @@ static void cgen_val_ptr_pre(CGenerator *g, void *v, Type *t) {
}
} break;
case TYPE_ARR:
- for (size_t i = 0; i < t->arr.n; ++i) {
- cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of);
+ for (size_t i = 0; i < t->arr->n; ++i) {
+ cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr->of), t->arr->of);
}
break;
case TYPE_FN:
@@ -403,9 +406,10 @@ static void cgen_val_ptr(CGenerator *g, void *v, Type *t) {
return;
case TYPE_ARR:
cgen_write(g, "{");
- for (size_t i = 0; i < t->arr.n; ++i) {
+ Type *of = t->arr->of;
+ for (size_t i = 0, n = t->arr->n; i < n; ++i) {
if (i) cgen_write(g, ", ");
- cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of);
+ cgen_val_ptr(g, (char *)v + i * compiler_sizeof(of), of);
}
cgen_write(g, "}");
break;
@@ -630,13 +634,14 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
}
cgen_write(g, ";");
break;
- case TYPE_ARR:
+ case TYPE_ARR: {
+ Type *of_type = type->arr->of;
cgen_write(g, "{");
cgen_nl(g);
cgen_write(g, "size_t i;");
- cgen_type_pre(g, type->arr.of);
+ cgen_type_pre(g, of_type);
cgen_write(g, "(*arr__in)");
- cgen_type_post(g, type->arr.of);
+ cgen_type_post(g, of_type);
cgen_write(g, " = ");
if (to_expr) {
cgen_expr(g, to_expr);
@@ -644,9 +649,9 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
cgen_write(g, to_str);
}
cgen_write(g, "; ");
- cgen_type_pre(g, type->arr.of);
+ cgen_type_pre(g, of_type);
cgen_write(g, "(*arr__out)");
- cgen_type_post(g, type->arr.of);
+ cgen_type_post(g, of_type);
cgen_write(g, " = ");
if (set_expr) {
cgen_expr(g, set_expr);
@@ -655,10 +660,10 @@ static void cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
}
cgen_write(g, ";");
cgen_nl(g);
- cgen_write(g, "for (i = 0; i < %lu; ++i) arr__out[i] = arr__in[i];", (unsigned long)type->arr.n);
+ cgen_write(g, "for (i = 0; i < %lu; ++i) arr__out[i] = arr__in[i];", (unsigned long)type->arr->n);
cgen_nl(g);
cgen_write(g, "}");
- break;
+ } break;
case TYPE_TUPLE:
assert(set_expr);
assert(to_expr);
@@ -700,7 +705,7 @@ static void cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents,
}
break;
case EXPR_CALL: {
- FnType *fn_type = &to->call.fn->type.fn;
+ FnType *fn_type = to->call.fn->type.fn;
Type *ret_type = &fn_type->types[0];
Constness *constness = fn_type->constness;
int i = 0;
@@ -803,8 +808,9 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
case EXPR_CALL: {
cgen_expr_pre(g, e->call.fn);
size_t i = 0;
- Constness *constness = e->call.fn->type.fn.constness;
- size_t nparams = arr_len(e->call.fn->type.fn.types)-1;
+ FnType *fn_type = e->call.fn->type.fn;
+ Constness *constness = fn_type->constness;
+ size_t nparams = arr_len(fn_type->types)-1;
arr_foreach(e->call.arg_exprs, Expression, arg) {
if (!constness || !arg_is_const(arg, constness[i])) {
cgen_arg_pre(g, arg);
@@ -869,7 +875,7 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) {
assert(s->of->type.kind == TYPE_ARR);
cgen_write(g, "mkslice_(");
cgen_expr(g, s->of);
- cgen_write(g, ", " U64_FMT, s->of->type.arr.n);
+ cgen_write(g, ", " U64_FMT, s->of->type.arr->n);
cgen_write(g, ")");
}
cgen_write(g, "; i64 ");
@@ -1177,7 +1183,7 @@ static void cgen_expr(CGenerator *g, Expression *e) {
} else if (cgen_uses_ptr(&e->type)) {
cgen_ident_id(g, e->cgen.id);
} else {
- FnType *fn_type = &e->call.fn->type.fn;
+ FnType *fn_type = e->call.fn->type.fn;
cgen_expr(g, e->call.fn);
cgen_write(g, "(");
bool first_arg = true;
@@ -1737,9 +1743,9 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
cgen_write(g, "; ");
break;
case TYPE_ARR:
- cgen_type_pre(g, of_type->arr.of);
+ cgen_type_pre(g, of_type->arr->of);
cgen_write(g, " (* of_)");
- cgen_type_post(g, of_type->arr.of);
+ cgen_type_post(g, of_type->arr->of);
cgen_write(g, " = ");
if (uses_ptr) cgen_write(g, "*");
cgen_expr(g, fo->of);
@@ -1810,7 +1816,7 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
cgen_write(g, ", (*end_) = p_ + ");
switch (of_type->kind) {
case TYPE_ARR:
- cgen_write(g, U64_FMT, (U64)of_type->arr.n);
+ cgen_write(g, U64_FMT, (U64)of_type->arr->n);
break;
case TYPE_SLICE:
cgen_write(g, "of_.len");
@@ -1869,7 +1875,7 @@ static void cgen_fn_decl(CGenerator *g, FnExpr *f) {
Type *t = &f->foreign.type;
/* foreign function declaration */
cgen_write(g, "extern ");
- Type *fn_types = t->fn.types;
+ Type *fn_types = t->fn->types;
const char *foreign_name = f->foreign.name;
CType *ctypes = f->foreign.ctypes;
if (ctypes[0].kind == CTYPE_NONE) {
diff --git a/copy.c b/copy.c
index b6716f5..ea5a9d4 100644
--- a/copy.c
+++ b/copy.c
@@ -34,6 +34,10 @@ static Copier copier_create(Allocator *a, Block *b) {
return c;
}
+static inline void *copier_malloc(Copier *c, size_t n) {
+ return allocr_malloc(c->allocr, n);
+}
+
static void copy_val(Allocator *a, Value *out, Value in, Type *t) {
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
@@ -57,7 +61,7 @@ static void copy_val(Allocator *a, Value *out, Value in, Type *t) {
*out = in;
break;
case TYPE_ARR: {
- size_t bytes = (size_t)t->arr.n * compiler_sizeof(t->arr.of);
+ size_t bytes = (size_t)t->arr->n * compiler_sizeof(t->arr->of);
out->arr = allocr_malloc(a, bytes);
memcpy(out->arr, in.arr, bytes);
} break;
@@ -129,11 +133,17 @@ static void copy_type(Copier *c, Type *out, Type *in) {
out->expr = copy_expr_(c, in->expr);
break;
case TYPE_FN: {
- size_t ntypes = arr_len(in->fn.types);
- out->fn.types = NULL;
- arr_set_lena(out->fn.types, ntypes, c->allocr);
+ FnType *outfn = copier_malloc(c, sizeof *outfn), *infn = in->fn;
+ size_t ntypes = arr_len(infn->types);
+ *outfn = *infn;
+ size_t constness_bytes = (ntypes-1) * sizeof *outfn->constness;
+ outfn->constness = allocr_malloc(c->allocr, constness_bytes);
+ memmove(outfn->constness, infn->constness, constness_bytes);
+
+ outfn->types = NULL;
+ arr_set_lena(outfn->types, ntypes, c->allocr);
for (size_t i = 0; i < ntypes; ++i) {
- copy_type(c, &out->fn.types[i], &in->fn.types[i]);
+ copy_type(c, &outfn->types[i], &infn->types[i]);
}
} break;
case TYPE_TUPLE: {
@@ -144,14 +154,14 @@ static void copy_type(Copier *c, Type *out, Type *in) {
copy_type(c, &out->tuple[i], &in->tuple[i]);
}
} break;
- case TYPE_ARR:
- if (in->flags & TYPE_IS_RESOLVED) {
- out->arr.n = in->arr.n;
- } else {
- out->arr.n_expr = copy_expr_(c, in->arr.n_expr);
+ case TYPE_ARR:{
+ ArrType *oarr = out->arr = copier_malloc(c, sizeof *oarr), *iarr = in->arr;
+ *oarr = *iarr;
+ if (!(in->flags & TYPE_IS_RESOLVED)) {
+ oarr->n_expr = copy_expr_(c, iarr->n_expr);
}
- out->arr.of = copy_type_(c, in->arr.of);
- break;
+ oarr->of = copy_type_(c, in->arr->of);
+ } break;
case TYPE_PTR:
out->ptr = copy_type_(c, in->ptr);
break;
@@ -179,10 +189,6 @@ static Type *copy_type_(Copier *c, Type *in) {
return out;
}
-static inline void *copier_malloc(Copier *c, size_t n) {
- return allocr_malloc(c->allocr, n);
-}
-
enum {
COPY_FN_EXPR_DONT_COPY_BODY = 0x01
};
@@ -195,7 +201,7 @@ static void copy_fn_expr(Copier *c, FnExpr *fout, FnExpr *fin, U8 flags) {
copy_expr(c, fout->foreign.name_expr = copier_malloc(c, sizeof *fin->foreign.name_expr), fin->foreign.name_expr);
copy_expr(c, fout->foreign.lib_expr = copier_malloc(c, sizeof *fin->foreign.lib_expr), fin->foreign.lib_expr);
copy_type(c, &fout->foreign.type, &fin->foreign.type);
- size_t nctypes = arr_len(fin->foreign.type.fn.types);
+ size_t nctypes = arr_len(fin->foreign.type.fn->types);
fout->foreign.ctypes = copier_malloc(c, nctypes * sizeof(CType));
memcpy(fout->foreign.ctypes, fin->foreign.ctypes, nctypes * sizeof(CType));
} else {
diff --git a/eval.c b/eval.c
index 3be73ea..d6a3487 100644
--- a/eval.c
+++ b/eval.c
@@ -52,7 +52,7 @@ static inline bool val_truthiness(Value v, Type *t) {
case TYPE_BUILTIN: return builtin_truthiness(v, t->builtin);
case TYPE_PTR: return v.ptr != NULL;
case TYPE_FN: return v.fn != NULL;
- case TYPE_ARR: return t->arr.n != 0;
+ case TYPE_ARR: return t->arr->n != 0;
case TYPE_SLICE: return v.slice.len != 0;
case TYPE_TUPLE:
case TYPE_STRUCT:
@@ -211,13 +211,13 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
} break;
case TYPE_ARR: {
fprintf(f, "["); /* @TODO: change? when array initializers are added */
- size_t n = (size_t)t->arr.n;
+ size_t n = (size_t)t->arr->n;
if (n > 5) n = 5;
for (size_t i = 0; i < n; ++i) {
if (i) fprintf(f, ", ");
- fprint_val_ptr(f, (char *)p + i * compiler_sizeof(t->arr.of), t->arr.of);
+ fprint_val_ptr(f, (char *)p + i * compiler_sizeof(t->arr->of), t->arr->of);
}
- if (t->arr.n > n) {
+ if (t->arr->n > n) {
fprintf(f, ", ...");
}
fprintf(f, "]");
@@ -232,7 +232,7 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
if (n > 5) n = 5;
for (I64 i = 0; i < n; ++i) {
if (i) fprintf(f, ", ");
- fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr.of), t->arr.of);
+ fprint_val_ptr(f, (char *)slice.data + i * (I64)compiler_sizeof(t->arr->of), t->arr->of);
}
if (slice.len > n) {
fprintf(f, ", ...");
@@ -604,13 +604,13 @@ static Status eval_val_ptr_at_index(Location where, Value *arr, U64 i, Type *arr
}
switch (arr_type->kind) {
case TYPE_ARR: {
- U64 arr_sz = (U64)arr_type->arr.n;
+ U64 arr_sz = (U64)arr_type->arr->n;
if (i > arr_sz) { /* this is INTENTIONALLY > and not >=, because it's okay to have a pointer to one past the end of an array */
err_print(where, "Array out of bounds (index = %lu, array size = %lu)\n", (unsigned long)i, (unsigned long)arr_sz);
return false;
}
- *ptr = (char *)arr_ptr + compiler_sizeof(arr_type->arr.of) * i;
- if (type) *type = arr_type->arr.of;
+ *ptr = (char *)arr_ptr + compiler_sizeof(arr_type->arr->of) * i;
+ if (type) *type = arr_type->arr->of;
} break;
case TYPE_SLICE: {
Slice slice = *(Slice *)arr_ptr;
@@ -993,7 +993,7 @@ static Value val_zero(Allocator *a, Type *t) {
val.struc = allocr_calloc(a, 1, compiler_sizeof(t));
break;
case TYPE_ARR:
- val.arr = allocr_calloc(a, (size_t)t->arr.n, compiler_sizeof(t->arr.of));
+ val.arr = allocr_calloc(a, (size_t)t->arr->n, compiler_sizeof(t->arr->of));
break;
default:
break;
@@ -1278,7 +1278,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
if (!eval_expr(ev, &e->call.arg_exprs[i], &args[i]))
return false;
}
- Type *ret_type = &e->call.fn->type.fn.types[0];
+ Type *ret_type = &e->call.fn->type.fn->types[0];
bool success = foreign_call(&ev->ffmgr, fn, ret_type, &e->call.arg_exprs[0].type, sizeof(Expression), args, nargs, e->where, v);
free(args);
if (!success)
@@ -1391,7 +1391,7 @@ static Status eval_expr(Evaluator *ev, Expression *e, Value *v) {
Type *of_type = &s->of->type;
if (!eval_expr(ev, s->of, &ofv))
return false;
- U64 n = of_type->kind == TYPE_ARR ? of_type->arr.n : (U64)ofv.slice.len;
+ U64 n = of_type->kind == TYPE_ARR ? of_type->arr->n : (U64)ofv.slice.len;
U64 from, to;
if (s->from) {
Value fromv;
@@ -1680,7 +1680,7 @@ static Status eval_stmt(Evaluator *ev, Statement *stmt) {
}
switch (of_type->kind) {
case TYPE_ARR:
- len = (I64)of_type->arr.n;
+ len = (I64)of_type->arr->n;
if (uses_ptr) {
of.arr = of.ptr;
}
diff --git a/infer.c b/infer.c
index aff8c6a..9778fb0 100644
--- a/infer.c
+++ b/infer.c
@@ -99,14 +99,14 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
}
} break;
case TYPE_FN: {
- if (match->fn.constness || to->fn.constness) {
+ if (match->fn->constness || to->fn->constness) {
return true;
}
if (to->kind != TYPE_FN) return true;
- if (arr_len(match->fn.types) != arr_len(to->fn.types)) return true;
- size_t i, len = arr_len(match->fn.types);
+ if (arr_len(match->fn->types) != arr_len(to->fn->types)) return true;
+ size_t i, len = arr_len(match->fn->types);
for (i = 0; i < len; ++i) {
- if (!infer_from_type(tr, &match->fn.types[i], &to->fn.types[i], idents, vals, types, where))
+ if (!infer_from_type(tr, &match->fn->types[i], &to->fn->types[i], idents, vals, types, where))
return false;
}
} break;
@@ -137,11 +137,11 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
Type n_type;
construct_resolved_builtin_type(&n_type, BUILTIN_I64);
Value val;
- val.i64 = (I64)to->arr.n;
+ val.i64 = (I64)to->arr->n;
/* try to match match's n expr to to's value */
- if (!infer_from_expr(tr, match->arr.n_expr, val, &n_type, where, idents, vals, types))
+ if (!infer_from_expr(tr, match->arr->n_expr, val, &n_type, where, idents, vals, types))
return false;
- if (!infer_from_type(tr, match->arr.of, to->arr.of, idents, vals, types, where))
+ if (!infer_from_type(tr, match->arr->of, to->arr->of, idents, vals, types, where))
return false;
} break;
}
diff --git a/instance_table.c b/instance_table.c
index 870ff60..0f1004e 100644
--- a/instance_table.c
+++ b/instance_table.c
@@ -97,7 +97,7 @@ static U64 type_hash(Type *t) {
hash = hash * type_hash(sub) + 0x16225b0aa9993299;
return hash;
case TYPE_FN:
- arr_foreach(t->fn.types, Type, sub)
+ arr_foreach(t->fn->types, Type, sub)
hash = hash * type_hash(sub) + 0x2092d851ab2008de;
return hash;
case TYPE_PTR:
@@ -110,8 +110,8 @@ static U64 type_hash(Type *t) {
hash += (U64)t->struc;
return hash;
case TYPE_ARR:
- hash += type_hash(t->arr.of) * 0x3b6256104800a414 + 0xa901e68bbd8968a1
- + 0xbf79c81a3e68e504 * t->arr.n;
+ hash += type_hash(t->arr->of) * 0x3b6256104800a414 + 0xa901e68bbd8968a1
+ + 0xbf79c81a3e68e504 * t->arr->n;
return hash;
case TYPE_EXPR: break;
}
@@ -169,9 +169,9 @@ static U64 val_ptr_hash(void *v, Type *t) {
case TYPE_ARR: {
U32 x = 1;
U64 hash = 0;
- U64 size = (U64)compiler_sizeof(t->arr.of);
- for (U64 i = 0; i < (U64)t->arr.n; ++i) {
- hash += (U64)x * val_ptr_hash((char *)v + i * size, t->arr.of);
+ U64 size = (U64)compiler_sizeof(t->arr->of);
+ for (U64 i = 0; i < (U64)t->arr->n; ++i) {
+ hash += (U64)x * val_ptr_hash((char *)v + i * size, t->arr->of);
x = rand_u32(x);
}
return hash;
@@ -259,10 +259,10 @@ static bool val_ptr_eq(void *u, void *v, Type *t) {
return true;
}
case TYPE_ARR: {
- U64 size = (U64)compiler_sizeof(t->arr.of);
+ U64 size = (U64)compiler_sizeof(t->arr->of);
char *uptr = u, *vptr = v;
- for (U64 i = 0; i < t->arr.n; ++i) {
- if (!val_ptr_eq(uptr, vptr, t->arr.of))
+ for (U64 i = 0; i < t->arr->n; ++i) {
+ if (!val_ptr_eq(uptr, vptr, t->arr->of))
return false;
uptr += size;
vptr += size;
@@ -270,7 +270,7 @@ static bool val_ptr_eq(void *u, void *v, Type *t) {
return true;
}
case TYPE_SLICE: {
- U64 size = (U64)compiler_sizeof(t->arr.of);
+ U64 size = (U64)compiler_sizeof(t->arr->of);
Slice *r = u;
Slice *s = v;
if (r->len != s->len) return false;
diff --git a/main.c b/main.c
index a95f566..033b58f 100644
--- a/main.c
+++ b/main.c
@@ -8,9 +8,7 @@
/*
@TODO:
-make slice a pointer field of Value
-make arr a pointer field of Type
-- start passing Types instead of pointers to Type
+start passing Types instead of pointers to Type
figure out how printf is gonna work
if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared)
fix #foreign not at global scope - right now the cgen'd definition doesn't use the proper type
diff --git a/parse.c b/parse.c
index 836e675..c1238ad 100644
--- a/parse.c
+++ b/parse.c
@@ -220,14 +220,14 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
}
case TYPE_FN: {
size_t written = str_copy(buffer, bufsize, "fn (");
- Type *ret_type = t->fn.types;
+ Type *ret_type = t->fn->types;
Type *param_types = ret_type + 1;
- size_t nparams = arr_len(t->fn.types) - 1;
+ size_t nparams = arr_len(t->fn->types) - 1;
for (size_t i = 0; i < nparams; ++i) {
if (i > 0)
written += str_copy(buffer + written, bufsize - written, ", ");
- if (t->fn.constness) {
- switch (t->fn.constness[i]) {
+ if (t->fn->constness) {
+ switch (t->fn->constness[i]) {
case CONSTNESS_NO: break;
case CONSTNESS_SEMI:
written += str_copy(buffer + written, bufsize - written, ":::");
@@ -275,13 +275,13 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
case TYPE_ARR: {
size_t written = str_copy(buffer, bufsize, "[");
if (resolved) {
- snprintf(buffer + written, bufsize - written, U64_FMT, t->arr.n);
+ snprintf(buffer + written, bufsize - written, U64_FMT, t->arr->n);
written += strlen(buffer + written);
} else {
written += str_copy(buffer + written, bufsize - written, "N");
}
written += str_copy(buffer + written, bufsize - written, "]");
- written += type_to_str_(t->arr.of, buffer + written, bufsize - written);
+ written += type_to_str_(t->arr->of, buffer + written, bufsize - written);
return written;
}
case TYPE_SLICE: {
@@ -542,18 +542,17 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
case KW_FN: {
/* function type */
type->kind = TYPE_FN;
- type->fn.types = NULL;
- type->fn.constness = NULL;
+ FnType *fn = type->fn = parser_calloc(p, 1, sizeof *type->fn);
++t->token;
if (!token_is_kw(t->token, KW_LPAREN)) {
tokr_err(t, "Expected ( to follow fn.");
return false;
}
- parser_arr_add_ptr(p, type->fn.types); /* add return type */
+ parser_arr_add_ptr(p, fn->types); /* add return type */
++t->token;
if (!token_is_kw(t->token, KW_RPAREN)) {
while (1) {
- Type *param_type = parser_arr_add_ptr(p, type->fn.types);
+ Type *param_type = parser_arr_add_ptr(p, fn->types);
Location type_where;
if (!parse_type(p, param_type, &type_where)) return false;
if (token_is_kw(t->token, KW_RPAREN))
@@ -566,7 +565,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
}
}
++t->token; /* move past ) */
- Type *ret_type = type->fn.types;
+ Type *ret_type = fn->types;
/* if there's a symbol that isn't [, (, or &, that can't be the start of a type */
if ((t->token->kind == TOKEN_KW
&& t->token->kw <= KW_LAST_SYMBOL
@@ -587,6 +586,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
case KW_LSQUARE: {
/* array/slice */
type->kind = TYPE_ARR;
+ ArrType *arr = type->arr = parser_malloc(p, sizeof *type->arr);
++t->token; /* move past [ */
if (token_is_kw(t->token, KW_RSQUARE)) {
/* slice */
@@ -598,12 +598,12 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
break;
}
Token *end = expr_find_end(p, 0);
- type->arr.n_expr = parser_new_expr(p);
- if (!parse_expr(p, type->arr.n_expr, end)) return false;
+ arr->n_expr = parser_new_expr(p);
+ if (!parse_expr(p, arr->n_expr, end)) return false;
t->token = end + 1; /* go past ] */
- type->arr.of = parser_malloc(p, sizeof *type->arr.of);
+ arr->of = parser_malloc(p, sizeof *arr->of);
Location of_where;
- if (!parse_type(p, type->arr.of, &of_where)) return false;
+ if (!parse_type(p, arr->of, &of_where)) return false;
} break;
case KW_AMPERSAND: {
/* pointer */
@@ -1380,7 +1380,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
++t->token;
Type *fn_t = &fn->foreign.type;
fn_t->kind = TYPE_FN;
- FnType *fn_type = &fn_t->fn;
+ FnType *fn_type = fn_t->fn = parser_malloc(p, sizeof *fn_t);
fn_type->constness = NULL;
fn_type->types = NULL;
/* reserve space for return type (Type + CType) */
diff --git a/types.c b/types.c
index 496908f..81ebfeb 100644
--- a/types.c
+++ b/types.c
@@ -239,7 +239,7 @@ static size_t compiler_alignof(Type *t) {
case TYPE_TUPLE:
return toc_alignof(Value *);
case TYPE_ARR:
- return compiler_alignof(t->arr.of);
+ return compiler_alignof(t->arr->of);
case TYPE_SLICE:
if (sizeof(void *) > sizeof(size_t))
return toc_alignof(void *);
@@ -267,7 +267,7 @@ static size_t compiler_sizeof(Type *t) {
case TYPE_PTR:
return sizeof v.ptr;
case TYPE_ARR:
- return (size_t)t->arr.n * compiler_sizeof(t->arr.of);
+ return (size_t)t->arr->n * compiler_sizeof(t->arr->of);
case TYPE_TUPLE:
return sizeof v.tuple;
case TYPE_SLICE:
@@ -358,10 +358,11 @@ static bool type_eq_exact(Type *a, Type *b) {
case TYPE_STRUCT:
return a->struc == b->struc;
case TYPE_FN: {
- if (arr_len(a->fn.types) != arr_len(b->fn.types)) return false;
- Type *a_types = a->fn.types, *b_types = b->fn.types;
- Constness *a_constness = a->fn.constness, *b_constness = b->fn.constness;
- for (size_t i = 0; i < arr_len(a->fn.types); ++i) {
+ FnType *afn = a->fn, *bfn = b->fn;
+ if (arr_len(afn->types) != arr_len(bfn->types)) return false;
+ Type *a_types = afn->types, *b_types = bfn->types;
+ Constness *a_constness = afn->constness, *b_constness = bfn->constness;
+ for (size_t i = 0; i < arr_len(afn->types); ++i) {
Constness const_a = CONSTNESS_NO, const_b = CONSTNESS_NO;
if (a_constness)
const_a = a_constness[i];
@@ -386,8 +387,8 @@ static bool type_eq_exact(Type *a, Type *b) {
return true;
}
case TYPE_ARR:
- if (a->arr.n != b->arr.n) return false;
- return type_eq_exact(a->arr.of, b->arr.of);
+ if (a->arr->n != b->arr->n) return false;
+ return type_eq_exact(a->arr->of, b->arr->of);
case TYPE_SLICE:
return type_eq_exact(a->slice, b->slice);
case TYPE_PTR:
@@ -528,9 +529,9 @@ static bool type_is_compileonly(Type *t) {
case TYPE_SLICE:
return type_is_compileonly(t->slice);
case TYPE_ARR:
- return type_is_compileonly(t->arr.of);
+ return type_is_compileonly(t->arr->of);
case TYPE_FN:
- arr_foreach(t->fn.types, Type, sub) {
+ arr_foreach(t->fn->types, Type, sub) {
if (sub->flags & TYPE_IS_RESOLVED) /* for templates */ {
if (type_is_compileonly(sub))
return true;
@@ -607,8 +608,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
}
t->kind = TYPE_FN;
- t->fn.types = NULL;
- t->fn.constness = NULL; /* @OPTIM: constness doesn't need to be a dynamic array */
+ t->fn = typer_calloc(tr, 1, sizeof *t->fn);
t->flags = 0;
bool success = true;
bool entered_fn = false;
@@ -624,7 +624,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
size_t idx = 0;
bool has_constant_params = false;
/* reserve space for return type */
- typer_arr_add_ptr(tr, t->fn.types);
+ typer_arr_add_ptr(tr, t->fn->types);
tr->fn = f;
Block *prev_block = tr->block;
tr->block = &f->body;
@@ -669,15 +669,15 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
}
U32 is_at_all_const = param->flags & (DECL_IS_CONST | DECL_SEMI_CONST);
if (is_at_all_const) {
- if (!t->fn.constness) {
+ if (!t->fn->constness) {
has_constant_params = true;
for (size_t i = 0; i < idx; ++i) {
- typer_arr_add(tr, t->fn.constness, CONSTNESS_NO);
+ typer_arr_add(tr, t->fn->constness, CONSTNESS_NO);
}
}
}
for (size_t i = 0; i < arr_len(param->idents); ++i) {
- Type *param_type = typer_arr_add_ptr(tr, t->fn.types);
+ Type *param_type = typer_arr_add_ptr(tr, t->fn->types);
if (param->flags & (DECL_ANNOTATES_TYPE|DECL_FOUND_TYPE))
*param_type = param->type;
else
@@ -691,7 +691,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
} else {
constn = CONSTNESS_NO;
}
- typer_arr_add(tr, t->fn.constness, constn);
+ typer_arr_add(tr, t->fn->constness, constn);
}
++idx;
}
@@ -753,7 +753,7 @@ static Status type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
}
{
- Type *ret_type = &t->fn.types[0];
+ Type *ret_type = &t->fn->types[0];
*ret_type = f->ret_type;
}
@@ -874,7 +874,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
case TYPE_ARR: {
/* it's an array */
Value val;
- Expression *n_expr = t->arr.n_expr;
+ Expression *n_expr = t->arr->n_expr;
if (!types_expr(tr, n_expr)) return false;
if (n_expr->type.kind == TYPE_UNKNOWN) {
err_print(n_expr->where, "Cannot determine type of array size at compile time.");
@@ -893,19 +893,19 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
if (type_builtin_is_signed(n_expr->type.builtin)) {
I64 ssize = val_to_i64(val, n_expr->type.builtin);
if (ssize < 0) {
- err_print(t->arr.n_expr->where, "Negative array length (" I64_FMT ")", ssize);
+ err_print(t->arr->n_expr->where, "Negative array length (" I64_FMT ")", ssize);
return false;
}
size = (U64)ssize;
} else {
size = val_to_u64(val, n_expr->type.builtin);
}
- t->arr.n = (U64)size;
- if (!type_resolve(tr, t->arr.of, where))
+ t->arr->n = (U64)size;
+ if (!type_resolve(tr, t->arr->of, where))
return false;
} break;
case TYPE_FN:
- arr_foreach(t->fn.types, Type, child_type) {
+ arr_foreach(t->fn->types, Type, child_type) {
if (!type_resolve(tr, child_type, where))
return false;
}
@@ -1201,7 +1201,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
if (instance) {
f = instance->fn;
} else {
- if (t->fn.constness)
+ if (t->fn->constness)
return true; /* don't type function body yet; we need to do that for every instance */
}
{
@@ -1213,7 +1213,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
success = false;
goto ret;
}
- ret_type = t->fn.types;
+ ret_type = t->fn->types;
has_named_ret_vals = f->ret_decls != NULL;
if (!type_is_builtin(ret_type, BUILTIN_VOID) && !has_named_ret_vals) {
Statement *stmts = f->body.stmts;
@@ -1239,7 +1239,7 @@ static Status types_fn(Typer *tr, FnExpr *f, Type *t, Instance *instance) {
static Status call_arg_param_order(FnExpr *fn, Type *fn_type, Argument *args, Location where, I16 **orderp) {
*orderp = NULL;
assert(fn_type->flags & TYPE_IS_RESOLVED);
- size_t nparams = arr_len(fn_type->fn.types)-1;
+ size_t nparams = arr_len(fn_type->fn->types)-1;
size_t nargs = arr_len(args);
if (nargs > nparams && !(fn->flags & FN_EXPR_HAS_VARARGS)) {
err_print(where, "Expected at most %lu argument%s to function, but got %lu.",
@@ -1639,7 +1639,7 @@ static Status types_expr(Typer *tr, Expression *e) {
if (!type_of_fn(tr, fn, &e->type, 0)) {
return false;
}
- if (!(fn->flags & FN_EXPR_FOREIGN) && (fn_has_any_const_params(fn) || fn_type_has_varargs(&e->type.fn))) {
+ if (!(fn->flags & FN_EXPR_FOREIGN) && (fn_has_any_const_params(fn) || fn_type_has_varargs(e->type.fn))) {
fn->instances = typer_calloc(tr, 1, sizeof *fn->instances);
t->flags |= TYPE_IS_RESOLVED; /* pretend this type is resolved, even though its children aren't to fix some assertions */
} else {
@@ -1839,7 +1839,7 @@ static Status types_expr(Typer *tr, Expression *e) {
err_print(e->where, "Calling non-function (type %s).", type);
return false;
}
- bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(&f->type.fn);
+ bool has_varargs = f->type.kind == TYPE_FN && fn_type_has_varargs(f->type.fn);
if (expr_is_definitely_const(f) || type_is_builtin(&f->type, BUILTIN_TYPE) || has_varargs) {
Value val;
@@ -1983,10 +1983,10 @@ static Status types_expr(Typer *tr, Expression *e) {
fn_decl = val.fn;
}
- Type *ret_type = f->type.fn.types;
+ Type *ret_type = f->type.fn->types;
Type *param_types = ret_type + 1;
Argument *args = c->args;
- size_t nparams = arr_len(f->type.fn.types) - 1;
+ size_t nparams = arr_len(f->type.fn->types) - 1;
size_t nargs = arr_len(c->args);
Expression *arg_exprs = NULL;
size_t narg_exprs = 0;
@@ -2025,7 +2025,7 @@ static Status types_expr(Typer *tr, Expression *e) {
arg_exprs[i].where = param->where;
arg_exprs[i].flags = param->expr.flags;
arg_exprs[i].type = param->type;
- if (has_varargs || f->type.fn.constness) {
+ if (has_varargs || f->type.fn->constness) {
/* param->expr hasn't been typed or evaluated, because we passed type_of_fn a "generic" function */
/* we actually need to make a copy of this, so that copy_fn_expr still works later */
Expression default_arg;
@@ -2115,7 +2115,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
- FnType *fn_type = &f->type.fn;
+ FnType *fn_type = f->type.fn;
c->arg_exprs = arg_exprs;
FnExpr *original_fn = NULL;
FnExpr *fn_copy = NULL;
@@ -2304,7 +2304,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
- ret_type = f->type.fn.types;
+ ret_type = f->type.fn->types;
param_types = ret_type + 1;
}
@@ -2755,7 +2755,7 @@ static Status types_expr(Typer *tr, Expression *e) {
}
switch (lhs_type->kind) {
case TYPE_ARR:
- *t = *lhs_type->arr.of;
+ *t = *lhs_type->arr->of;
break;
case TYPE_SLICE:
*t = *lhs_type->slice;
@@ -2900,7 +2900,7 @@ static Status types_expr(Typer *tr, Expression *e) {
e->val.i64 = (I64)arr_len(decl->val.varargs);
} else if (struct_type->kind == TYPE_ARR) {
e->kind = EXPR_VAL;
- e->val.i64 = (I64)struct_type->arr.n;
+ e->val.i64 = (I64)struct_type->arr->n;
}
} else if (type_is_builtin(struct_type, BUILTIN_NMS)) {
Value nms_val;
@@ -2951,7 +2951,7 @@ static Status types_expr(Typer *tr, Expression *e) {
return false;
switch (s->of->type.kind) {
case TYPE_ARR:
- t->slice = s->of->type.arr.of;
+ t->slice = s->of->type.arr->of;
break;
case TYPE_SLICE:
t->slice = s->of->type.slice;
@@ -3214,16 +3214,16 @@ static Status types_decl(Typer *tr, Declaration *d) {
if (!type_resolve(tr, val->type, d->where)) return false;
}
}
- } else if (!(d->flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn.constness) {
- for (size_t p = 0; p < arr_len(t->fn.types)-1; ++p) {
- if (t->fn.constness[p] == CONSTNESS_YES) {
+ } else if (!(d->flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn->constness) {
+ for (size_t p = 0; p < arr_len(t->fn->types)-1; ++p) {
+ if (t->fn->constness[p] == CONSTNESS_YES) {
err_print(d->where, "You can't have a pointer to a function with constant parameters.");
success = false;
goto ret;
}
}
/* make constness NULL, so that semi-constant parameters turn into non-constant arguments */
- t->fn.constness = NULL;
+ t->fn->constness = NULL;
}
}
@@ -3507,7 +3507,7 @@ top:
iter_type = iter_type->slice;
break;
case TYPE_ARR:
- iter_type = iter_type->arr.of;
+ iter_type = iter_type->arr->of;
break;
case TYPE_BUILTIN:
switch (iter_type->builtin) {
diff --git a/types.h b/types.h
index 8ffd890..b8c1026 100644
--- a/types.h
+++ b/types.h
@@ -434,9 +434,17 @@ typedef U8 Constness;
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. */
+ Constness *constness; /* [i] = constness of param #i. iff no parameters are constant, this is NULL. don't use it as a dynamic array, because it might not always be. */
} FnType;
+typedef struct {
+ struct Type *of;
+ union {
+ U64 n; /* after resolving */
+ struct Expression *n_expr; /* before resolving */
+ };
+} ArrType;
+
enum {
TYPE_IS_FLEXIBLE = 0x01,
TYPE_IS_RESOLVED = 0x02,
@@ -447,15 +455,9 @@ typedef struct Type {
TypeFlags flags;
union {
BuiltinType builtin;
- FnType fn;
+ FnType *fn;
struct Type *tuple;
- struct {
- struct Type *of;
- union {
- U64 n; /* after resolving */
- struct Expression *n_expr; /* before resolving */
- };
- } arr;
+ ArrType *arr;
struct Type *ptr;
struct Type *slice;
struct StructDef *struc; /* multiple resolved types can refer to the same struct */