aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c51
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(&params, param);
+ }
+ if (!lexmatch(P, &tok, ',')) {
+ lexexpect(P, ')');
+ break;
+ } else if (ty.fn.variadic) {
+ lexexpect(P, ')');
+ break;
+ }
+ }
+ vec_slice_cpy(&ty.fn.params, &params);
+ 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(&params, param);
}
if (!lexmatch(P, &tok, ',')) {
@@ -1754,7 +1800,7 @@ parsefn(struct decl *decl, struct parser *P) {
vec_slice_cpy(&fn->params, &params);
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);