summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c4
-rw-r--r--test.toc21
-rw-r--r--tests/arr3.toc14
-rw-r--r--types.c244
4 files changed, 143 insertions, 140 deletions
diff --git a/main.c b/main.c
index ac039e9..b397804 100644
--- a/main.c
+++ b/main.c
@@ -8,7 +8,6 @@
/*
@TODO:
-local structs should not be named in C
make sure global slices work
allow `use ???;` if an error has already occurred
if something gets included into a namespace, and its typing fails, the namespace should still be of type namespace, not ???
@@ -17,8 +16,7 @@ do we consistently handle x := &some_array_or_slice; x.len
use
- use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
compile to a temp file, then move it if compilation succeeds
-if you include something twice, it should #define one thing to the other -- it's okay because struct field can't contain __
- -> allow #force'd includes to namespaces
+fix including something twice - just use the non-namespacey version if it exists or pick one namespace to use everywhere otherwise
&void
simplify eval macros with val_to_u/i64
#if should not create a block
diff --git a/test.toc b/test.toc
index c6deab2..990e8a4 100644
--- a/test.toc
+++ b/test.toc
@@ -1,22 +1,37 @@
//#include "std/io.toc";
-#include "std/io.toc", foo;
-#include "std/io.toc", bar;
+#include "std/io.toc";
c_add ::= fn(x:int, y:int) int {
#C("x+y")
}
main ::= fn() {
+ {
xs : [5]Point;
for use x, i := &xs {
z = c_add(i*i, i*i*i) as f32;
}
for use x := xs {
- foo.puti(z as int);
+ puti(z as int);
}
Point ::= struct {
x: int;
y: int;
z: f32;
}
+ }
+ {
+ xs : [5]Point;
+ for use x, i := &xs {
+ z = c_add(i*i, i*i*i) as f32;
+ }
+ for use x := xs {
+ puti(z as int);
+ }
+ Point ::= struct {
+ x: int;
+ y: int;
+ z: f32;
+ }
+ }
}
diff --git a/tests/arr3.toc b/tests/arr3.toc
index cfbbc5a..4310d64 100644
--- a/tests/arr3.toc
+++ b/tests/arr3.toc
@@ -1,11 +1,6 @@
#include "io.toc";
#include "mem.toc";
-Arr ::= struct (t :: Type) {
- data: []t;
- len, cap: int;
-};
-
arr_add ::= fn(t ::=, a : &Arr(t), x : t) {
if a.len >= a.cap {
@@ -33,14 +28,14 @@ square ::= fn(t ::=, x : t) t {
};
-// ArrInt ::= Arr(int);
+ArrInt ::= Arr(int);
inc ::= fn(t ::=, x : t) t {
x + 1
};
main ::= fn() {
- arr : Arr(int);
+ arr : ArrInt;
farr : Arr(float);
for i := 1..100 {
arr_add(&arr, inc(square(i)));
@@ -53,3 +48,8 @@ main ::= fn() {
puti(farr.data[i] as int);
}
};
+
+Arr ::= struct (t :: Type) {
+ data: []t;
+ len, cap: int;
+};
diff --git a/types.c b/types.c
index b58e040..63b96c5 100644
--- a/types.c
+++ b/types.c
@@ -75,37 +75,125 @@ static size_t compiler_alignof_builtin(BuiltinType b) {
return 0;
}
-/* finds offsets and size */
-static Status struct_find_offsets(StructDef *s) {
- /* assume the align of a struct is the greatest align out of its children's */
- if (!(s->flags & STRUCT_DEF_FOUND_OFFSETS)) {
- if (s->flags & STRUCT_DEF_FINDING_OFFSETS) {
- err_print(s->where, "Circular dependency in struct!");
+/* new_stmts is what s->body.stmts will become after typing is done */
+static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement **new_stmts) {
+ arr_foreach(b->stmts, Statement, stmt) {
+ if (stmt->kind == STMT_EXPR) {
+ if (stmt->expr->kind == EXPR_BLOCK) {
+ if (!add_block_to_struct(tr, stmt->expr->block, s, new_stmts))
+ return false;
+ continue;
+ }
+ }
+ if (stmt->kind != STMT_DECL) {
+ err_print(stmt->where, "structs can only contain declarations.");
return false;
}
- s->flags |= STRUCT_DEF_FINDING_OFFSETS;
- size_t bytes = 0;
- size_t total_align = 1;
- arr_foreach(s->fields, Field, f) {
- size_t size = compiler_sizeof(f->type);
- if (size == SIZE_MAX) {
- info_print(f->where, "... while descending into this field of a struct.");
+ Declaration *d = stmt->decl;
+ DeclFlags flags = d->flags;
+ if (flags & DECL_EXPORT) {
+ err_print(d->where, "struct members can't be exported.");
+ return false;
+ }
+ if (flags & DECL_IS_CONST) {
+ if (flags & DECL_INFER) {
+ err_print(d->where, "struct members can't be inferred.");
+ return false;
+ }
+ typer_arr_add(tr, *new_stmts, *stmt);
+ } else {
+ if (flags & DECL_SEMI_CONST) {
+ err_print(d->where, "struct members can't be semi-constant.");
return false;
}
- size_t falign = compiler_alignof(f->type);
- if (falign > total_align)
- total_align = falign;
- /* align */
- bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */
- assert(bytes % falign == 0);
- f->offset = bytes;
- /* add size */
- bytes += size;
- }
- bytes += ((total_align - bytes) % total_align + total_align) % total_align; /* = -bytes mod align */
- s->size = bytes;
- s->align = total_align;
- s->flags |= STRUCT_DEF_FOUND_OFFSETS;
+ if (flags & DECL_HAS_EXPR) {
+ err_print(d->where, "Non-constant struct members can't have initializers.");
+ return false;
+ }
+ int i = 0;
+ arr_foreach(d->idents, Identifier, ident) {
+ Field *field = typer_arr_add_ptr(tr, s->fields);
+ field->where = d->where;
+ field->name = *ident;
+ field->type = decl_type_at_index(d, i);
+ ++i;
+ }
+
+ typer_arr_add(tr, *new_stmts, *stmt);
+ }
+ if (b != &s->body) {
+ /* we need to translate d's identifiers to s's scope */
+ arr_foreach(d->idents, Identifier, ip) {
+ Identifier redeclared = ident_get(&s->body.idents, (*ip)->str);
+ if (redeclared) {
+ char *str = ident_to_str(*ip);
+ err_print(d->where, "Redeclaration of struct member %s", str);
+ info_print(ident_decl_location(redeclared), "Previous declaration was here.");
+ free(str);
+ return false;
+ }
+ *ip = ident_translate_forced(*ip, &s->body.idents);
+ (*ip)->decl = d;
+ }
+ }
+ }
+ return true;
+}
+
+static Status struct_resolve(Typer *tr, StructDef *s) {
+ if (!(s->flags & STRUCT_DEF_RESOLVED)) {
+ { /* resolving stuff */
+ if (!types_block(tr, &s->body))
+ return false;
+ s->fields = NULL;
+ Statement *new_stmts = NULL;
+ if (!add_block_to_struct(tr, &s->body, s, &new_stmts))
+ return false;
+ s->body.stmts = new_stmts;
+ /* set the field of each declaration, so that we can lookup struct members quickly */
+ Field *field = s->fields;
+ arr_foreach(new_stmts, Statement, stmt) {
+ assert(stmt->kind == STMT_DECL);
+ Declaration *decl = stmt->decl;
+ if (!(decl->flags & DECL_IS_CONST)) {
+ assert(!(decl->flags & DECL_HAS_EXPR));
+ decl->field = field;
+ field += arr_len(decl->idents);
+ }
+ }
+ s->instance_id = 0;
+ }
+ /* find offsets and size */
+ /* assume the align of a struct is the greatest align out of its children's */
+ {
+ if (s->flags & STRUCT_DEF_FINDING_OFFSETS) {
+ err_print(s->where, "Circular dependency in struct!");
+ return false;
+ }
+ s->flags |= STRUCT_DEF_FINDING_OFFSETS;
+ size_t bytes = 0;
+ size_t total_align = 1;
+ arr_foreach(s->fields, Field, f) {
+ size_t size = compiler_sizeof(f->type);
+ if (size == SIZE_MAX) {
+ info_print(f->where, "... while descending into this field of a struct.");
+ return false;
+ }
+ size_t falign = compiler_alignof(f->type);
+ if (falign > total_align)
+ total_align = falign;
+ /* align */
+ bytes += ((falign - bytes) % falign + falign) % falign; /* = -bytes mod falign */
+ assert(bytes % falign == 0);
+ f->offset = bytes;
+ /* add size */
+ bytes += size;
+ }
+ bytes += ((total_align - bytes) % total_align + total_align) % total_align; /* = -bytes mod align */
+ s->size = bytes;
+ s->align = total_align;
+ }
+ s->flags |= STRUCT_DEF_RESOLVED;
}
return true;
}
@@ -131,8 +219,6 @@ static size_t compiler_alignof(Type *t) {
else
return toc_alignof(size_t);
case TYPE_STRUCT:
- if (!struct_find_offsets(t->struc))
- return SIZE_MAX;
return t->struc->align;
case TYPE_UNKNOWN:
case TYPE_EXPR:
@@ -160,8 +246,6 @@ static size_t compiler_sizeof(Type *t) {
case TYPE_SLICE:
return sizeof v.slice;
case TYPE_STRUCT: {
- if (!struct_find_offsets(t->struc))
- return SIZE_MAX;
return t->struc->size;
} break;
case TYPE_VOID:
@@ -692,97 +776,6 @@ top:;
return true;
}
-/* new_stmts is what s->body.stmts will become after typing is done */
-static Status add_block_to_struct(Typer *tr, Block *b, StructDef *s, Statement **new_stmts) {
- arr_foreach(b->stmts, Statement, stmt) {
- if (stmt->kind == STMT_EXPR) {
- if (stmt->expr->kind == EXPR_BLOCK) {
- if (!add_block_to_struct(tr, stmt->expr->block, s, new_stmts))
- return false;
- continue;
- }
- }
- if (stmt->kind != STMT_DECL) {
- err_print(stmt->where, "structs can only contain declarations.");
- return false;
- }
- Declaration *d = stmt->decl;
- DeclFlags flags = d->flags;
- if (flags & DECL_EXPORT) {
- err_print(d->where, "struct members can't be exported.");
- return false;
- }
- if (flags & DECL_IS_CONST) {
- if (flags & DECL_INFER) {
- err_print(d->where, "struct members can't be inferred.");
- return false;
- }
- typer_arr_add(tr, *new_stmts, *stmt);
- } else {
- if (flags & DECL_SEMI_CONST) {
- err_print(d->where, "struct members can't be semi-constant.");
- return false;
- }
- if (flags & DECL_HAS_EXPR) {
- err_print(d->where, "Non-constant struct members can't have initializers.");
- return false;
- }
- int i = 0;
- arr_foreach(d->idents, Identifier, ident) {
- Field *field = typer_arr_add_ptr(tr, s->fields);
- field->where = d->where;
- field->name = *ident;
- field->type = decl_type_at_index(d, i);
- ++i;
- }
-
- typer_arr_add(tr, *new_stmts, *stmt);
- }
- if (b != &s->body) {
- /* we need to translate d's identifiers to s's scope */
- arr_foreach(d->idents, Identifier, ip) {
- Identifier redeclared = ident_get(&s->body.idents, (*ip)->str);
- if (redeclared) {
- char *str = ident_to_str(*ip);
- err_print(d->where, "Redeclaration of struct member %s", str);
- info_print(ident_decl_location(redeclared), "Previous declaration was here.");
- free(str);
- return false;
- }
- *ip = ident_translate_forced(*ip, &s->body.idents);
- (*ip)->decl = d;
- }
- }
- }
- return true;
-}
-
-static Status struct_resolve(Typer *tr, StructDef *s) {
- if (!(s->flags & STRUCT_DEF_RESOLVED)) {
- if (!types_block(tr, &s->body))
- return false;
- s->fields = NULL;
- Statement *new_stmts = NULL;
- if (!add_block_to_struct(tr, &s->body, s, &new_stmts))
- return false;
- s->body.stmts = new_stmts;
- /* set the field of each declaration, so that we can lookup struct members quickly */
- Field *field = s->fields;
- arr_foreach(new_stmts, Statement, stmt) {
- assert(stmt->kind == STMT_DECL);
- Declaration *decl = stmt->decl;
- if (!(decl->flags & DECL_IS_CONST)) {
- assert(!(decl->flags & DECL_HAS_EXPR));
- decl->field = field;
- field += arr_len(decl->idents);
- }
- }
- s->instance_id = 0;
- s->flags |= STRUCT_DEF_RESOLVED;
- }
- return true;
-}
-
/* fixes the type (replaces [5+3]int with [8]int, etc.) */
static Status type_resolve(Typer *tr, Type *t, Location where) {
Evaluator *ev = tr->evalr;
@@ -904,10 +897,6 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
case TYPE_BUILTIN:
break;
}
- if (t->kind == TYPE_STRUCT && !!(t->struc->params) == !!(t->struc->instance_id)) { /* don't want it to try to deal with templates */
- if (!struct_find_offsets(t->struc))
- return false;
- }
assert(t->kind != TYPE_EXPR);
t->flags |= TYPE_IS_RESOLVED;
return true;
@@ -3341,7 +3330,8 @@ static Status types_decl(Typer *tr, Declaration *d) {
if ((d->flags & DECL_HAS_EXPR)
&& d->expr.kind == EXPR_TYPE
- && d->expr.typeval->kind == TYPE_STRUCT) {
+ && d->expr.typeval->kind == TYPE_STRUCT
+ && tr->fn == NULL) {
d->expr.typeval->struc->name = d->idents[0];
}