diff options
Diffstat (limited to 'bootstrap/parse.c')
| -rw-r--r-- | bootstrap/parse.c | 152 |
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"); |