diff options
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/all.h | 2 | ||||
| -rw-r--r-- | bootstrap/cgen.c | 14 | ||||
| -rw-r--r-- | bootstrap/parse.c | 51 | ||||
| -rw-r--r-- | bootstrap/test.cff | 11 | ||||
| -rw-r--r-- | bootstrap/types.c | 5 | ||||
| -rw-r--r-- | bootstrap/util.c | 1 |
6 files changed, 77 insertions, 7 deletions
diff --git a/bootstrap/all.h b/bootstrap/all.h index b01bce7..fa24479 100644 --- a/bootstrap/all.h +++ b/bootstrap/all.h @@ -227,7 +227,7 @@ struct decl { struct var { const struct type *ty; struct expr *ini; - int fnid; + int id, fnid; } var; struct macro macro; }; diff --git a/bootstrap/cgen.c b/bootstrap/cgen.c index faf7b6f..2f92375 100644 --- a/bootstrap/cgen.c +++ b/bootstrap/cgen.c @@ -180,6 +180,8 @@ genexpr(struct expr *ex) { case Ename: if ((ex->ref->t == Dfn || ex->ref->t == Dstatic) && *ex->ref->_cname) pri("%s", *ex->ref->_cname); + else if (ex->ref->t == Dlet && ex->ref->var.id >= 0) + pri("%s_%d", ex->ref->name, ex->ref->var.id); else pri("%s", ex->ref->name); break; @@ -255,7 +257,7 @@ genstmt(struct stmt *stmt) { ; struct decl decl = stmt->decl; switch (decl.t) { case Dlet: - pri("%t %s", decl.var.ty, decl.name); + pri("%t %s_%d", decl.var.ty, decl.name, decl.var.id); if (decl.var.ini) { pri(" = "); if ((decl.var.ty->t == TYstruct || decl.var.ty->t == TYarr) @@ -521,9 +523,14 @@ defctype(const struct type *ty, void *_) { switch (ty->t) { case TYvoid: case TYbool: case TYint: case TYfloat: - case TYptr: case TYenum: + break; + case TYenum: + defctype(ty->enu.intty, NULL); return; - case TYarr: + case TYptr: + defctype(ty->child, NULL); + break; + case TYarr: assert(ty->length >= 0); defctype(ty->child, NULL); *cname = xasprintf("__ty%d", id++); @@ -562,6 +569,7 @@ defctype(const struct type *ty, void *_) { pri("%s %s {\n", kind, *cname); for (int i = 0; i < ty->agg.flds.n; ++i) { struct aggfield fld = ty->agg.flds.d[i]; + defctype(ty->agg.flds.d[i].ty, NULL); pri("%t %s;\n", fld.ty, fld.name); } pri("};\n"); diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 822212e..9cdb7de 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -528,6 +528,45 @@ finddecl(struct parser *P, const char *name) { static struct expr parseexpr(struct parser *P); +static const struct type *parsetype(struct parser *P); + +static const struct type * +parsefntype(struct parser *P) { + struct type ty = {TYfn, 0, g_targ.sizesize}; + vec_t(const struct type *) params = {0}; + struct tok tok; + + lexexpect(P, '('); + while (!lexmatch(P, &tok, ')')) { + if (lexmatch(P, &tok, '...')) { + ty.fn.variadic = 1; + } else { + const struct type *param; + lexexpects(P, TKident, "parameter name"); + param = parsetype(P); + if (!completetype(param)) + fatal(P, tok.span, "parameter type is incomplete (%t)", + param); + vec_push(¶ms, param); + } + if (!lexmatch(P, &tok, ',')) { + lexexpect(P, ')'); + break; + } else if (ty.fn.variadic) { + lexexpect(P, ')'); + break; + } + } + vec_slice_cpy(&ty.fn.params, ¶ms); + ty.fn.retty = unconstify(parsetype(P)); + if (ty.fn.retty != ty_void && !completetype(ty.fn.retty)) { + fatal(P, tok.span, "return type is incomplete (%t)", + ty.fn.retty); + } + + return interntype(ty); +} + static const struct type * parsetype(struct parser *P) { struct tok tok; @@ -580,6 +619,8 @@ parsetype(struct parser *P) { if (decl->t != Dtype) fatal(P, P->tokspan, "%T is not a type", tok); return decl->ty; + } else if (lexmatch(P, &tok, TKkw_fn)) { + return parsefntype(P); } fatal(P, P->tokspan, "expected type (near %T)", tok); } @@ -1316,6 +1357,7 @@ parsevardecl(struct parser *P, struct decl *decl) { const struct type *ty = NULL; struct expr *ini = NULL; bool konst = 0; + static int id; if (lexmatch(P, NULL, TKkw_const)) konst = 1; @@ -1355,6 +1397,7 @@ parsevardecl(struct parser *P, struct decl *decl) { decl->name = name; decl->var.ty = ty; decl->var.ini = ini; + decl->var.id = id++; decl->var.fnid = P->curfn ? P->curfn->id : -1; } @@ -1736,11 +1779,14 @@ parsefn(struct decl *decl, struct parser *P) { lexexpect(P, '('); while (!lexmatch(P, &tok, ')')) { struct fnparam param; - if (lexmatch(P, NULL, '...')) { + if (lexmatch(P, &tok, '...')) { fn->variadic = 1; } else { param.name = lexexpects(P, TKident, "parameter name").str; param.ty = parsetype(P); + if (!completetype(param.ty)) + fatal(P, tok.span, "parameter type is incomplete (%t)", + param.ty); vec_push(¶ms, param); } if (!lexmatch(P, &tok, ',')) { @@ -1754,7 +1800,7 @@ parsefn(struct decl *decl, struct parser *P) { vec_slice_cpy(&fn->params, ¶ms); fn->retty = unconstify(parsetype(P)); if (fn->retty != ty_void && !completetype(fn->retty)) { - fatal(P, tok.span, "return type is incomplette (%t)", + fatal(P, tok.span, "return type is incomplete (%t)", fn->retty); } fn->selfty = fntype(fn); @@ -1775,6 +1821,7 @@ parsefn(struct decl *decl, struct parser *P) { Dlet, params.data[i].name, .var = { .ty = params.data[i].ty, .fnid = fn->id, + .id = -1, } }; putdecl(P, tok.span, &decl); diff --git a/bootstrap/test.cff b/bootstrap/test.cff index 966176f..f74619a 100644 --- a/bootstrap/test.cff +++ b/bootstrap/test.cff @@ -17,6 +17,16 @@ enum Color { static xs *void = {}; +fn isort(xs *int, n usize) void { + extern fn qsort(base *void, nmemb usize, size usize, compar *fn(l *const void, r *const void, _ *void) int) void; + fn icmp(lhs *const void, rhs *const void, _ *void) int { + let lhs = *as(*int)lhs; + let rhs = *as(*int)rhs; + return lhs - rhs; + } + qsort(xs, n, 4, &icmp); +} + extern fn main (argc int, argv **u8) int { extern fn printf(fmt *const u8, ...) int; @@ -25,6 +35,7 @@ extern fn main (argc int, argv **u8) int { printf("v = { %g, %g }\n", x.x, x.y); 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]); } diff --git a/bootstrap/types.c b/bootstrap/types.c index 7491b4b..386ad58 100644 --- a/bootstrap/types.c +++ b/bootstrap/types.c @@ -52,6 +52,7 @@ hashtype(const struct type *ty) { h = jkhashv(h, ty->fn.params.n); for (int i = 0; i < ty->fn.params.n; ++i) h = jkhashv(h, ty->fn.params.d[i]->_id); + break; case TYenum: h = jkhashv(h, ty->enu.id); break; @@ -81,7 +82,9 @@ typeeql(const struct type *lhs, const struct type *rhs) { case TYarr: return lhs->length == rhs->length && typeeql(lhs->child, rhs->child); case TYfn: - if (lhs->length != rhs->length) + if (lhs->fn.params.n != rhs->fn.params.n) + return 0; + if (lhs->fn.variadic != rhs->fn.variadic) return 0; for (int i = 0; i < lhs->fn.params.n; ++i) if (!typeeql(lhs->fn.params.d[i], rhs->fn.params.d[i])) diff --git a/bootstrap/util.c b/bootstrap/util.c index bb38b90..be3aea0 100644 --- a/bootstrap/util.c +++ b/bootstrap/util.c @@ -72,6 +72,7 @@ xasprintf(const char *fmt, ...) { va_end(aq); } va_end(ap); + assert(str); return str; } |