summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.html2
-rw-r--r--README.md2
-rwxr-xr-xbuild.sh2
-rw-r--r--cgen.c69
-rw-r--r--copy.c6
-rw-r--r--decls_cgen.c2
-rw-r--r--err.c3
-rw-r--r--eval.c73
-rw-r--r--infer.c5
-rw-r--r--instance_table.c29
-rw-r--r--main.c2
-rw-r--r--package.c28
-rw-r--r--parse.c18
-rwxr-xr-xtest-build.sh2
-rw-r--r--test.toc7
-rw-r--r--toc.c8
-rw-r--r--tokenizer.c3
-rw-r--r--typedefs_cgen.c4
-rw-r--r--types.c183
-rw-r--r--types.h9
20 files changed, 254 insertions, 203 deletions
diff --git a/README.html b/README.html
index 3b4bc57..32673e4 100644
--- a/README.html
+++ b/README.html
@@ -74,7 +74,7 @@ it is nearly as fast in theory.</p>
<ul>
<li>Anonymous structures/unions</li>
-<li><code>max_align_t</code> and <code>alignof</code> - It can still compile without these but it won&rsquo;t technically be standard-compliant</li>
+<li><code>max_align_t</code> - It can still compile without this, and will almost definitely work, but it won&rsquo;t technically be standard-compliant</li>
</ul>
diff --git a/README.md b/README.md
index 9366559..0a62770 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ Here are all the C99 features which `toc` depends on (I might have forgotten som
And here are all of its C11 features:
- Anonymous structures/unions
-- `max_align_t` and `alignof` - It can still compile without these but it won't technically be standard-compliant
+- `max_align_t` - It can still compile without this, and will almost definitely work, but it won't technically be standard-compliant
#### More
diff --git a/build.sh b/build.sh
index c22169d..6ca55e6 100755
--- a/build.sh
+++ b/build.sh
@@ -27,7 +27,7 @@ RELEASE_FLAGS="-O3 -s -DNDEBUG $WARNINGS -std=c11"
if [ "$1" = "release" ]; then
FLAGS="$RELEASE_FLAGS $ADDITIONAL_FLAGS"
- COMMAND="$CC compatibility.c -Wall -Wextra -std=c99 -Wpedantic -o compatibility"
+ COMMAND="$CC compatibility.c -Wall -Wextra -o compatibility"
echo $COMMAND
$COMMAND || exit 1
FLAGS="$FLAGS $(./compatibility)"
diff --git a/cgen.c b/cgen.c
index cf3f8d4..9f16b8b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -187,8 +187,6 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d);
break; \
case TYPE_VOID: \
case TYPE_BUILTIN: \
- case TYPE_PKG: \
- case TYPE_TYPE: \
case TYPE_UNKNOWN: \
break; \
case TYPE_EXPR: assert(0); \
@@ -278,10 +276,8 @@ static bool cgen_uses_ptr(Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
- case TYPE_TYPE:
return false;
case TYPE_EXPR:
- case TYPE_PKG:
break;
}
assert(0);
@@ -332,6 +328,9 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
case BUILTIN_BOOL: cgen_write(g, "bool"); break;
case BUILTIN_F32: cgen_write(g, "f32"); break;
case BUILTIN_F64: cgen_write(g, "f64"); break;
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ assert(0); break;
} break;
case TYPE_PTR:
if (!cgen_type_pre(g, t->ptr, where))
@@ -370,9 +369,7 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
}
break;
case TYPE_TUPLE:
- case TYPE_TYPE:
case TYPE_EXPR:
- case TYPE_PKG:
/* We should never try to generate this type */
assert(0);
return false;
@@ -441,12 +438,10 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
- case TYPE_TYPE:
case TYPE_SLICE:
case TYPE_STRUCT:
break;
case TYPE_EXPR:
- case TYPE_PKG:
assert(0);
break;
}
@@ -465,53 +460,15 @@ static inline void cgen_fn_instance_number(CGenerator *g, U64 instance) {
cgen_write(g, U64_FMT"_", instance);
}
-/* does this type have a Type or a Package in it? (e.g. [5]Type, &&Package) */
-static bool type_contains_compileonly_type(Type *t) {
- assert(t->flags & TYPE_IS_RESOLVED);
- switch (t->kind) {
- case TYPE_BUILTIN:
- case TYPE_VOID:
- case TYPE_UNKNOWN:
- return false;
- case TYPE_PKG:
- case TYPE_TYPE:
- return true;
- case TYPE_PTR:
- return type_contains_compileonly_type(t->ptr);
- case TYPE_SLICE:
- return type_contains_compileonly_type(t->slice);
- case TYPE_ARR:
- return type_contains_compileonly_type(t->arr.of);
- case TYPE_FN:
- arr_foreach(t->fn.types, Type, sub)
- if (type_contains_compileonly_type(sub))
- return true;
- return false;
- case TYPE_TUPLE:
- arr_foreach(t->tuple, Type, sub)
- if (type_contains_compileonly_type(sub))
- return true;
- return false;
- case TYPE_STRUCT:
- arr_foreach(t->struc->fields, Field, f)
- if (type_contains_compileonly_type(f->type))
- return true;
- return false;
- case TYPE_EXPR: break;
- }
- assert(0);
- return false;
-}
-
/* should we generate this function? (or is it just meant for compile time) */
static bool cgen_should_gen_fn(FnExpr *f) {
if (f->ret_decls) {
arr_foreach(f->ret_decls, Declaration, decl)
- if (type_contains_compileonly_type(&decl->type))
+ if (type_is_compileonly(&decl->type))
return false;
return true;
} else {
- return !type_contains_compileonly_type(&f->ret_type);
+ return !type_is_compileonly(&f->ret_type);
}
}
@@ -669,9 +626,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E
return false;
break;
case TYPE_VOID:
- case TYPE_TYPE:
case TYPE_EXPR:
- case TYPE_PKG:
assert(0);
return false;
}
@@ -1567,12 +1522,10 @@ static void cgen_zero_value(CGenerator *g, Type *t) {
case TYPE_STRUCT:
cgen_write(g, "{0}");
break;
- case TYPE_TYPE:
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_EXPR:
- case TYPE_PKG:
assert(0);
break;
}
@@ -1605,7 +1558,7 @@ static bool cgen_fn(CGenerator *g, FnExpr *f, Location where, U64 instance, Valu
Type *type = param->type.kind == TYPE_TUPLE ? &param->type.tuple[i]
: &param->type;
Value arg = compile_time_args[carg_idx];
- if (type->kind == TYPE_TYPE) {
+ if (type_is_builtin(type, BUILTIN_TYPE)) {
/* don't need to do anything; we'll just use the type's id */
} else {
if (!cgen_val_pre(g, arg, type, where))
@@ -1708,7 +1661,6 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
}
break;
case TYPE_FN:
- case TYPE_TYPE:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
case TYPE_VOID:
@@ -1717,7 +1669,6 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) {
case TYPE_STRUCT:
break;
case TYPE_EXPR:
- case TYPE_PKG:
assert(0);
return false;
}
@@ -1731,8 +1682,6 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
case TYPE_TUPLE:
case TYPE_VOID:
case TYPE_EXPR:
- case TYPE_TYPE:
- case TYPE_PKG:
assert(0);
return false;
case TYPE_UNKNOWN:
@@ -1779,6 +1728,10 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) {
case BUILTIN_F64: cgen_write(g, F64_FMT, *(F64 *)v); break;
case BUILTIN_CHAR: cgen_write(g, "'\\x%02x'", *(char *)v); break;
case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break;
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ assert(0);
+ break;
}
break;
}
@@ -1804,7 +1757,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
Identifier i = d->idents[idx];
Type *type = decl_type_at_index(d, idx);
Value *val = decl_val_at_index(d, idx);
- if (type_contains_compileonly_type(type)) {
+ if (type_is_compileonly(type)) {
continue;
}
if (g->block == NULL && g->fn == NULL && !i->export_name)
diff --git a/copy.c b/copy.c
index c13dfa1..80d5a52 100644
--- a/copy.c
+++ b/copy.c
@@ -38,8 +38,6 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) {
case TYPE_SLICE:
case TYPE_VOID:
case TYPE_UNKNOWN:
- case TYPE_PKG:
- case TYPE_TYPE:
*out = *in;
break;
case TYPE_ARR: {
@@ -63,7 +61,7 @@ static void copy_val(Allocator *a, Value *out, Value *in, Type *t) {
}
static void copy_val_full(Copier *c, Value *out, Value *in, Type *t) {
- if (t->kind == TYPE_TYPE) {
+ if (type_is_builtin(t, BUILTIN_TYPE)) {
Type *new_type = allocr_malloc(c->allocr, sizeof *new_type);
copy_type(c, new_type, in->type);
out->type = new_type;
@@ -77,8 +75,6 @@ static void copy_type(Copier *c, Type *out, Type *in) {
*out = *in;
switch (in->kind) {
case TYPE_BUILTIN:
- case TYPE_TYPE:
- case TYPE_PKG:
case TYPE_VOID:
case TYPE_UNKNOWN:
break;
diff --git a/decls_cgen.c b/decls_cgen.c
index 728d83e..e8f7cca 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -152,7 +152,7 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
for (int i = 0, n_idents = (int)arr_len(d->idents); i < n_idents; ++i) {
Identifier ident = d->idents[i];
Type *type = decl_type_at_index(d, i);
- if (!type_contains_compileonly_type(type)) {
+ if (!type_is_compileonly(type)) {
if (ident->export_name)
cgen_write(g, "extern ");
else
diff --git a/err.c b/err.c
index 823c039..94d6d64 100644
--- a/err.c
+++ b/err.c
@@ -187,6 +187,9 @@ static void err_print_footer_(Location where) {
static void err_vprint(Location where, const char *fmt, va_list args) {
if (location_is_ctx_disabled(where)) return;
+ if (where.start) {
+ where.start->pos.ctx->have_errored = true;
+ }
err_print_header_(where);
err_vfprint(fmt, args);
err_print_footer_(where);
diff --git a/eval.c b/eval.c
index 2f6baa8..38fc316 100644
--- a/eval.c
+++ b/eval.c
@@ -50,6 +50,8 @@ static size_t compiler_sizeof_builtin(BuiltinType b) {
case BUILTIN_F64: return sizeof(F64);
case BUILTIN_CHAR: return sizeof(char); /* = 1 */
case BUILTIN_BOOL: return sizeof(bool);
+ case BUILTIN_TYPE: return sizeof(Type *);
+ case BUILTIN_PKG: return sizeof(Package *);
}
assert(0);
return 0;
@@ -101,10 +103,6 @@ static size_t compiler_alignof(Type *t) {
return sizeof(void *);
else
return sizeof(size_t);
- case TYPE_TYPE:
- return sizeof v.type;
- case TYPE_PKG:
- return sizeof v.pkg;
case TYPE_STRUCT: {
/* assume the align of a struct is (at most) the greatest align out of its children's */
eval_struct_find_offsets(t);
@@ -135,10 +133,6 @@ static size_t compiler_sizeof(Type *t) {
return sizeof v.tuple;
case TYPE_SLICE:
return sizeof v.slice;
- case TYPE_TYPE:
- return sizeof v.type;
- case TYPE_PKG:
- return sizeof v.pkg;
case TYPE_STRUCT: {
eval_struct_find_offsets(t);
return t->struc->size;
@@ -167,6 +161,9 @@ static bool builtin_truthiness(Value *v, BuiltinType b) {
case BUILTIN_F64: return v->f64 != 0;
case BUILTIN_BOOL: return v->boolv;
case BUILTIN_CHAR: return v->charv != 0;
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ break;
}
assert(0); return false;
}
@@ -181,11 +178,9 @@ 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_TYPE:
case TYPE_TUPLE:
case TYPE_STRUCT:
case TYPE_EXPR:
- case TYPE_PKG:
break;
}
assert(0);
@@ -256,9 +251,7 @@ static void *val_get_ptr(Value *v, Type *t) {
case TYPE_UNKNOWN:
case TYPE_FN:
case TYPE_SLICE:
- case TYPE_TYPE:
case TYPE_TUPLE:
- case TYPE_PKG:
return v;
case TYPE_ARR:
return v->arr;
@@ -293,6 +286,13 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
case BUILTIN_F64: fprintf(f, F64_FMT, *(F64 *)p); break;
case BUILTIN_CHAR: fprint_char_literal(f, *(char *)p); break;
case BUILTIN_BOOL: fprintf(f, "%s", *(bool *)p ? "true" : "false"); break;
+ case BUILTIN_PKG: {
+ Package *pkg = *(Package **)p;
+ fprintf(f, "<package at %p>", (void *)pkg);
+ } break;
+ case BUILTIN_TYPE:
+ fprint_type(f, *(Type **)p);
+ break;
}
break;
case TYPE_FN:
@@ -323,10 +323,6 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
case TYPE_PTR:
fprintf(f, "<pointer: %p>", *(void **)p);
break;
- case TYPE_PKG: {
- Package *pkg = *(Package **)p;
- fprintf(f, "<package at %p>", (void *)pkg);
- } break;
case TYPE_SLICE: {
fprintf(f, "["); /* TODO: change? when slice initializers are added */
Slice slice = *(Slice *)p;
@@ -341,9 +337,6 @@ static void fprint_val_ptr(FILE *f, void *p, Type *t) {
}
fprintf(f, "]");
} break;
- case TYPE_TYPE:
- fprint_type(f, *(Type **)p);
- break;
case TYPE_STRUCT:
fprintf(f, "["); /* TODO: change? when struct initializers are added */
arr_foreach(t->struc->fields, Field, fi) {
@@ -378,8 +371,6 @@ static void *val_ptr_to_free(Value *v, Type *t) {
case TYPE_PTR:
case TYPE_SLICE:
case TYPE_VOID:
- case TYPE_TYPE:
- case TYPE_PKG:
case TYPE_UNKNOWN:
return NULL;
case TYPE_ARR:
@@ -429,6 +420,7 @@ static void val_free(Value *v, Type *t) {
builtin_casts_to_num(low); \
case BUILTIN_CHAR: vout->charv = (char)vin->low; break; \
case BUILTIN_BOOL: vout->boolv = vin->low != 0; break; \
+ case BUILTIN_PKG: case BUILTIN_TYPE: assert(0); break; \
} break
#define builtin_float_casts(low, up) \
@@ -437,6 +429,7 @@ static void val_free(Value *v, Type *t) {
builtin_casts_to_num(low); \
case BUILTIN_BOOL: vout->boolv = vin->low != 0.0f; break; \
case BUILTIN_CHAR: \
+ case BUILTIN_PKG: case BUILTIN_TYPE: \
assert(0); break; \
} break
@@ -465,9 +458,15 @@ static void val_builtin_cast(Value *vin, BuiltinType from, Value *vout, BuiltinT
case BUILTIN_F32:
case BUILTIN_F64:
case BUILTIN_BOOL:
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
assert(0); break;
}
break;
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ assert(0);
+ break;
}
}
@@ -484,10 +483,8 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_TUPLE:
- case TYPE_TYPE:
case TYPE_STRUCT:
case TYPE_EXPR:
- case TYPE_PKG:
assert(0); break;
case TYPE_BUILTIN:
switch (to->kind) {
@@ -515,8 +512,6 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case TYPE_TUPLE:
case TYPE_FN:
case TYPE_ARR:
- case TYPE_TYPE:
- case TYPE_PKG:
assert(0);
break;
}
@@ -544,6 +539,8 @@ static void val_cast(Value *vin, Type *from, Value *vout, Type *to) {
case BUILTIN_CHAR:
case BUILTIN_F32:
case BUILTIN_F64:
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
assert(0); break;
}
break;
@@ -615,17 +612,17 @@ static void eval_deref(Value *v, void *ptr, Type *type) {
case BUILTIN_F64: v->f64 = *(F64 *)ptr; break;
case BUILTIN_CHAR: v->charv = *(char *)ptr; break;
case BUILTIN_BOOL: v->boolv = *(bool *)ptr; break;
+ case BUILTIN_TYPE:
+ v->type = *(Type **)ptr;
+ break;
+ case BUILTIN_PKG:
+ v->pkg = *(Package **)ptr;
+ break;
}
break;
case TYPE_SLICE:
v->slice = *(Slice *)ptr;
break;
- case TYPE_TYPE:
- v->type = *(Type **)ptr;
- break;
- case TYPE_PKG:
- v->pkg = *(Package **)ptr;
- break;
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_EXPR:
@@ -656,17 +653,17 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
case BUILTIN_F64: *(F64 *)set = to->f64; break;
case BUILTIN_CHAR: *(char *)set = to->charv; break;
case BUILTIN_BOOL: *(bool *)set = to->boolv; break;
+ case BUILTIN_TYPE:
+ *(Type **)set = to->type;
+ break;
+ case BUILTIN_PKG:
+ *(Package **)set = to->pkg;
+ break;
}
break;
case TYPE_SLICE:
*(Slice *)set = to->slice;
break;
- case TYPE_TYPE:
- *(Type **)set = to->type;
- break;
- case TYPE_PKG:
- *(Package **)set = to->pkg;
- break;
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_EXPR:
@@ -1030,7 +1027,7 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
switch (e->unary.op) {
case UNARY_ADDRESS: {
Expression *o = e->unary.of;
- if (o->type.kind == TYPE_TYPE) {
+ if (type_is_builtin(&o->type, BUILTIN_TYPE)) {
if (!eval_expr(ev, e->unary.of, &of)) return false;
/* "address" of type (pointer to type) */
v->type = evalr_malloc(ev, sizeof *v->type); /* TODO: this might be bad in the future; should free this at some point */
diff --git a/infer.c b/infer.c
index 325d165..48102e0 100644
--- a/infer.c
+++ b/infer.c
@@ -83,8 +83,6 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
case TYPE_VOID:
case TYPE_UNKNOWN:
case TYPE_BUILTIN:
- case TYPE_TYPE:
- case TYPE_PKG:
break; /* nothing we can do here */
case TYPE_TUPLE: {
if (to->kind != TYPE_TUPLE) return true;
@@ -137,7 +135,8 @@ static bool infer_from_type(Typer *tr, Type *match, Type *to, Identifier *idents
e.flags = EXPR_FOUND_TYPE;
Type *type = &e.type;
type->flags = TYPE_IS_RESOLVED;
- type->kind = TYPE_TYPE;
+ type->kind = TYPE_BUILTIN;
+ type->builtin = BUILTIN_TYPE;
if (!to_expr) {
to_expr = &e;
}
diff --git a/instance_table.c b/instance_table.c
index b2a4c01..0e5827f 100644
--- a/instance_table.c
+++ b/instance_table.c
@@ -85,8 +85,7 @@ static U64 type_hash(Type *t) {
0x50da97f1211b2423,
0xc3977306abd0ae6c,
0x87ea684427e1c521,
- 0xcee5fd6d6cbdfe23,
- 0xd80dd2469d6e7c1b
+ 0xcee5fd6d6cbdfe23
};
U64 hash = starters[t->kind];
assert(t->flags & TYPE_IS_RESOLVED);
@@ -95,8 +94,6 @@ static U64 type_hash(Type *t) {
return hash + (U64)t->builtin * 0x1307787dfff73417;
case TYPE_VOID:
case TYPE_UNKNOWN:
- case TYPE_TYPE:
- case TYPE_PKG:
return hash;
case TYPE_TUPLE:
arr_foreach(t->tuple, Type, sub)
@@ -144,6 +141,12 @@ static U64 val_ptr_hash(void *v, Type *t) {
case BUILTIN_F64: return f64_hash(*(F64 *)v);
case BUILTIN_CHAR: return (U64)*(char *)v;
case BUILTIN_BOOL: return (U64)*(bool *)v;
+ case BUILTIN_TYPE:
+ return type_hash(*(Type **)v);
+ case BUILTIN_PKG: {
+ Package *pkg = *(Package **)v;
+ return (U64)pkg;
+ } break;
}
assert(0);
return 0;
@@ -159,8 +162,6 @@ static U64 val_ptr_hash(void *v, Type *t) {
return hash;
}
case TYPE_PTR: return (U64)*(void **)v;
- case TYPE_TYPE:
- return type_hash(*(Type **)v);
case TYPE_ARR: {
U32 x = 1;
U64 hash = 0;
@@ -191,10 +192,6 @@ static U64 val_ptr_hash(void *v, Type *t) {
}
return hash;
}
- case TYPE_PKG: {
- Package *pkg = *(Package **)v;
- return (U64)pkg;
- } break;
case TYPE_EXPR: break;
}
assert(0);
@@ -222,6 +219,12 @@ static bool val_ptr_eq(void *u, void *v, Type *t) {
case BUILTIN_F64: return *(F64 *)u == *(F64 *)v;
case BUILTIN_BOOL: return *(bool *)u == *(bool *)v;
case BUILTIN_CHAR: return *(char *)u == *(char *)v;
+ case BUILTIN_TYPE: {
+ bool ret = type_eq(*(Type **)u, *(Type **)v);
+ return ret;
+ }
+ case BUILTIN_PKG:
+ return *(Package **)u == *(Package **)v;
}
break;
case TYPE_VOID:
@@ -232,10 +235,6 @@ static bool val_ptr_eq(void *u, void *v, Type *t) {
return *(FnExpr **)u == *(FnExpr **)v;
case TYPE_PTR:
return *(void **)u == *(void **)v;
- case TYPE_TYPE: {
- bool ret = type_eq(*(Type **)u, *(Type **)v);
- return ret;
- }
case TYPE_TUPLE: {
Value *us = *(Value **)u;
Value *vs = *(Value **)v;
@@ -276,8 +275,6 @@ static bool val_ptr_eq(void *u, void *v, Type *t) {
return false;
}
return true;
- case TYPE_PKG:
- return *(Package **)u == *(Package **)v;
case TYPE_EXPR: break;
}
assert(0);
diff --git a/main.c b/main.c
index 849aabf..0259f07 100644
--- a/main.c
+++ b/main.c
@@ -117,7 +117,7 @@ int main(int argc, char **argv) {
Evaluator ev;
Exporter exptr;
evalr_create(&ev, &tr, &main_allocr);
- typer_create(&tr, &ev, &main_allocr, &idents);
+ typer_create(&tr, &ev, &err_ctx, &main_allocr, &idents);
tr.exptr = &exptr;
if (!block_enter(NULL, f.stmts, SCOPE_CHECK_REDECL)) /* enter global scope */
diff --git a/package.c b/package.c
index 0181e4b..24074b7 100644
--- a/package.c
+++ b/package.c
@@ -226,18 +226,18 @@ static bool import_pkg(Allocator *allocr, Package *p, FILE *f, const char *fname
static bool export_type(Exporter *ex, Type *type, Location where) {
assert(type->flags & TYPE_IS_RESOLVED);
- export_u8(ex, (U8)type->kind);
+ if (type->kind == TYPE_BUILTIN) {
+ export_u8(ex, (U8)(type->builtin + TYPE_COUNT));
+ } else {
+ export_u8(ex, (U8)type->kind);
+ }
switch (type->kind) {
case TYPE_VOID:
- case TYPE_TYPE:
- case TYPE_PKG:
case TYPE_UNKNOWN:
+ case TYPE_BUILTIN:
break;
case TYPE_PTR: export_type(ex, type->ptr, where); break;
case TYPE_SLICE: export_type(ex, type->slice, where); break;
- case TYPE_BUILTIN:
- export_u8(ex, (U8)type->builtin);
- break;
case TYPE_TUPLE:
export_len(ex, arr_len(type->tuple));
arr_foreach(type->tuple, Type, sub)
@@ -316,6 +316,14 @@ static bool export_val_ptr(Exporter *ex, void *val, Type *type, Location where)
case BUILTIN_F64: export_f64(ex, *(F64 *)val); break;
case BUILTIN_BOOL: export_bool(ex, *(bool *)val); break;
case BUILTIN_CHAR: export_char(ex, *(char *)val); break;
+ case BUILTIN_TYPE:
+ if (!export_type(ex, *(Type **)val, where))
+ return false;
+ break;
+ case BUILTIN_PKG: {
+ Package *pkg = *(Package **)val;
+ export_ident(ex, pkg->name);
+ } break;
}
break;
case TYPE_TUPLE: {
@@ -326,10 +334,6 @@ static bool export_val_ptr(Exporter *ex, void *val, Type *type, Location where)
return false;
}
} break;
- case TYPE_TYPE:
- if (!export_type(ex, *(Type **)val, where))
- return false;
- break;
case TYPE_PTR:
err_print(where, "Cannot export pointer.");
return false;
@@ -365,10 +369,6 @@ static bool export_val_ptr(Exporter *ex, void *val, Type *type, Location where)
if (!export_fn_ptr(ex, *(FnExpr **)val, where))
return false;
break;
- case TYPE_PKG: {
- Package *pkg = *(Package **)val;
- export_ident(ex, pkg->name);
- } break;
case TYPE_UNKNOWN:
case TYPE_EXPR:
assert(0);
diff --git a/parse.c b/parse.c
index 7b8a6cd..bb3bf5e 100644
--- a/parse.c
+++ b/parse.c
@@ -151,6 +151,8 @@ static int kw_to_builtin_type(Keyword kw) {
case KW_F64: return BUILTIN_F64;
case KW_BOOL: return BUILTIN_BOOL;
case KW_CHAR: return BUILTIN_CHAR;
+ case KW_PACKAGE: return BUILTIN_PKG;
+ case KW_TYPE: return BUILTIN_TYPE;
default: return -1;
}
return -1;
@@ -170,6 +172,8 @@ static Keyword builtin_type_to_kw(BuiltinType t) {
case BUILTIN_F64: return KW_F64;
case BUILTIN_BOOL: return KW_BOOL;
case BUILTIN_CHAR: return KW_CHAR;
+ case BUILTIN_PKG: return KW_PACKAGE;
+ case BUILTIN_TYPE: return KW_TYPE;
}
assert(0);
return KW_COUNT;
@@ -265,10 +269,6 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) {
written += type_to_str_(t->ptr, buffer + written, bufsize - written);
return written;
}
- case TYPE_TYPE:
- return str_copy(buffer, bufsize, "Type");
- case TYPE_PKG:
- return str_copy(buffer, bufsize, "pkg");
case TYPE_EXPR:
/* TODO: improve this... we're gonna need expr_to_str ): */
return str_copy(buffer, bufsize, "<type expression>");
@@ -455,10 +455,6 @@ static bool parse_type(Parser *p, Type *type) {
}
/* Not a builtin */
switch (t->token->kw) {
- case KW_TYPE:
- type->kind = TYPE_TYPE;
- ++t->token;
- break;
case KW_FN: {
/* function type */
type->kind = TYPE_FN;
@@ -1875,6 +1871,12 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
}
d->where.end = t->token;
+ switch (ends_with) {
+ case DECL_END_RPAREN_COMMA:
+ case DECL_END_LBRACE_COMMA:
+ --d->where.end; /* don't include the ) / { as part of the declaration */
+ case DECL_END_SEMICOLON: break;
+ }
return true;
diff --git a/test-build.sh b/test-build.sh
index d03eff1..38f667a 100755
--- a/test-build.sh
+++ b/test-build.sh
@@ -1,8 +1,8 @@
#!/bin/sh
-./build.sh release || exit 1
for CC in tcc gcc clang g++ ; do
CC="$CC" ./build.sh || exit 1
CC="$CC" ./build.sh release || exit 1
done
+./build.sh release || exit 1
./build.sh || exit 1
diff --git a/test.toc b/test.toc
index 2c58e20..fc5dd32 100644
--- a/test.toc
+++ b/test.toc
@@ -7,9 +7,8 @@ putf ::= fn(x: float) {
");
};
point ::= pkg "point";
-main ::= fn() {
- x := fahfsdkjahksjdfh;
-fahfsdkjahksjdfh :=
-5;
+main ::= fn() {
+f::=fn(t::Type)Type {t};
+x:f(int) = 5;
}; \ No newline at end of file
diff --git a/toc.c b/toc.c
index c7cc82b..1f6472d 100644
--- a/toc.c
+++ b/toc.c
@@ -45,6 +45,13 @@ static void fprint_char_literal(FILE *f, char c) {
}
+static inline bool type_is_builtin(Type *t, BuiltinType b) {
+ return t->kind == TYPE_BUILTIN && t->builtin == b;
+}
+
+static inline bool type_is_slicechar(Type *t) {
+ return t->kind == TYPE_SLICE && type_is_builtin(t->slice, BUILTIN_CHAR);
+}
/* utilities */
#include "allocator.c"
@@ -57,6 +64,7 @@ static void fprint_char_literal(FILE *f, char c) {
#include "copy.c"
#include "binfile.c"
+
#include "identifiers.c"
#include "tokenizer.c"
#include "parse.c"
diff --git a/tokenizer.c b/tokenizer.c
index 5c46ec8..d7a7b1e 100644
--- a/tokenizer.c
+++ b/tokenizer.c
@@ -3,7 +3,7 @@
This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/
-static const char *keywords[KW_COUNT] =
+static const char *const keywords[KW_COUNT] =
{";", ":", ",", "(", ")", "{", "}", "[", "]", "==",
"+=", "-=", "*=", "/=",
"!=", "<=", "<", ">=", ">",
@@ -13,6 +13,7 @@ static const char *keywords[KW_COUNT] =
"new", "del", "struct",
"int", "i8", "i16", "i32", "i64",
"u8", "u16", "u32", "u64", "float", "f32", "f64", "Type",
+ "Package",
"char", "bool", "true", "false",
"pkg"};
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index 884d61e..3f7d8f1 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -83,7 +83,7 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) {
Identifier i = d->idents[idx];
Type *type = decl_type_at_index(d, idx);
Value *val = decl_val_at_index(d, idx);
- if (type->kind == TYPE_TYPE) {
+ if (type_is_builtin(type, BUILTIN_TYPE)) {
/* generate typedef */
typedefs_type(g, val->type, i);
@@ -91,7 +91,7 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) {
IdentID id = 0;
if (g->block != NULL || g->fn != NULL)
id = ++g->ident_counter;
- if (val->type->kind != TYPE_TYPE) {
+ if (!type_is_compileonly(val->type)) {
cgen_write(g, "typedef ");
if (!cgen_type_pre(g, val->type, d->where)) return false;
cgen_write(g, " ");
diff --git a/types.c b/types.c
index 00ddd8c..e2a544c 100644
--- a/types.c
+++ b/types.c
@@ -20,14 +20,6 @@ static inline void *typer_arr_add_(Typer *tr, void **arr, size_t sz) {
return arr_adda_(arr, sz, tr->allocr);
}
-static inline bool type_is_builtin(Type *t, BuiltinType b) {
- return t->kind == TYPE_BUILTIN && t->builtin == b;
-}
-
-static inline bool type_is_slicechar(Type *t) {
- return t->kind == TYPE_SLICE && type_is_builtin(t->slice, BUILTIN_CHAR);
-}
-
#define typer_arr_add(tr, a) typer_arr_add_(tr, (void **)(a), sizeof **(a))
static bool type_eq(Type *a, Type *b) {
@@ -56,8 +48,6 @@ static bool type_eq(Type *a, Type *b) {
switch (a->kind) {
case TYPE_VOID: return true;
case TYPE_UNKNOWN: assert(0); return false;
- case TYPE_TYPE: return true;
- case TYPE_PKG: return true;
case TYPE_BUILTIN:
return a->builtin == b->builtin;
case TYPE_STRUCT: return a->struc == b->struc;
@@ -193,6 +183,48 @@ static bool expr_must_lval(Expression *e) {
return false;
}
+
+/* does this type have a Type or a Package in it? (e.g. [5]Type, &&Package) */
+static bool type_is_compileonly(Type *t) {
+ assert(t->flags & TYPE_IS_RESOLVED);
+ switch (t->kind) {
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ return false;
+ case TYPE_BUILTIN:
+ return t->builtin == BUILTIN_PKG || t->builtin == BUILTIN_TYPE;
+ case TYPE_PTR:
+ return type_is_compileonly(t->ptr);
+ case TYPE_SLICE:
+ return type_is_compileonly(t->slice);
+ case TYPE_ARR:
+ return type_is_compileonly(t->arr.of);
+ case TYPE_FN:
+ arr_foreach(t->fn.types, Type, sub) {
+ if (sub->flags & TYPE_IS_RESOLVED) /* for templates */ {
+ if (type_is_compileonly(sub))
+ return true;
+ } else {
+ return true;
+ }
+ }
+ return false;
+ case TYPE_TUPLE:
+ arr_foreach(t->tuple, Type, sub)
+ if (type_is_compileonly(sub))
+ return true;
+ return false;
+ case TYPE_STRUCT:
+ arr_foreach(t->struc->fields, Field, f)
+ if (type_is_compileonly(f->type))
+ return true;
+ return false;
+ case TYPE_EXPR: break;
+ }
+ assert(0);
+ return false;
+}
+
enum {
/* is f an instance? (changes behaviour a bit) */
TYPE_OF_FN_IS_INSTANCE = 0x01
@@ -327,21 +359,23 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Type *t, U16 flags) {
success = false;
goto ret;
}
- }
- *ret_type = f->ret_type;
-
- if (ret_type->kind == TYPE_TYPE) {
- /*
- a function which returns a type but has non-constant parameters is weird...
- but might be useful, so let's warn
- */
- arr_foreach(f->params, Declaration, param) {
- if (!(param->flags & DECL_IS_CONST)) {
- warn_print(param->where, "Non-constant parameter in function which returns Type. (You can't call functions which return types at run-time, y'know)");
- break;
+ if (type_is_compileonly(&f->ret_type)) {
+ /*
+ a function which returns a compile-only type but has non-constant parameters is weird...
+ but might be useful, so let's warn
+ */
+ arr_foreach(f->params, Declaration, param) {
+ if (!(param->flags & DECL_IS_CONST)) {
+ char *s = type_to_str(ret_type);
+ warn_print(param->where, "Non-constant parameter in function which returns %s (which is a type which can only be used at run time).", s);
+ free(s);
+ break;
+ }
}
}
+
}
+ *ret_type = f->ret_type;
ret:
arr_remove_lasta(&tr->blocks, tr->allocr);
@@ -521,7 +555,9 @@ static bool type_resolve(Typer *tr, Type *t, Location where) {
Value typeval;
if (!types_expr(tr, t->expr))
return false;
- if (t->expr->type.kind != TYPE_TYPE) {
+ if (t->expr->type.kind == TYPE_UNKNOWN && tr->err_ctx->have_errored)
+ return false; /* silently fail (e.g. if a function couldn't be typed) */
+ if (!type_is_builtin(&t->expr->type, BUILTIN_TYPE)) {
err_print(where, "This expression is not a type, but it's being used as one.");
return false;
}
@@ -534,8 +570,6 @@ static bool type_resolve(Typer *tr, Type *t, Location where) {
} break;
case TYPE_UNKNOWN:
case TYPE_VOID:
- case TYPE_TYPE:
- case TYPE_PKG:
case TYPE_BUILTIN:
break;
}
@@ -552,16 +586,32 @@ static bool type_can_be_truthy(Type *t) {
case TYPE_VOID:
case TYPE_TUPLE:
case TYPE_ARR:
- case TYPE_TYPE:
case TYPE_STRUCT:
- case TYPE_PKG:
return false;
case TYPE_FN:
case TYPE_UNKNOWN:
- case TYPE_BUILTIN:
case TYPE_PTR:
case TYPE_SLICE:
return true;
+ case TYPE_BUILTIN:
+ switch (t->builtin) {
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ return false;
+ case BUILTIN_I8:
+ case BUILTIN_U8:
+ case BUILTIN_I16:
+ case BUILTIN_U16:
+ case BUILTIN_I32:
+ case BUILTIN_U32:
+ case BUILTIN_I64:
+ case BUILTIN_U64:
+ case BUILTIN_F32:
+ case BUILTIN_F64:
+ case BUILTIN_CHAR:
+ case BUILTIN_BOOL:
+ return true;
+ }
case TYPE_EXPR:
break;
}
@@ -584,9 +634,7 @@ static Status type_cast_status(Type *from, Type *to) {
switch (from->kind) {
case TYPE_UNKNOWN: return STATUS_NONE;
case TYPE_STRUCT:
- case TYPE_TYPE:
case TYPE_VOID:
- case TYPE_PKG:
return STATUS_ERR;
case TYPE_BUILTIN:
switch (from->builtin) {
@@ -600,6 +648,26 @@ static Status type_cast_status(Type *from, Type *to) {
case BUILTIN_U64:
switch (to->kind) {
case TYPE_BUILTIN:
+ switch (to->builtin) {
+ case BUILTIN_I8:
+ case BUILTIN_U8:
+ case BUILTIN_I16:
+ case BUILTIN_U16:
+ case BUILTIN_I32:
+ case BUILTIN_U32:
+ case BUILTIN_I64:
+ case BUILTIN_U64:
+ case BUILTIN_F32:
+ case BUILTIN_F64:
+ case BUILTIN_BOOL:
+ case BUILTIN_CHAR:
+ return STATUS_NONE;
+ case BUILTIN_PKG:
+ case BUILTIN_TYPE:
+ return STATUS_ERR;
+ }
+ assert(0);
+ break;
case TYPE_UNKNOWN:
return STATUS_NONE;
case TYPE_PTR:
@@ -610,15 +678,36 @@ static Status type_cast_status(Type *from, Type *to) {
break;
case BUILTIN_F32:
case BUILTIN_F64:
- if (to->kind == TYPE_BUILTIN && to->builtin != BUILTIN_CHAR)
+ if (to->kind == TYPE_BUILTIN) return STATUS_ERR;
+ switch (to->builtin) {
+ case BUILTIN_I8:
+ case BUILTIN_U8:
+ case BUILTIN_I16:
+ case BUILTIN_U16:
+ case BUILTIN_I32:
+ case BUILTIN_U32:
+ case BUILTIN_I64:
+ case BUILTIN_U64:
+ case BUILTIN_F32:
+ case BUILTIN_F64:
+ case BUILTIN_BOOL:
return STATUS_NONE;
- return STATUS_ERR;
+ case BUILTIN_CHAR:
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ return STATUS_ERR;
+ }
+ assert(0);
+ break;
case BUILTIN_CHAR:
if (to->kind == TYPE_BUILTIN && type_builtin_is_int(to->builtin))
return STATUS_NONE;
return STATUS_ERR;
case BUILTIN_BOOL:
return type_can_be_truthy(to) ? STATUS_NONE : STATUS_ERR;
+ case BUILTIN_TYPE:
+ case BUILTIN_PKG:
+ return STATUS_ERR;
}
break;
case TYPE_TUPLE: return STATUS_ERR;
@@ -855,7 +944,8 @@ static bool types_expr(Typer *tr, Expression *e) {
t->builtin = BUILTIN_CHAR;
break;
case EXPR_PKG: {
- t->kind = TYPE_PKG;
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_PKG;
Expression *name_expr = e->pkg.name_expr;
if (!types_expr(tr, name_expr)) return false;
if (!type_is_slicechar(&name_expr->type)) {
@@ -1357,7 +1447,7 @@ static bool types_expr(Typer *tr, Expression *e) {
Value *val = &inferred_vals[i];
Type *type = &inferred_types[i];
/* if we have an inferred type argument, it shouldn't be flexible */
- if (type->kind == TYPE_TYPE)
+ if (type_is_builtin(type, BUILTIN_TYPE))
val->type->flags &= (TypeFlags)~(TypeFlags)TYPE_IS_FLEXIBLE;
param->val = *val;
param->type = *type;
@@ -1544,7 +1634,7 @@ static bool types_expr(Typer *tr, Expression *e) {
Expression *of = e->kind == EXPR_DSIZEOF ? e->dsizeof.of : e->dalignof.of;
if (!types_expr(tr, of))
return false;
- if (of->type.kind == TYPE_TYPE) {
+ if (type_is_builtin(&of->type, BUILTIN_TYPE)) {
Value val;
if (!eval_expr(tr->evalr, of, &val))
return false;
@@ -1579,9 +1669,10 @@ static bool types_expr(Typer *tr, Expression *e) {
*t = *of_type;
break;
case UNARY_ADDRESS:
- if (of_type->kind == TYPE_TYPE) {
+ if (type_is_builtin(of_type, BUILTIN_TYPE)) {
/* oh it's a type! */
- t->kind = TYPE_TYPE;
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_TYPE;
break;
}
if (!expr_must_lval(of)) {
@@ -1678,10 +1769,6 @@ static bool types_expr(Typer *tr, Expression *e) {
if (o == BINARY_SET) {
valid = type_eq(lhs_type, rhs_type);
- if (lhs_type->kind == TYPE_TYPE) {
- err_print(e->where, "Cannot set type.");
- return false;
- }
} else {
/* numerical binary ops */
if (lhs_type->kind == TYPE_BUILTIN && type_eq(lhs_type, rhs_type)) {
@@ -1925,7 +2012,8 @@ static bool types_expr(Typer *tr, Expression *e) {
case EXPR_TYPE:
if (!type_resolve(tr, &e->typeval, e->where))
return false;
- t->kind = TYPE_TYPE;
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_TYPE;
break;
case EXPR_VAL:
assert(0);
@@ -2043,12 +2131,16 @@ static bool types_decl(Typer *tr, Declaration *d) {
}
for (size_t i = 0; i < arr_len(d->idents); ++i) {
Type *t = d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type;
- if (t->kind == TYPE_TYPE) {
+ if (type_is_compileonly(&d->type)) {
if (!(d->flags & DECL_IS_CONST)) {
- err_print(d->where, "Cannot declare non-constant type.");
+ char *s = type_to_str(&d->type);
+ err_print(d->where, "Declarations with type %s must be constant.", s);
+ free(s);
success = false;
goto ret;
}
+ }
+ if (type_is_builtin(t, BUILTIN_TYPE)) {
if (d->flags & DECL_HAS_EXPR) {
Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[i] : &d->val;
if (!type_resolve(tr, val->type, d->where)) return false;
@@ -2154,11 +2246,12 @@ static bool types_stmt(Typer *tr, Statement *s) {
return true;
}
-static void typer_create(Typer *tr, Evaluator *ev, Allocator *allocr, Identifiers *idents) {
+static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents) {
tr->block = NULL;
tr->blocks = NULL;
tr->fn = NULL;
tr->evalr = ev;
+ tr->err_ctx = err_ctx;
tr->exptr = NULL; /* by default, don't set an exporter */
tr->in_decls = NULL;
tr->in_expr_decls = NULL;
diff --git a/types.h b/types.h
index 606c748..b69c525 100644
--- a/types.h
+++ b/types.h
@@ -86,6 +86,7 @@ typedef struct ErrCtx {
char *str; /* file contents */
bool enabled;
bool color_enabled;
+ bool have_errored;
struct Location *instance_stack; /* stack of locations which generate the instances we're dealing with */
} ErrCtx;
@@ -269,6 +270,7 @@ typedef enum {
KW_F32,
KW_F64,
KW_TYPE,
+ KW_PACKAGE,
KW_CHAR,
KW_BOOL,
KW_TRUE,
@@ -344,8 +346,6 @@ typedef enum {
TYPE_ARR,
TYPE_PTR,
TYPE_SLICE,
- TYPE_TYPE,
- TYPE_PKG,
TYPE_EXPR, /* just use this expression as the type. this kind of type doesn't exist after resolving. */
TYPE_STRUCT
#define TYPE_COUNT (TYPE_STRUCT+1)
@@ -364,7 +364,9 @@ typedef enum {
BUILTIN_F32,
BUILTIN_F64,
BUILTIN_CHAR,
- BUILTIN_BOOL
+ BUILTIN_BOOL,
+ BUILTIN_TYPE,
+ BUILTIN_PKG
} BuiltinType;
/* field of a struct */
@@ -774,6 +776,7 @@ typedef struct Typer {
Block **blocks; /* dyn array of all the block's we're in ([0] = NULL for global scope) */
FnExpr *fn; /* the function we're currently parsing. */
char *pkg_name;
+ ErrCtx *err_ctx;
} Typer;
typedef struct Package {