diff options
Diffstat (limited to 'bootstrap/parse.c')
| -rw-r--r-- | bootstrap/parse.c | 51 |
1 files changed, 49 insertions, 2 deletions
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); |