aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-06 14:10:19 +0200
committerlemon <lsof@mailbox.org>2022-08-06 14:10:29 +0200
commitb8d9ad1f6636f46a832b0f949ce7525ae08f53bd (patch)
tree037c7e0a86835b2e284df786e3ba2680b7677cc4 /bootstrap
parent1dd19e56fb81d1334bb21e4aa097f9593576feb7 (diff)
basic method calls & many bugfix
Diffstat (limited to 'bootstrap')
-rw-r--r--bootstrap/.gitignore1
-rw-r--r--bootstrap/all.h28
-rw-r--r--bootstrap/cgen.c79
-rw-r--r--bootstrap/dump.c9
-rw-r--r--bootstrap/env.c28
-rw-r--r--bootstrap/main.c1
-rw-r--r--bootstrap/parse.c178
-rw-r--r--bootstrap/test.cff40
-rw-r--r--bootstrap/types.c67
-rw-r--r--bootstrap/util.c17
10 files changed, 336 insertions, 112 deletions
diff --git a/bootstrap/.gitignore b/bootstrap/.gitignore
index b5e3e58..51939a1 100644
--- a/bootstrap/.gitignore
+++ b/bootstrap/.gitignore
@@ -1,4 +1,5 @@
compile_commands.json
a.out
cff0
+.gdb_history
.cache/
diff --git a/bootstrap/all.h b/bootstrap/all.h
index 15f932c..ff20c25 100644
--- a/bootstrap/all.h
+++ b/bootstrap/all.h
@@ -177,6 +177,7 @@ struct type {
const char *name;
const struct type *ty;
}) flds;
+ slice_t(struct decl) decls;
bool fwd;
int id;
} agg;
@@ -263,6 +264,7 @@ enum exprtype {
Ezeroini,
Eini,
Eget,
+ Emcall,
};
struct blockstmt {
@@ -316,6 +318,10 @@ struct expr {
struct expr *lhs;
const char *fld;
} get;
+ struct {
+ struct fn *met;
+ slice_t(struct expr) args;
+ } mcall;
};
};
@@ -434,15 +440,27 @@ bswap64(u64 x) {
#define vec_slice_cpy(slice, v) \
((slice)->d = vec_compact(v), \
(slice)->n = (v)->length)
+
+#define container_of(x, T, fld) \
+ (T *)((char *)(x) - offsetof(T, fld))
+
///
/////////////////////////////////
/** util.c **/
-u32 jkhash(u32 hash, const u8 *data, size_t length);
-#define jkhashv(h, v) jkhash(h, (void *)&(v), sizeof((v)))
+#define FNV1A_INI 0x84222325u
+u32 fnv1a(u32 hash, const void *data, size_t length);
+static inline u32
+fnv1ai(u32 hash, int i) {
+ return fnv1a(hash, &i, sizeof i);
+}
+static inline u32
+fnv1aI(u32 hash, i64 i) {
+ return fnv1a(hash, &i, sizeof i);
+}
static inline u32
-jkhashu32(u32 h, u32 x) {
- return jkhashv(h, x);
+fnv1az(u32 hash, size_t i) {
+ return fnv1a(hash, &i, sizeof i);
}
int addfilepath(const char *);
const char *fileid2path(int);
@@ -485,7 +503,7 @@ const struct type *typeof2(const struct type *a, const struct type *b);
/** env.c **/
struct decl *envfind(const struct env *, const char *name);
-bool envput(struct env *, const struct decl *decl);
+struct decl *envput(struct env *, const struct decl *decl);
struct env *mkenv(const struct env *parent);
/** dump.c **/
diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c
index 8685ffe..3df1ce7 100644
--- a/bootstrap/cgen.c
+++ b/bootstrap/cgen.c
@@ -33,7 +33,7 @@ gentype(const struct type *ty) {
case TYeunion:
assert(ty->_cname);
pri("%s", ty->_cname);
- return;
+ break;
case TYenum:
gentype(ty->enu.intty);
break;
@@ -155,6 +155,8 @@ geniniex(struct expr *ex) {
static void
genexpr(struct expr *ex) {
const struct type *ty = unconstify(ex->ty);
+ struct decl *decl;
+
switch (ex->t) {
case Eintlit:
intlit:
@@ -234,6 +236,17 @@ genexpr(struct expr *ex) {
case Eget:
pri("%e%s%s", ex->get.lhs, ex->get.lhs->ty->t == TYptr ? "->" : ".", ex->get.fld);
break;
+ case Emcall:
+ decl = container_of(ex->mcall.met, struct decl, fn);
+ assert(*decl->_cname);
+ pri("%s(", *decl->_cname);
+ for (int i = 0; i < ex->mcall.args.n; ++i) {
+ pri("%e", &ex->mcall.args.d[i]);
+ if (i < ex->mcall.args.n - 1)
+ pri(", ");
+ }
+ pri(")");
+ break;
}
}
@@ -343,7 +356,7 @@ genblock(struct blockstmt block) {
static void liftnested(struct stmt *stmt);
-// lift nested fns and static vars
+static void liftdecl(struct decl *decl);
static void
liftnestedex(struct expr *ex) {
@@ -390,12 +403,41 @@ liftnestedex(struct expr *ex) {
case Eget:
liftnestedex(ex->get.lhs);
break;
+ case Emcall:
+ liftdecl(container_of(ex->mcall.met, struct decl, fn));
+ for (int i = 0; i < ex->call.args.n; ++i)
+ liftnestedex(&ex->mcall.args.d[i]);
+ break;
+ }
+}
+
+static void
+liftdecl(struct decl *decl) {
+ static int id;
+ switch (decl->t) {
+ case Dfn:
+ if (decl->fn.body) {
+ *decl->_cname = xasprintf("__f%s_%d", decl->fn.name, id++);
+ genfn(decl->externp, *decl->_cname, &decl->fn);
+ }
+ break;
+ case Dstatic:
+ if (!decl->externp) {
+ assert(decl->var.ini);
+ *decl->_cname = xasprintf("__s%s_%d", decl->name, id++);
+ genstatic(decl->externp, *decl->_cname, &decl->var);
+ }
+ break;
+ case Dlet:
+ liftnestedex(decl->var.ini);
+ break;
+ default:
+ break;
}
}
static void // lift nested fns and static vars
liftnested(struct stmt *stmt) {
- static int id;
if (!stmt)
return;
switch (stmt->t) {
@@ -407,26 +449,7 @@ liftnested(struct stmt *stmt) {
liftnestedex(&stmt->expr);
break;
case Sdecl:
- switch (stmt->decl.t) {
- case Dfn:
- if (stmt->decl.fn.body) {
- *stmt->decl._cname = xasprintf("__f%s_%d", stmt->decl.fn.name, id++);
- genfn(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.fn);
- }
- break;
- case Dstatic:
- if (!stmt->decl.externp) {
- assert(stmt->decl.var.ini);
- *stmt->decl._cname = xasprintf("__s%s_%d", stmt->decl.name, id++);
- genstatic(stmt->decl.externp, *stmt->decl._cname, &stmt->decl.var);
- }
- break;
- case Dlet:
- liftnestedex(stmt->decl.var.ini);
- break;
- default:
- break;
- }
+ liftdecl(&stmt->decl);
break;
case Sifelse:
liftnested(stmt->ifelse.f);
@@ -525,11 +548,8 @@ defctype(const struct type *ty, void *_) {
if (!ty->_cname)
switch (ty->t) {
case TYvoid: case TYbool:
- case TYint: case TYfloat:
+ case TYenum: case TYint: case TYfloat:
break;
- case TYenum:
- defctype(ty->enu.intty, NULL);
- return;
case TYptr:
defctype(ty->child, NULL);
break;
@@ -566,6 +586,11 @@ defctype(const struct type *ty, void *_) {
case TYunion:
kind = "union";
agg:
+ if (ty->konst) {
+ defctype(unconstify(ty), NULL);
+ *cname = (char *)unconstify(ty)->_cname;
+ break;
+ }
*cname = xasprintf("__ty%s%d", ty->agg.name ? ty->agg.name : "", id++);
pri("typedef %s %s %s;\n", kind, *cname, *cname);
if (!ty->agg.fwd) {
diff --git a/bootstrap/dump.c b/bootstrap/dump.c
index 12a5a2a..8bec36d 100644
--- a/bootstrap/dump.c
+++ b/bootstrap/dump.c
@@ -164,14 +164,21 @@ vepri(const char *fmt, va_list ap) {
int ws;
for (char c; (c = *fmt++);) {
+ bool bold = 0;
if (c != '%') {
fputc(c, stderr);
continue;
}
+ again:
+ if (bold)
+ fprintf(stderr, "\x1b[1m");
switch ((c = *fmt++)) {
case '%':
fputc(c, stderr);
break;
+ case 'b':
+ bold = 1;
+ goto again;
case 'c':
ch = bswap32(va_arg(ap, int));
while (ch) {
@@ -226,6 +233,8 @@ vepri(const char *fmt, va_list ap) {
abort();
break;
}
+ if (bold)
+ fprintf(stderr, "\x1b[0m");
}
}
diff --git a/bootstrap/env.c b/bootstrap/env.c
index 0c0021b..477c267 100644
--- a/bootstrap/env.c
+++ b/bootstrap/env.c
@@ -30,21 +30,37 @@ declscompatible(const struct decl *a, const struct decl *b) {
return 0;
}
-bool
+struct decl *
envput(struct env *env, const struct decl *decl) {
struct decls *decls;
struct env env_noparent = {
.decls = env->decls
};
- struct decl *decl0;
- if ((decl0 = envfind(&env_noparent, decl->name))) {
- if (!declsshadowable(decl0, decl) && !declscompatible(decl0, decl))
- return 0;
+ struct decl *d0;
+ if ((d0 = envfind(&env_noparent, decl->name))) {
+ for (int kind = TYstruct; kind <= TYunion; ++kind) {
+ if (d0->t == Dtype && d0->ty->t == kind
+ && decl->t == Dtype && decl->ty->t == kind && d0->ty->agg.fwd) {
+ // modify existing forward declaration
+ *(size_t *)&d0->ty->size = decl->ty->size;
+ *(size_t *)&d0->ty->align = decl->ty->align;
+ *(bool *)&d0->ty->agg.fwd = 0;
+ memcpy((void *)&d0->ty->agg.flds, &decl->ty->agg.flds,
+ sizeof d0->ty->agg.flds);
+ memcpy((void *)&d0->ty->agg.decls, &decl->ty->agg.decls,
+ sizeof d0->ty->agg.decls);
+ d0->span = decl->span;
+ return d0;
+ }
+ }
+ if (!declsshadowable(d0, decl) && !declscompatible(d0, decl)) {
+ return NULL;
+ }
}
decls = xcalloc(1, sizeof *decls);
decls->next = env->decls;
decls->decl = *decl;
env->decls = decls;
- return 1;
+ return &decls->decl;
}
diff --git a/bootstrap/main.c b/bootstrap/main.c
index 95759af..9432dcb 100644
--- a/bootstrap/main.c
+++ b/bootstrap/main.c
@@ -11,4 +11,5 @@ main(int argc, char **argv) {
parse(&cf, &P);
// dumptransunit(&tu);
cgen(stdout, &cf);
+ // prialltypes();
}
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 381cfcc..025e061 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -413,6 +413,7 @@ lex(struct parser *P) {
case '-':
if (chrmatch(P, '=')) tok.t = '-=';
else if (chrmatch(P, '-')) tok.t = '--';
+ else if (chrmatch(P, '>')) tok.t = '->';
else tok.t = '-';
return tok;
case '&':
@@ -511,13 +512,15 @@ popenv(struct parser *P) {
assert(P->curenv);
}
-static void
+static struct decl *
putdecl(struct parser *P, struct span espan, const struct decl *decl) {
+ struct decl *ret;
if (envfind(P->primenv, decl->name))
fatal(P, espan, "cannot shadow primitive `%s'", decl->name);
- if (!envput(P->curenv, decl))
+ if (!(ret = envput(P->curenv, decl)))
fatal(P, decl->span,
"cannot shadow earlier incompatible declaration of `%s'", decl->name);
+ return ret;
}
static const struct decl *
@@ -652,6 +655,8 @@ islvalue(const struct expr *ex) {
return 1;
if (ex->t == Eprefix && ex->unop.op == '*')
return 1;
+ if (ex->t == Eindex || ex->t == Eget)
+ return 1;
return 0;
}
@@ -683,14 +688,22 @@ structidx2fld(const struct type *ty, int idx) {
static int
structfldnam2idx(const struct type *ty, const char *name) {
- int i;
assert(name);
- for (i = 0; i < ty->agg.flds.n; ++i)
+ for (int i = 0; i < ty->agg.flds.n; ++i)
if (!strcmp(name, ty->agg.flds.d[i].name))
return i;
return -1;
}
+static struct decl *
+findaggdecl(const struct type *ty, const char *name) {
+ assert(name);
+ for (int i = 0; i < ty->agg.decls.n; ++i)
+ if (!strcmp(name, ty->agg.decls.d[i].name))
+ return &ty->agg.decls.d[i];
+ return NULL;
+}
+
static struct expr
parsestructini(struct parser *P, const struct type *ty) {
struct expr ex = {Eini};
@@ -788,6 +801,8 @@ parsearrini(struct parser *P, const struct type *ty) {
static const struct type *
fntype(const struct fn *fn) {
struct type ty = { TYfn, 0, g_targ.sizesize };
+ if (fn->selfty)
+ return fn->selfty;
vec_t(const struct type *) params = {0};
ty.fn.retty = fn->retty;
for (int i = 0; i < fn->params.n; ++i)
@@ -946,6 +961,7 @@ static struct expr
pexpostfix(struct parser *P) {
struct expr ex = pexprimary(P);
struct tok tok;
+ struct fn *met = NULL;
if (P->used_targty) return ex;
@@ -954,6 +970,12 @@ pexpostfix(struct parser *P) {
const struct type *ty = ex.ty;
int i = 0;
+ if (met) {
+ ++i;
+ ty = met->selfty = fntype(met);
+ vec_push(&args, ex);
+ }
+
if (ty->t == TYptr)
ty = ty->child;
@@ -979,11 +1001,17 @@ pexpostfix(struct parser *P) {
break;
}
}
- ex.call.callee = exprdup(ex);
- ex.t = Ecall;
- ex.span = tok.span;
- ex.ty = ty->fn.retty;
- vec_slice_cpy(&ex.call.args, &args);
+ if (met) {
+ ex.t = Emcall;
+ ex.mcall.met = met;
+ vec_slice_cpy(&ex.mcall.args, &args);
+ } else {
+ ex.call.callee = exprdup(ex);
+ ex.t = Ecall;
+ ex.span = tok.span;
+ ex.ty = ty->fn.retty;
+ vec_slice_cpy(&ex.call.args, &args);
+ }
} else if (lexmatch(P, &tok, '[')) {
struct expr lhs = ex,
rhs = parseexpr(P);
@@ -1023,7 +1051,7 @@ pexpostfix(struct parser *P) {
int idx = structfldnam2idx(ty, fnam);
struct aggfield *fld = &ty->agg.flds.d[idx];
if (idx < 0)
- fatal(P, tok.span, "%t has no such field `%s'", ex.ty, fnam);
+ fatal(P, tok.span, "%t has no such field `%s'", ty, fnam);
ex.get.lhs = exprdup(ex);
ex.t = Eget;
@@ -1034,6 +1062,62 @@ pexpostfix(struct parser *P) {
fatal(P, tok.span, "cannot access `%s': left-hand-side is not an aggregate (%t)",
fnam, ex.ty);
}
+ } else if (lexmatch(P, &tok, '->')) {
+ const char *fnam = (tok = lexexpect(P, TKident)).str;
+ const struct type *ty = ex.ty;
+ bool exptr = 0, metptr = 0;
+
+ if ((exptr = ty->t == TYptr))
+ ty = ty->child;
+ if (ty->t == TYstruct || ty->t == TYunion) {
+ struct decl *decl = findaggdecl(ty, fnam);
+ if (!decl)
+ fatal(P, tok.span, "%t has no such method `%s'", ty, fnam);
+ if (decl->t != Dfn)
+ fatal(P, tok.span, "%t:%bs is not a function", ty, fnam);
+ met = &decl->fn;
+ if (met->params.n == 0)
+ fatal(P, tok.span,
+ "cannot call `->%s', it takes zero arguments",
+ fnam);
+
+ const struct type *recv0 = met->params.d[0].ty,
+ *recv = recv0;
+ if ((metptr = recv->t == TYptr))
+ recv = recv->child;
+ if (unconstify(ty) != unconstify(recv))
+ fatal(P, tok.span,
+ "method receiver type mismatch for `->%s' (%t vs %t)",
+ fnam, ty, recv);
+ if (!exptr && !metptr) {
+ ;
+ } else if (exptr && !metptr) {
+ ex = (struct expr) {
+ Eprefix, ex.span, ty, .unop = { '*', exprdup(ex) }
+ };
+ } else if (!exptr && metptr) {
+ struct type pty = {TYptr, g_targ.ptrsize, 0, 0, .child = ty};
+ if (!islvalue(&ex))
+ fatal(P, tok.span, "cannot call `->%s' by reference: left-hand-side is not"
+ "an lvalue", fnam);
+ else if (ty->konst && !recv->konst)
+ fatal(P, tok.span, "constness mismatch: method takes %t but subject is %t",
+ recv0, ex.ty);
+ ex = (struct expr) {
+ Eprefix, ex.span, interntype(pty), .unop = { '&', exprdup(ex) }
+ };
+ } else if (exptr && metptr) {
+ if (ty->konst && !recv->konst)
+ fatal(P, tok.span, "constness mismatch: method takes %t but subject is %t",
+ recv0, ex.ty);
+ }
+
+ if (lexpeek(P).t != '(')
+ lexexpect(P, '(');
+ } else {
+ fatal(P, tok.span, "cannot call `->%s': left-hand-side is not an aggregate (%t)",
+ fnam, ex.ty);
+ }
} else {
break;
}
@@ -2076,7 +2160,6 @@ parseenum(struct parser *P, const char *name) {
if (min >= INT32_MIN && max <= INT32_MAX) ty.enu.intty = ty_int;
if (min >= INT64_MIN && max <= INT64_MAX) ty.enu.intty = ty_int;
}
- assert(ty.enu.intty);
}
ty.size = ty.enu.intty->size;
@@ -2088,18 +2171,24 @@ parseenum(struct parser *P, const char *name) {
}
static const struct type *
-parseagg(struct parser *P, const char *name, int kind) {
+parseagg(struct parser *P, const char *name, int kind, bool *put) {
struct tok tok;
struct type ty = {kind};
+ const struct type *pty = NULL;
static int id = 0;
size_t size = 0, align = 1;
vec_t(struct aggfield) flds = {0};
+ *put = 1;
+
if (lexmatch(P, &tok, ';')) {
ty.agg.fwd = 1;
} else {
lexexpect(P, '{');
while (!lexmatch(P, &tok, '}')) {
+ if (isdecltokt(lexpeek(P).t))
+ goto decls;
+
const char *fnam = (tok = lexexpect(P, TKident)).str;
const struct type *ty = parsetype(P);
size_t off = kind == TYunion ? 0 : ALIGNUP(size, ty->align);
@@ -2129,6 +2218,41 @@ parseagg(struct parser *P, const char *name, int kind) {
}
}
}
+ if (0)
+decls: {
+ vec_t(struct decl) decls = {0};
+ struct env env = {.parent = P->curenv};
+ struct decl *decl;
+
+ ty.size = ALIGNUP(size, align);
+ ty.align = align;
+ ty.agg.name = name;
+ vec_slice_cpy(&ty.agg.flds, &flds);
+ ty.agg.id = id++;
+ pty = interntype(ty);
+ if (name)
+ decl = putdecl(P, tok.span,
+ &(struct decl){Dtype, name, .span = tok.span, .ty = pty});
+ if (decl->ty != pty)
+ uninterntype(pty);
+ pty = decl->ty;
+
+ pushenv(P, &env);
+ while (!lexmatch(P, &tok, '}'))
+ parsedecl(NULL, NULL, P, 0);
+ for (struct decls *ds = env.decls, *next; ds; ds = next) {
+ if (ds->decl.t == Dtype && ds->decl.ty == pty)
+ ;
+ else
+ vec_push(&decls, ds->decl);
+ next = ds->next;
+ free(ds);
+ }
+ vec_slice_cpy(&((struct type *)decl->ty)->agg.decls, &decls);
+ popenv(P);
+ *put = 0;
+ return decl->ty;
+ }
ty.size = ALIGNUP(size, align);
ty.align = align;
@@ -2184,7 +2308,8 @@ staticvaryield(struct decl *decl, void *arg) {
if (a->P->is_header && a->externp && decl->var.ini)
fatal(a->P, decl->span,
"cannot define extern variable in header");
- a->yield(decl, a->yarg);
+ if (a->yield)
+ a->yield(decl, a->yarg);
}
static void
@@ -2234,25 +2359,13 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) {
decl.name = lexexpects(P, TKident, "enum name").str;
decl.ty = parseenum(P, decl.name);
} else if (lexmatch(P, &tok, TKkw_struct)) {
- struct decl *d2;
+ bool put;
kind = TYstruct;
if (externp) fatal(P, tok.span, "struct cannot be `extern'");
agg:
decl.name = lexexpects(P, TKident, "struct name").str;
- decl.ty = parseagg(P, decl.name, kind);
- d2 = (struct decl *)finddecl(P, decl.name);
- if (d2 && d2->t == Dtype && d2->ty->t == kind && d2->ty->agg.fwd) {
- // modify existing forward declaration
- *(size_t *)&d2->ty->size = decl.ty->size;
- *(size_t *)&d2->ty->align = decl.ty->align;
- *(bool *)&d2->ty->agg.fwd = 0;
- memcpy((void *)&d2->ty->agg.flds, &decl.ty->agg.flds,
- sizeof d2->ty->agg.flds);
- uninterntype(decl.ty);
- d2->span = tok.span;
- envput(P->curenv, d2);
- return;
- }
+ decl.ty = parseagg(P, decl.name, kind, &put);
+ if (!put) goto noput;
} else if (lexmatch(P, &tok, TKkw_union)) {
if (externp) fatal(P, tok.span, "union cannot be `extern'");
kind = TYunion;
@@ -2265,7 +2378,8 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) {
cf = doimport(P, path);
for (int i = 0; i < cf.decls.n; ++i) {
putdecl(P, tok.span, &cf.decls.d[i]);
- yield(&cf.decls.d[i], yarg);
+ if (yield)
+ yield(&cf.decls.d[i], yarg);
}
free(cf.decls.d);
lexexpect(P, ';');
@@ -2276,8 +2390,10 @@ parsedecl(decl_yielder_t yield, void *yarg, struct parser *P, bool toplevel) {
}
decl.span = tok.span;
- putdecl(P, tok.span, &decl);
- yield(&decl, yarg);
+ decl = *putdecl(P, tok.span, &decl);
+noput:
+ if (yield)
+ yield(&decl, yarg);
}
static void
diff --git a/bootstrap/test.cff b/bootstrap/test.cff
index 011d386..7a6b7ce 100644
--- a/bootstrap/test.cff
+++ b/bootstrap/test.cff
@@ -1,12 +1,5 @@
import "libc.hff";
import "libc.hff";
-
-struct Vec2f;
-struct Vec2f {
- x f32,
- y f32,
-}
-
union Val {
x i64,
lo i32,
@@ -17,6 +10,13 @@ enum Color {
Red, Green, Blue
}
+defmacro each(i, x, arr, ...body) [
+ for let i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i {
+ let x = arr[i];
+ { body }
+ }
+]
+
static xs *void = {},
ok = 6;
@@ -33,18 +33,36 @@ fn isort(xs *int, n usize) void {
x();
}
+struct Vec2f;
+struct Vec2f {
+ x f32,
+ y f32,
+
+ fn mag(v Vec2f) f32 {
+ extern fn sqrtf(_ f32) f32;
+ return sqrtf((v.x * v.x) + (v.y * v.y));
+ }
+ fn zero(v *Vec2f) void {
+ v.x = 0;
+ v.y = 0;
+ }
+}
+
extern fn main (argc int, argv **u8) int {
let colors [3]Color = { :Red, :Green, :Blue } ;
let x = Vec2f { .y: 1, .x: 2.4 };
- let p = &x;
+ let p *const Vec2f = &x;
printf("v = { %g, %g }\n", x.x, p.y);
+ printf("mag = %g\n", x->mag());
+ x->zero();
+ printf("mag = %g\n", (&x)->mag());
let is [10]int = { [4] = 1, 2, [1 - 1] = 3 };
isort(is, 10);
- for let i = 0; i < 10; ++i {
- printf("%d\n", is[i]);
- }
+ each(i, x, is,
+ printf("%d\n", x);
+ )
printf("sizeof(is) = %zu\n", sizeof(is));
printf("sizeof *void = %zu\n", sizeof *void);
diff --git a/bootstrap/types.c b/bootstrap/types.c
index 7b223f6..f826f9d 100644
--- a/bootstrap/types.c
+++ b/bootstrap/types.c
@@ -28,36 +28,42 @@ inittypes() {
static u32
hashtype(const struct type *ty) {
- u32 h = 0;
- h = jkhashv(h, ty->t);
- h = jkhashv(h, ty->size);
- h = jkhashv(h, ty->align);
- h = jkhashv(h, ty->konst);
+ u32 h = FNV1A_INI;
+
+ h = fnv1ai(h, ty->t);
+ h = fnv1ai(h, ty->konst);
+ if (ty->t == TYfn)
+ epri("");
+
switch (ty->t) {
- case TYvoid: case TYbool: case TYfloat:
+ case TYvoid: case TYbool:
break;
- case TYint:
- h = jkhashv(h, ty->int_signed);
+ case TYint: case TYfloat:
+ h = fnv1az(h, ty->size);
+ h = fnv1az(h, ty->align);
+ h = fnv1ai(h, ty->int_signed);
break;
case TYptr:
case TYslice:
- h = jkhashv(h, ty->child->_id);
+ assert(ty->child->size || ty->align == 1);
+ h = fnv1ai(h, ty->child->_id);
break;
case TYarr:
- h = jkhashv(h, ty->child->_id);
- h = jkhashv(h, ty->length);
+ assert(ty->child->size || ty->align == 1);
+ h = fnv1ai(h, ty->child->_id);
+ h = fnv1aI(h, ty->length);
break;
case TYfn:
- h = jkhashv(h, ty->fn.retty->_id);
- h = jkhashv(h, ty->fn.params.n);
+ h = fnv1ai(h, ty->fn.retty->_id);
+ h = fnv1ai(h, ty->fn.params.n);
for (int i = 0; i < ty->fn.params.n; ++i)
- h = jkhashv(h, ty->fn.params.d[i]->_id);
+ h = fnv1ai(h, ty->fn.params.d[i]->_id);
break;
case TYenum:
- h = jkhashv(h, ty->enu.id);
+ h = fnv1ai(h, ty->enu.id);
break;
case TYstruct: case TYunion: case TYeunion:
- h = jkhashv(h, ty->agg.id);
+ h = fnv1ai(h, ty->agg.id);
break;
}
return h;
@@ -67,15 +73,15 @@ bool
typeeql(const struct type *lhs, const struct type *rhs) {
if (lhs == rhs)
return 1;
- if (lhs->t != rhs->t || lhs->size != rhs->size
- || lhs->align != rhs->align
- || lhs->konst != rhs->konst)
+ if (lhs->t != rhs->t || lhs->konst != rhs->konst)
return 0;
switch (lhs->t) {
- case TYvoid: case TYbool: case TYfloat:
+ case TYvoid: case TYbool:
return 1;
+ case TYfloat:
+ return lhs->size == rhs->size;
case TYint:
- return lhs->int_signed == rhs->int_signed;
+ return lhs->size == rhs->size && lhs->int_signed == rhs->int_signed;
case TYptr:
case TYslice:
return typeeql(lhs->child, rhs->child);
@@ -139,6 +145,7 @@ typesput(const struct type *key) {
nodes->next = types.buckets[idx];
types.buckets[idx] = nodes;
}
+ idx = hash & (types.nbuckets - 1);
}
n->next = types.buckets[idx];
@@ -151,11 +158,14 @@ interntype(struct type ty) {
static int id;
if (!ty.align)
ty.align = ty.size;
+ if ((ty.t == TYptr || ty.t == TYarr) && !ty.child->size)
+ ty.align = 1;
const struct type *ty2 = typesfind(&ty);
if (ty2)
return ty2;
ty._id = id++;
ty2 = typesput(&ty);
+ // epri("new %t, h = %d. %d\n", ty2, hashtype(ty2), ty2->agg.id);
assert(ty2);
return ty2;
}
@@ -164,13 +174,15 @@ void
uninterntype(const struct type *key) {
u32 hash = hashtype(key);
size_t idx = hash & (types.nbuckets - 1);
- for (struct typesnode *n = types.buckets[idx], *prev = NULL; n; n = n->next) {
+ types.size--;
+ for (struct typesnode *n = types.buckets[idx], *prev = NULL; n; n = n->next) {
if (key == &n->ty) {
if (prev) {
prev->next = n->next;
} else {
types.buckets[idx] = n->next;
}
+ free(n);
break;
}
prev = n;
@@ -384,3 +396,14 @@ typeof2(const struct type *a, const struct type *b) {
}
return NULL;
}
+
+
+void
+prialltypes(void) {
+ for (int i = 0; i < types.nbuckets; ++i) {
+ epri("bkt %d:\n", i);
+ for (struct typesnode *n = types.buckets[i]; n; n = n->next) {
+ epri(" %t : %d\n", &n->ty, hashtype(&n->ty));
+ }
+ }
+}
diff --git a/bootstrap/util.c b/bootstrap/util.c
index c9be845..bd6f951 100644
--- a/bootstrap/util.c
+++ b/bootstrap/util.c
@@ -1,18 +1,15 @@
#include "all.h"
-// Bob Jenkins's one_at_a_time hash
u32
-jkhash(u32 h, const u8 *data, size_t length) {
+fnv1a(u32 h, const void *p, size_t length) {
+ const u8 *data = p;
size_t i = 0;
+ u64 H = h;
while (i != length) {
- h += data[i++];
- h += h << 10;
- h ^= h >> 6;
+ H ^= data[i++];
+ H *= 0x100000001b3;
}
- h += h << 3;
- h ^= h >> 11;
- h += h << 15;
- return h;
+ return H;
}
static const char *filepaths[100];
@@ -117,7 +114,7 @@ eprifileline(struct span span) {
--j;
n = fprintf(stderr, "%4d| ", span.line);
- for (long k = i; k < j; ++k)
+ for (long k = i; k <= j; ++k)
epri("%c", src[k]);
epri("\n");
while (n--)