summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c12
-rw-r--r--copy.c7
-rw-r--r--decls_cgen.c70
-rw-r--r--eval.c34
-rw-r--r--identifiers.c1
-rw-r--r--instance_table.c6
-rw-r--r--package.c7
-rw-r--r--parse.c8
-rw-r--r--test.toc2
-rw-r--r--typedefs_cgen.c103
-rw-r--r--types.c35
-rw-r--r--types.h12
12 files changed, 209 insertions, 88 deletions
diff --git a/cgen.c b/cgen.c
index 958b781..b94cdfc 100644
--- a/cgen.c
+++ b/cgen.c
@@ -5,7 +5,7 @@
*/
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev, Allocator *allocr) {
g->outc = out;
- g->ident_counter = 1; /* some places use 0 to mean no id */
+ g->ident_counter = 0;
g->main_ident = ident_get(ids, "main");
g->evalr = ev;
g->will_indent = true;
@@ -760,7 +760,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
case EXPR_WHILE:
case EXPR_EACH:
case EXPR_BLOCK: {
- id = g->ident_counter++;
+ id = ++g->ident_counter;
cgen_ident_id_to_str(ret_name, id);
char *p = ret_name + strlen(ret_name);
@@ -1026,7 +1026,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
}
if (cgen_uses_ptr(&e->type)
&& e->type.kind != TYPE_TUPLE) {
- e->call.c.id = g->ident_counter++;
+ e->call.c.id = ++g->ident_counter;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
cgen_write(g, " ");
cgen_ident_id(g, e->call.c.id);
@@ -1070,8 +1070,8 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
break;
case EXPR_SLICE: {
SliceExpr *s = &e->slice;
- IdentID s_id = e->slice.c.id = g->ident_counter++;
- IdentID from_id = g->ident_counter++;
+ IdentID s_id = e->slice.c.id = ++g->ident_counter;
+ IdentID from_id = ++g->ident_counter;
if (!cgen_expr_pre(g, s->of))
return false;
if (s->from && !cgen_expr_pre(g, s->from))
@@ -1135,7 +1135,7 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!cgen_val_pre(g, e->val, &e->type, e->where))
return false;
if (!cgen_type_pre(g, &e->type, e->where)) return false;
- e->val_c_id = g->ident_counter++;
+ e->val_c_id = ++g->ident_counter;
cgen_write(g, " ");
cgen_ident_id(g, e->val_c_id);
if (!cgen_type_post(g, &e->type, e->where)) return false;
diff --git a/copy.c b/copy.c
index 1b3c5ac..c13dfa1 100644
--- a/copy.c
+++ b/copy.c
@@ -38,6 +38,8 @@ 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: {
@@ -55,9 +57,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_TYPE:
- *out = *in;
- break;
case TYPE_EXPR:
assert(0);
}
@@ -268,7 +267,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) {
copy_expr(c, sout->to = allocr_malloc(a, sizeof *sout->to), sin->to);
} break;
case EXPR_PKG:
- copy_expr(c, out->pkg.name = allocr_malloc(a, sizeof *out->pkg.name), in->pkg.name);
+ copy_expr(c, out->pkg.name_expr = allocr_malloc(a, sizeof *out->pkg.name_expr), in->pkg.name_expr);
break;
case EXPR_TYPE:
copy_type(c, &out->typeval, &in->typeval);
diff --git a/decls_cgen.c b/decls_cgen.c
index 94e65df..85c574c 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -7,6 +7,41 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s);
static bool cgen_decls_block(CGenerator *g, Block *b);
static bool cgen_decls_decl(CGenerator *g, Declaration *d);
+static bool cgen_decls_type(CGenerator *g, Type *type, Location where) {
+ if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */
+ return true;
+ if (type->kind == TYPE_STRUCT) {
+ StructDef *sdef = type->struc;
+ if (!(sdef->flags & STRUCT_DEF_CGENERATED)) {
+ /* generate struct definition */
+ cgen_write(g, "struct ");
+ if (sdef->c.name) {
+ cgen_ident(g, sdef->c.name);
+ } else {
+ assert(sdef->c.id);
+ cgen_ident_id(g, sdef->c.id);
+ }
+ cgen_write(g, "{");
+ cgen_nl(g);
+ ++g->indent_lvl;
+ arr_foreach(sdef->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, "};");
+ cgen_nl(g);
+ sdef->flags |= STRUCT_DEF_CGENERATED;
+ }
+ }
+ cgen_recurse_into_type(cgen_decls_type, g, type, where);
+ return true;
+}
+
static bool cgen_fn_decl(CGenerator *g, FnExpr *f, Location where, U64 instance, U64 which_are_const) {
if (cgen_should_gen_fn(f)) {
if (!fn_enter(f, 0))
@@ -57,7 +92,7 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
FnExpr *f = e->fn;
f->c.name = NULL;
if (!f->c.id)
- f->c.id = g->ident_counter++;
+ f->c.id = ++g->ident_counter;
FnType *fn_type = &e->type.fn;
if (fn_type->constness) {
if (!cgen_decls_fn_instances(g, e))
@@ -69,33 +104,12 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
} break;
case EXPR_TYPE: {
Type *type = &e->typeval;
- if (type->kind == TYPE_STRUCT) {
- StructDef *sdef = type->struc;
- if (!(sdef->flags & STRUCT_DEF_CGENERATED)) {
- /* generate struct definition */
- cgen_write(g, "struct ");
- if (sdef->c.name)
- cgen_ident(g, sdef->c.name);
- else
- cgen_ident_id(g, sdef->c.id);
- cgen_write(g, "{");
- cgen_nl(g);
- ++g->indent_lvl;
- arr_foreach(sdef->fields, Field, f) {
- if (!cgen_type_pre(g, f->type, e->where)) return false;
- cgen_write(g, " ");
- cgen_ident(g, f->name);
- if (!cgen_type_post(g, f->type, e->where)) return false;
- cgen_write(g, ";");
- cgen_nl(g);
- }
- --g->indent_lvl;
- cgen_write(g, "};");
- cgen_nl(g);
- sdef->flags |= STRUCT_DEF_CGENERATED;
- }
- }
+ if (!cgen_decls_type(g, type, e->where))
+ return false;
} break;
+ case EXPR_CAST:
+ if (!cgen_decls_type(g, &e->cast.type, e->where))
+ return false;
default:
break;
}
@@ -117,6 +131,8 @@ static bool cgen_decls_block(CGenerator *g, Block *b) {
}
static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
+ if (!cgen_decls_type(g, &d->type, d->where))
+ return false;
if (cgen_fn_is_direct(g, d)) {
d->expr.fn->c.name = d->idents[0];
if (d->expr.type.fn.constness) {
diff --git a/eval.c b/eval.c
index ded9b5b..d6a29a8 100644
--- a/eval.c
+++ b/eval.c
@@ -56,6 +56,7 @@ static size_t compiler_sizeof_builtin(BuiltinType b) {
}
static size_t compiler_alignof(Type *t) {
+ Value v;
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
@@ -63,11 +64,11 @@ static size_t compiler_alignof(Type *t) {
case TYPE_VOID:
return 1;
case TYPE_FN:
- return sizeof(FnExpr *);
+ return sizeof v.fn;
case TYPE_PTR:
- return sizeof(void *);
+ return sizeof v.ptr;
case TYPE_TUPLE:
- return sizeof(Value *);
+ return sizeof v.tuple;
case TYPE_ARR:
return compiler_alignof(t->arr.of);
case TYPE_SLICE:
@@ -76,7 +77,9 @@ static size_t compiler_alignof(Type *t) {
else
return sizeof(size_t);
case TYPE_TYPE:
- return sizeof(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 */
size_t align = 1;
@@ -118,22 +121,25 @@ static void eval_struct_find_offsets(Type *t) {
/* size of a type at compile time */
static size_t compiler_sizeof(Type *t) {
+ Value v;
assert(t->flags & TYPE_IS_RESOLVED);
switch (t->kind) {
case TYPE_BUILTIN:
return compiler_sizeof_builtin(t->builtin);
case TYPE_FN:
- return sizeof(FnExpr *);
+ return sizeof v.fn;
case TYPE_PTR:
- return sizeof(void *);
+ return sizeof v.ptr;
case TYPE_ARR:
return t->arr.n * compiler_sizeof(t->arr.of);
case TYPE_TUPLE:
- return sizeof(Value *);
+ return sizeof v.tuple;
case TYPE_SLICE:
- return sizeof(Slice);
+ return sizeof v.slice;
case TYPE_TYPE:
- return sizeof(Type *);
+ return sizeof v.type;
+ case TYPE_PKG:
+ return sizeof v.pkg;
case TYPE_STRUCT: {
eval_struct_find_offsets(t);
return t->struc->size;
@@ -318,6 +324,10 @@ 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;
@@ -614,6 +624,9 @@ static void eval_deref(Value *v, void *ptr, Type *type) {
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:
@@ -652,6 +665,9 @@ static void eval_deref_set(void *set, Value *to, Type *type) {
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:
diff --git a/identifiers.c b/identifiers.c
index a7750a7..3bb3eb1 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -36,6 +36,7 @@ static Identifier ident_new(Identifiers *ids, Identifier parent, unsigned char i
for (size_t i = 0; i < TREE_NCHILDREN; ++i)
tree->children[i] = NULL;
tree->decls = NULL;
+ tree->pkg = NULL;
#endif
tree->parent = parent;
if (parent)
diff --git a/instance_table.c b/instance_table.c
index 3c859ac..aeb72d3 100644
--- a/instance_table.c
+++ b/instance_table.c
@@ -191,6 +191,10 @@ 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);
@@ -272,6 +276,8 @@ 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/package.c b/package.c
index 8c8ee77..de0ab43 100644
--- a/package.c
+++ b/package.c
@@ -261,6 +261,10 @@ 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);
@@ -406,8 +410,7 @@ static bool export_expr(Exporter *ex, Expression *e) {
return false;
} break;
case EXPR_PKG:
- if (!export_expr(ex, e->pkg.name))
- return false;
+ export_ident(ex, e->pkg.name_ident);
break;
case EXPR_SLICE: {
SliceExpr *s = &e->slice;
diff --git a/parse.c b/parse.c
index 0efe4ff..9cf3059 100644
--- a/parse.c
+++ b/parse.c
@@ -1013,7 +1013,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
case KW_PKG:
++t->token;
e->kind = EXPR_PKG;
- if (!parse_expr(p, e->pkg.name = parser_malloc(p, sizeof *e->pkg.name), expr_find_end(p, 0)))
+ if (!parse_expr(p, e->pkg.name_expr = parser_malloc(p, sizeof *e->pkg.name_expr), expr_find_end(p, 0)))
return false;
return true;
case KW_FN: {
@@ -2236,7 +2236,11 @@ static void fprint_expr(FILE *out, Expression *e) {
break;
case EXPR_PKG:
fprintf(out, "(pkg ");
- fprint_expr(out, e->pkg.name);
+ if (found_type) {
+ fprint_ident(out, e->pkg.name_ident);
+ } else {
+ fprint_expr(out, e->pkg.name_expr);
+ }
fprintf(out, ")");
break;
}
diff --git a/test.toc b/test.toc
index d3f0f3e..e88affb 100644
--- a/test.toc
+++ b/test.toc
@@ -17,4 +17,6 @@ main ::= fn() {
puti(a); puti(b);
c:x = 7;
d:x = 18;
+ k : [5]struct {x: int; y: int;};
+ puti(k[0].x);
}; \ No newline at end of file
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index 3050409..531fb0d 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -7,6 +7,75 @@ static bool typedefs_stmt(CGenerator *g, Statement *s);
static bool typedefs_decl(CGenerator *g, Declaration *d);
static bool typedefs_expr(CGenerator *g, Expression *e);
+#define cgen_recurse_into_type(f, g, type, extra) \
+ switch (type->kind) { \
+ case TYPE_STRUCT: \
+ arr_foreach(type->struc->fields, Field, fl) \
+ if (!f(g, fl->type, extra)) \
+ return false; \
+ break; \
+ case TYPE_FN: \
+ arr_foreach(type->fn.types, Type, sub) { \
+ if (!f(g, sub, extra)) \
+ return false; \
+ } \
+ break; \
+ case TYPE_TUPLE: \
+ arr_foreach(type->tuple, Type, sub) \
+ if (!f(g, sub, extra)) \
+ return false; \
+ break; \
+ case TYPE_ARR: \
+ if (!f(g, type->arr.of, extra)) \
+ return false; \
+ break; \
+ case TYPE_SLICE: \
+ if (!f(g, type->slice, extra)) \
+ return false; \
+ break; \
+ case TYPE_PTR: \
+ if (!f(g, type->ptr, extra)) \
+ return false; \
+ break; \
+ case TYPE_VOID: \
+ case TYPE_BUILTIN: \
+ case TYPE_PKG: \
+ case TYPE_TYPE: \
+ case TYPE_UNKNOWN: \
+ break; \
+ case TYPE_EXPR: assert(0); \
+ }
+
+
+/* i is the name for this type, NULL if not available */
+/* ALWAYS RETURNS TRUE. it just returns a bool for cgen_recurse_into_type to work */
+static bool typedefs_type(CGenerator *g, Type *type, Identifier i) {
+ if (!(type->flags & TYPE_IS_RESOLVED)) /* non-instance constant fn parameter type */
+ return true;
+ if (type->kind == TYPE_STRUCT) {
+ StructDef *sdef = type->struc;
+ /* we'll actually define the struct later; here we can just declare it */
+
+ if (sdef->c.id || sdef->c.name) {
+ /* we've already done this */
+ } else {
+ cgen_write(g, "struct ");
+ if (i) {
+ cgen_ident(g, i);
+ sdef->c.name = i;
+ } else {
+ IdentID id = ++g->ident_counter;
+ cgen_ident_id(g, id);
+ sdef->c.id = id;
+ }
+ cgen_write(g, ";");
+ cgen_nl(g);
+ }
+ }
+ cgen_recurse_into_type(typedefs_type, g, type, NULL);
+ return true;
+}
+
static bool typedefs_block(CGenerator *g, Block *b) {
Block *prev = g->block;
if (!cgen_block_enter(g, b))
@@ -22,9 +91,12 @@ static bool typedefs_block(CGenerator *g, Block *b) {
static bool typedefs_expr(CGenerator *g, Expression *e) {
cgen_recurse_subexprs(g, e, typedefs_expr, typedefs_block, typedefs_decl);
+ if (e->kind == EXPR_CAST) {
+ typedefs_type(g, &e->cast.type, NULL);
+ }
if (e->kind == EXPR_FN) {
/* needs to go before decls_cgen.c... */
- e->fn->c.id = g->ident_counter++;
+ e->fn->c.id = ++g->ident_counter;
}
if (e->kind == EXPR_TYPE && e->typeval.kind == TYPE_STRUCT) {
StructDef *sdef = e->typeval.struc;
@@ -32,7 +104,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) {
/* we've already done this */
} else {
cgen_write(g, "struct ");
- IdentID id = g->ident_counter++;
+ IdentID id = ++g->ident_counter;
cgen_ident_id(g, id);
sdef->c.id = id;
cgen_write(g, ";");
@@ -43,6 +115,7 @@ static bool typedefs_expr(CGenerator *g, Expression *e) {
}
static bool typedefs_decl(CGenerator *g, Declaration *d) {
+ typedefs_type(g, &d->type, NULL);
if (cgen_fn_is_direct(g, d)) {
d->expr.fn->c.name = d->idents[0];
}
@@ -52,26 +125,12 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) {
Value *val = decl_val_at_index(d, idx);
if (type->kind == TYPE_TYPE) {
/* generate typedef */
- IdentID id = 0;
- if (g->block != NULL || g->fn != NULL)
- id = g->ident_counter++;
- if (val->type->kind == TYPE_STRUCT) {
- /* we'll actually define the struct later; here we can just declare it */
- StructDef *sdef = val->type->struc;
- if (sdef->c.id || sdef->c.name) {
- /* we've already done this */
- } else {
- cgen_write(g, "struct ");
- if (id) {
- cgen_ident_id(g, id);
- sdef->c.id = id;
- } else {
- cgen_ident(g, i);
- sdef->c.name = i;
- }
- cgen_write(g, ";");
- }
- } else {
+ typedefs_type(g, val->type, i);
+
+ if (val->type->kind != TYPE_STRUCT) {
+ IdentID id = 0;
+ if (g->block != NULL || g->fn != NULL)
+ id = ++g->ident_counter;
if (val->type->kind != TYPE_TYPE) {
cgen_write(g, "typedef ");
if (!cgen_type_pre(g, val->type, d->where)) return false;
diff --git a/types.c b/types.c
index 143dbec..66a31e9 100644
--- a/types.c
+++ b/types.c
@@ -7,6 +7,7 @@ static bool types_stmt(Typer *tr, Statement *s);
static bool types_block(Typer *tr, Block *b);
static bool type_resolve(Typer *tr, Type *t, Location where);
+
static inline void *typer_malloc(Typer *tr, size_t bytes) {
return allocr_malloc(tr->allocr, bytes);
}
@@ -23,6 +24,10 @@ 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) {
@@ -826,7 +831,7 @@ static bool types_expr(Typer *tr, Expression *e) {
case EXPR_LITERAL_INT:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_I64;
- t->flags |= TYPE_IS_FLEXIBLE | TYPE_IS_RESOLVED;
+ t->flags |= TYPE_IS_FLEXIBLE;
break;
case EXPR_LITERAL_STR:
t->kind = TYPE_SLICE;
@@ -835,22 +840,25 @@ static bool types_expr(Typer *tr, Expression *e) {
t->slice->was_expr = NULL;
t->slice->kind = TYPE_BUILTIN;
t->slice->builtin = BUILTIN_CHAR;
- t->flags |= TYPE_IS_RESOLVED;
break;
case EXPR_LITERAL_FLOAT:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_F32;
- t->flags |= TYPE_IS_FLEXIBLE | TYPE_IS_RESOLVED;
+ t->flags |= TYPE_IS_FLEXIBLE;
break;
case EXPR_LITERAL_BOOL:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_BOOL;
- t->flags |= TYPE_IS_RESOLVED;
break;
case EXPR_LITERAL_CHAR:
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_CHAR;
- t->flags |= TYPE_IS_RESOLVED;
+ break;
+ case EXPR_PKG:
+ t->kind = TYPE_PKG;
+ Expression *name_expr = e->pkg.name_expr;
+ if (!types_expr(tr, name_expr)) return false;
+ Value name_val;
break;
case EXPR_EACH: {
EachExpr *ea = e->each;
@@ -1476,10 +1484,9 @@ static bool types_expr(Typer *tr, Expression *e) {
Expression *code = e->c.code;
if (!types_expr(tr, code))
return false;
- if (code->type.kind != TYPE_SLICE
- || !type_is_builtin(code->type.slice, BUILTIN_CHAR)) {
+ if (!type_is_slicechar(&code->type)) {
char *s = type_to_str(&code->type);
- err_print(e->where, "Argument to #C directive must be a string, but got type %s.");
+ err_print(e->where, "Argument to #C directive must of type []char, but got type %s.");
free(s);
return false;
}
@@ -1732,8 +1739,7 @@ static bool types_expr(Typer *tr, Expression *e) {
/* fallthrough */
case TYPE_STRUCT: {
/* allow accessing struct members with a string */
- if (rhs_type->kind != TYPE_SLICE
- || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) {
+ if (!type_is_slicechar(rhs_type)) {
char *s = type_to_str(rhs_type);
err_print(e->where, "Expected a string for struct member access with [], but got type %s.", s);
return false;
@@ -1803,10 +1809,11 @@ static bool types_expr(Typer *tr, Expression *e) {
Value field_name;
if (!types_expr(tr, rhs)) return false;
- if (rhs_type->kind != TYPE_SLICE || !type_is_builtin(rhs_type->slice, BUILTIN_CHAR)) {
- err_print(e->where, "Invalid field of type %s.");
+ if (!type_is_slicechar(rhs_type)) {
+ char *s = type_to_str(rhs_type);
+ err_print(e->where, "Invalid field of type %s.", s);
+ free(s);
return false;
-
}
if (!eval_expr(tr->evalr, rhs, &field_name)) return false;
char *str = field_name.slice.data;
@@ -2125,7 +2132,7 @@ static bool types_file(Typer *tr, ParsedFile *f, char *code) {
Value pkg_name;
if (!types_expr(tr, f->pkg_name))
return false;
- if (f->pkg_name->type.kind != TYPE_SLICE || !type_is_builtin(f->pkg_name->type.slice, BUILTIN_CHAR)) {
+ if (!type_is_slicechar(&f->pkg_name->type)) {
char *typestr = type_to_str(&f->pkg_name->type);
err_print(f->pkg_name->where, "Package names must be of type []char, but this is of type %s.", typestr);
free(typestr);
diff --git a/types.h b/types.h
index 147ee44..dc0d817 100644
--- a/types.h
+++ b/types.h
@@ -150,6 +150,7 @@ typedef union Value {
union Value *tuple;
Slice slice;
struct Type *type;
+ struct Package *pkg;
} Value;
enum {
@@ -187,6 +188,7 @@ typedef struct IdentTree {
unsigned char index_in_parent; /* index of this in .parent.children */
bool export_name; /* is this identifier's name important? */
U64 export_id; /* 0 if there's no exported identifier here, otherwise unique positive integer associated with this identifier */
+ struct Package *pkg; /* NULL if this is not associated with a package */
struct IdentTree *parent;
struct IdentTree *children[TREE_NCHILDREN];
IdentDecl *decls; /* array of declarations of this identifier */
@@ -643,8 +645,9 @@ typedef struct Expression {
struct {
Type type;
} del;
- struct {
- struct Expression *name;
+ union {
+ struct Expression *name_expr;
+ Identifier name_ident;
} pkg;
IfExpr if_;
WhileExpr while_;
@@ -763,6 +766,10 @@ typedef struct Typer {
char *pkg_name;
} Typer;
+typedef struct Package {
+ Identifier name;
+ Identifiers idents;
+} Package;
typedef struct Exporter {
FILE *out; /* .top (toc package) to output to */
@@ -790,6 +797,7 @@ typedef struct CGenerator {
Identifiers *idents;
} CGenerator;
+
#ifdef TOC_DEBUG
#define add_ident_decls(b, d, flags) add_ident_decls_(__FILE__, __LINE__, b, d, flags)
#endif