aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-05 07:28:56 +0200
committerlemon <lsof@mailbox.org>2022-08-05 07:28:56 +0200
commit9667272414380e2d50113e0a0c6408a02e7c23eb (patch)
tree9537c57f7b13aa43ce63553ca44d8ba42e6ed1c3
parentfc29f3f2b0c3a7c5ef1c75d910cf0815d2edbba2 (diff)
fn type syntax, bugfixs
-rw-r--r--bootstrap/all.h2
-rw-r--r--bootstrap/cgen.c14
-rw-r--r--bootstrap/parse.c51
-rw-r--r--bootstrap/test.cff11
-rw-r--r--bootstrap/types.c5
-rw-r--r--bootstrap/util.c1
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(&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);
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;
}