summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c24
-rw-r--r--decls_cgen.c71
-rw-r--r--instance_table.c69
-rw-r--r--location.c7
-rw-r--r--test.toc8
-rw-r--r--typedefs_cgen.c7
-rw-r--r--types.h2
7 files changed, 122 insertions, 66 deletions
diff --git a/cgen.c b/cgen.c
index 169db09..57e3891 100644
--- a/cgen.c
+++ b/cgen.c
@@ -29,10 +29,9 @@ static bool cgen_defs_block(CGenerator *g, Block *b);
static bool cgen_defs_decl(CGenerator *g, Declaration *d);
#define cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f) \
- if (cgen_should_gen_fn(fn)) { \
if (!fn_enter(fn, 0)) return false; \
FnExpr *prev_fn = g->f##n; \
- g->f##n = fn; \
+ g->f##n = fn; \
arr_foreach(fn->params, Declaration, param) \
if (!decl_f(g, param)) \
return false; \
@@ -42,8 +41,7 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d);
if (!block_f(g, &fn->body)) \
return false; \
fn_exit(fn); \
- g->f##n = prev_fn; \
- }
+ g->f##n = prev_fn;
/* calls f on every sub-expression of e, block_f on every sub-block, and decl_f on every sub-declaration. */
#define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \
@@ -136,17 +134,17 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d);
for (U64 i = 0; i < fn->instances.cap; i++) { \
if (fn->instances.occupied[i]) { \
cgen_recurse_subexprs_fn_simple((&(*data)->fn), decl_f, block_f); \
- } \
- data++; \
- } \
- } else { \
- cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f); \
+ } \
+ data++; \
+ } \
+ } else { \
+ cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f); \
} \
} break; \
- case EXPR_NEW: \
- if (e->new.n && !f(g, e->new.n)) \
- return false; \
- break; \
+ case EXPR_NEW: \
+ if (e->new.n && !f(g, e->new.n)) \
+ return false; \
+ break; \
}
static bool cgen_block_enter(CGenerator *g, Block *b) {
diff --git a/decls_cgen.c b/decls_cgen.c
index 82bf56f..ca127db 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -47,7 +47,36 @@ static bool cgen_decls_expr(CGenerator *g, Expression *e) {
fn_exit(&e->fn);
}
}
- } break;
+ } 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;
+ }
+ }
+ } break;
default:
break;
}
@@ -86,44 +115,8 @@ static bool cgen_decls_decl(CGenerator *g, Declaration *d) {
}
cgen_recurse_subexprs(g, (&d->expr), cgen_decls_expr, cgen_decls_block, cgen_decls_decl);
} else if (d->flags & DECL_HAS_EXPR) {
- if (d->flags & DECL_IS_CONST) {
- for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
- Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
- if (type->kind == TYPE_TYPE) {
- Value *val = d->type.kind == TYPE_TUPLE ? &d->val.tuple[idx] : &d->val;
- if (val->type->kind == TYPE_STRUCT) {
- StructDef *sdef = val->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, d->where)) return false;
- cgen_write(g, " ");
- cgen_ident(g, f->name);
- if (!cgen_type_post(g, f->type, d->where)) return false;
- cgen_write(g, ";");
- cgen_nl(g);
- }
- g->indent_lvl--;
- cgen_write(g, "};");
- cgen_nl(g);
- sdef->flags |= STRUCT_DEF_CGENERATED;
- }
- }
- }
- }
- }
- if (!(d->flags & DECL_IS_CONST) || (d->expr.kind == EXPR_FN)) {
- if (!cgen_decls_expr(g, &d->expr))
- return false;
- }
+ if (!cgen_decls_expr(g, &d->expr))
+ return false;
}
return true;
}
diff --git a/instance_table.c b/instance_table.c
index d370a2a..7c8b61c 100644
--- a/instance_table.c
+++ b/instance_table.c
@@ -1,3 +1,12 @@
+/*
+ TODO: better hash functions, especially for integers
+ (right now, nearby integers are close together in hash
+ space, which is bad with the way these hash tables
+ are designed)
+*/
+
+/* NOTE: any time you see 0x then 16 hexadecimal digits, that's probably a random number for hashing */
+
/*
hash tables are initialized by setting them to {0}, e.g.
HashTable x = {0};
@@ -60,8 +69,55 @@ static U64 f64_hash(F64 f) {
return hash;
}
-static void fprint_val(FILE *f, Value v, Type *t); /* DELME */
-static void fprint_type(FILE *out, Type *t); /* !! */
+static U64 type_hash(Type *t) {
+ static const U64 starters[TYPE_COUNT] = {
+ 0x40d8675d0f148df7,
+ 0xee4db91f31fdf2e1,
+ 0x94963ca71f7f0df4,
+ 0x95b9d36f45f27cf2,
+ 0x68d393d7cade0570,
+ 0x8191b5178d728e8c,
+ 0x50da97f1211b2423,
+ 0xc3977306abd0ae6c,
+ 0x87ea684427e1c521,
+ 0xcee5fd6d6cbdfe23,
+ 0xd80dd2469d6e7c1b
+ };
+ U64 hash = starters[t->kind];
+ assert(t->flags & TYPE_IS_RESOLVED);
+ switch (t->kind) {
+ case TYPE_BUILTIN:
+ return hash + (U64)t->builtin * 0x1307787dfff73417;
+ case TYPE_VOID:
+ case TYPE_UNKNOWN:
+ case TYPE_TYPE:
+ return hash;
+ case TYPE_TUPLE:
+ arr_foreach(t->tuple, Type, sub)
+ hash = hash * type_hash(sub) + 0x16225b0aa9993299;
+ return hash;
+ case TYPE_FN:
+ arr_foreach(t->fn.types, Type, sub)
+ hash = hash * type_hash(sub) + 0x2092d851ab2008de;
+ return hash;
+ case TYPE_PTR:
+ hash += type_hash(t->ptr) * 0x277caae472151119 + 0xf5c6ae7b4dae3bcf;
+ return hash;
+ case TYPE_SLICE:
+ hash += type_hash(t->slice) * 0x67a571620f9a5d6a + 0xc3f91e92c844ab1f;
+ return hash;
+ case TYPE_STRUCT:
+ hash += (U64)t->struc;
+ return hash;
+ case TYPE_ARR:
+ hash += type_hash(t->arr.of) * 0x3b6256104800a414 + 0xa901e68bbd8968a1
+ + 0xbf79c81a3e68e504 * t->arr.n;
+ return hash;
+ case TYPE_EXPR: break;
+ }
+ assert(0); return 0;
+}
+
/* Note that for these value hashing functions, values of different types may collide */
static U64 val_ptr_hash(void *v, Type *t) {
assert(t->flags & TYPE_IS_RESOLVED);
@@ -97,7 +153,8 @@ static U64 val_ptr_hash(void *v, Type *t) {
return hash;
}
case TYPE_PTR: return (U64)*(void **)v;
- case TYPE_TYPE: return (U64)*(Type **)v;
+ case TYPE_TYPE:
+ return type_hash(*(Type **)v);
case TYPE_ARR: {
U32 x = 1;
U64 hash = 0;
@@ -165,8 +222,10 @@ 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:
- return type_eq(*(Type **)u, *(Type **)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;
diff --git a/location.c b/location.c
index 48fd269..d3ad5b8 100644
--- a/location.c
+++ b/location.c
@@ -2,3 +2,10 @@ static bool location_after(Location a, Location b) { /* a is after b? */
assert(a.ctx == b.ctx);
return a.code > b.code;
}
+
+static void fprint_location(FILE *out, Location location) {
+ char *newline = strchr(location.code, '\n');
+ if (newline) *newline = 0;
+ fprintf(out, "Line %ld: %s\n", (long)location.line, location.code);
+ if (newline) *newline = '\n';
+}
diff --git a/test.toc b/test.toc
index d5e24c4..936820e 100644
--- a/test.toc
+++ b/test.toc
@@ -23,11 +23,11 @@ y:s;
};
main @= fn() {
-// a : pair(int);
+a : pair(int);
b : pair(int);
c : pair(float);
-// a.x = 5;
-// puti(a.x);
+a.x = 5;
+puti(a.x);
c.x = 13.3;
-// putf(c.x);
+putf(c.x);
};
diff --git a/typedefs_cgen.c b/typedefs_cgen.c
index 9da3121..8c2d627 100644
--- a/typedefs_cgen.c
+++ b/typedefs_cgen.c
@@ -4,7 +4,6 @@ static bool typedefs_expr(CGenerator *g, Expression *e);
static bool typedefs_block(CGenerator *g, Block *b) {
Block *prev = g->block;
- printf("%s\n",b->stmts[0].where.code);
if (!cgen_block_enter(g, b))
return false;
arr_foreach(b->stmts, Statement, s)
@@ -85,10 +84,8 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) {
}
}
if (d->flags & DECL_HAS_EXPR) {
- if (!(d->flags & DECL_IS_CONST) || d->expr.kind == EXPR_FN) {
- if (!typedefs_expr(g, &d->expr))
- return false;
- }
+ if (!typedefs_expr(g, &d->expr))
+ return false;
}
return true;
}
diff --git a/types.h b/types.h
index 0c1c628..01b2fa0 100644
--- a/types.h
+++ b/types.h
@@ -299,8 +299,10 @@ typedef enum {
TYPE_TYPE,
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)
} TypeKind;
+
typedef enum {
BUILTIN_I8,
BUILTIN_I16,