aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/parse.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-04 10:07:13 +0200
committerlemon <lsof@mailbox.org>2022-08-04 10:07:13 +0200
commitc5d837d2cd9a57e453da9eaab0e41e0c185e084e (patch)
tree60539ae58df6738772f1e63e2aa58dd8002803e4 /bootstrap/parse.c
parentbb1d4b4a3e51a06fb0530dfc271a97a6cd88cc73 (diff)
fold & more
Diffstat (limited to 'bootstrap/parse.c')
-rw-r--r--bootstrap/parse.c152
1 files changed, 18 insertions, 134 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 3d609c4..3cb6924 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -502,38 +502,6 @@ finddecl(struct parser *P, const char *name) {
static struct expr parseexpr(struct parser *P);
static const struct type *
-constify(const struct type *ty) {
- struct type ty2 = *ty;
- if (ty->konst)
- return ty;
- if (ty2.t != TYfn)
- ty2.konst = 1;
- return interntype(ty2);
-}
-
-static const struct type *
-unconstify(const struct type *ty) {
- struct type ty2 = *ty;
- if (!ty->konst)
- return ty;
- ty2.konst = 0;
- return interntype(ty2);
-}
-
-static const struct type *
-constifychild(const struct type *ty) {
- struct type ty2 = *ty;
- const struct type *child = constify(ty->child);
- if (child == ty->child)
- return ty;
- ty2.child = child;
- return interntype(ty2);
-}
-
-
-static const struct type * typeof2(const struct type *, const struct type *);
-
-static const struct type *
parsetype(struct parser *P) {
struct tok tok;
if (lexmatch(P, &tok, '*')) {
@@ -545,8 +513,12 @@ parsetype(struct parser *P) {
} else if (lexmatch(P, &tok, '[')) {
i64 length = -1;
if (!lexmatch(P, &tok, ']')) {
- length = lexexpect(P, TKintlit).ilit.i;
- assert(length >= 0);
+ struct expr ex = parseexpr(P);
+ if (!fold(&ex) || ex.t != Eintlit)
+ fatal(P, ex.span,
+ "array length should be a compile-time integral expression");
+ if ((length = ex.i) < 0)
+ fatal(P, ex.span, "negative array length");
lexexpect(P, ']');
}
return interntype((struct type) {
@@ -583,42 +555,16 @@ parsetype(struct parser *P) {
}
static const struct type *
-ilittype(struct parser *P, u64 i) {
- if (i <= INT_MAX)
+ilittype(struct parser *P, u64 n) {
+ if (n <= INT_MAX)
return ty_int;
- if (i <= INT32_MAX)
+ if (n <= INT32_MAX)
return ty_i32;
- if (i <= INT64_MAX)
+ if (n <= INT64_MAX)
return ty_i64;
return ty_u64;
}
-static int
-numtype2rank(const struct type *a) {
- if (a->t == TYint) {
- if (a->size < g_targ.intsize || a == ty_int)
- return 0;
- if (a == ty_uint) return 1;
- if (a == ty_i32) return 2;
- if (a == ty_u32) return 3;
- if (a == ty_i64) return 4;
- if (a == ty_u64) return 5;
- }
- if (a == ty_f32) return 6;
- if (a == ty_f64) return 7;
- return -1;
-}
-
-static const struct type *
-rank2numtype(int r) {
- static const struct type **types[] = {
- &ty_int, &ty_uint, &ty_i32, &ty_u32,
- &ty_i64, &ty_u64, &ty_f32, &ty_f64,
- };
- assert(r >= 0 && r < ARRAY_LENGTH(types));
- return *types[r];
-}
-
static const struct type *
numpromote(const struct type *ty) {
int r = numtype2rank(ty);
@@ -628,73 +574,6 @@ numpromote(const struct type *ty) {
}
static bool
-isnumtype(const struct type *a) {
- return a->t == TYint || a->t == TYfloat;
-}
-
-static const struct type *
-arraydecay(const struct type *ty) {
- struct type ty2 = *ty;
-
- if (ty->t != TYarr)
- return ty;
-
- ty2.t = TYptr;
- return interntype(ty2);
-}
-
-// peer type resolution
-static const struct type *
-typeof2(const struct type *a, const struct type *b) {
- if (isnumtype(a) && isnumtype(b)) {
- int ra = numtype2rank(a), rb = numtype2rank(b);
- return rank2numtype(MAX(ra, rb));
- }
- if (a == b)
- return a;
- if (unconstify(a) == b)
- return a;
- if (a == unconstify(b))
- return b;
- if (a->t == TYarr && b->t == TYarr)
- a = arraydecay(a);
- if (a->t == TYptr && b->t == TYarr)
- b = arraydecay(b);
- if (a->t == TYarr && b->t == TYptr)
- a = arraydecay(a);
- if (a->t == TYptr && b->t == TYptr) {
- bool akonst = a->child->konst,
- bkonst = b->child->konst;
- const struct type *uac = unconstify(a->child),
- *ubc = unconstify(b->child);
- if (uac == ubc)
- return akonst ? a : b;
- if (uac == ty_void) {
- if (bkonst && !akonst)
- return constifychild(a);
- return a;
- }
- if (ubc == ty_void) {
- if (akonst && !bkonst)
- return constifychild(b);
- return b;
- }
- if (uac == ty_u8) {
- if (bkonst && !akonst)
- return constifychild(a);
- return a;
- }
- if (ubc == ty_u8) {
- if (akonst && !bkonst)
- return constifychild(b);
- return b;
- }
-
- }
- return NULL;
-}
-
-static bool
islvalue(const struct expr *ex) {
if (ex->t == Ename)
return 1;
@@ -731,7 +610,7 @@ pexprimary(struct parser *P) {
ex.t = Eintlit;
ex.span = tok.span;
ex.i = tok.ilit.i;
- ex.ty = tok.ilit.ty ? tok.ilit.ty : ilittype(P, ex.i);
+ ex.ty = tok.ilit.ty ? tok.ilit.ty : ilittype(P, ex.u);
} else if (lexmatch(P, &tok, TKflolit)) {
ex.t = Eflolit;
ex.span = tok.span;
@@ -957,9 +836,10 @@ peeksbitarithop(struct parser *P, struct tok* tokp) {
if (tokp)
*tokp = tok;
switch (tok.t) {
- case '+': case '-': case '*': case '/': case '%':
+ case '+': case '-': case '*': case '/':
return 1;
- case '&': case '|': case '^': case '<<': case '>>':
+ case '%': case '&': case '|':
+ case '^': case '<<': case '>>':
return 2;
case '##':
return 3;
@@ -1206,6 +1086,10 @@ parsevardecl(struct parser *P, struct decl *decl) {
fatal(P, tok.span, "variable must be initialized");
}
}
+
+ if (ini && decl->t == Dstatic && !fold(ini))
+ fatal(P, ini->span, "static initializer isn't constant");
+
if (ini && !typeof2(ty, ini->ty))
fatal(P, tok.span, "incompatible initializer type");