From a9e8fe82c8c2e6bf15df0cae861d163f668e9a5a Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 19 Aug 2022 16:45:10 +0200 Subject: change enum backing type --- src/cffc.hff | 4 ++-- src/parse.cff | 32 ++++++++++++++++++++++++++++---- src/type.cff | 3 +++ 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cffc.hff b/src/cffc.hff index 9fd9080..4563583 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -172,7 +172,7 @@ struct Expr { Slice struct { lhs *Expr, begin *Expr, end *Expr }, Call struct { lhs *Expr, args [#]Expr }, ZeroIni, - EnumIni struct { name *const u8, val i64 }, + EnumIni i64, EUnionIni struct { var *const AggField, ex *Expr }, AggIni struct { flds [#]*const AggField, exs [#]Expr }, ArrIni struct { idxs [#]u32, exs [#]Expr, maxn i64 }, @@ -412,7 +412,7 @@ fn childtype(ty *const Type) *const Type { } extern fn completetype(ty *const Type) bool; fn isnumtype(ty *const Type) bool { - return ty->is(:Int) or ty->is(:Flo); + return ty->is(:Int) or ty->is(:Flo) or (ty->is(:Enum) and ty.u.Enum.lax); } extern fn typeof2(a *const Type, b *const Type) *const Type; diff --git a/src/parse.cff b/src/parse.cff index 3453485..89a059f 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -634,6 +634,14 @@ typedef DeclYielder *fn(*Decl, *void) void; fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) void; fn parseenum(P *Parser, name *const u8, lax bool) *const Type { + let intty *const Type = #null; + let tok Tok #?; + if lexmatch(P, &tok, ':') { + intty = parsetype(P); + if !intty->is(:Int) { + fatal(P, tok.loc, "enum backing type must be integral (%t)", intty); + } + } lexexpect(P, '{'); let iota = 0i64; let max = iota; @@ -656,10 +664,10 @@ fn parseenum(P *Parser, name *const u8, lax bool) *const Type { break; } } - let intty *const Type = + let intty *const Type = intty ?? ( max < 1u64 << ((g_targ.intsize * 8) - 1) ? ty_int : max < 1u64 << 31 ? ty_i32 - : ty_i64; + : ty_i64); static id int = 0; return interntype({ .u: :Enum { intty, name, lax, id++, vals->move(P.alloc) }}); } @@ -1033,6 +1041,22 @@ fn parsetype(P *Parser) *const Type { case lexmatch(P, &tok, :kw_fn); return parsefntype(P); + case lexmatch(P, &tok, :kw_struct); + let decl *Decl; + return parseagg(P, tok.loc, :Struct, #null, &decl); + + case lexmatch(P, &tok, :kw_union); + let decl *Decl; + return parseagg(P, tok.loc, :Union, #null, &decl); + + case lexmatch(P, &tok, :kw_enum); + let decl *Decl; + if lexmatch(P, #null, :kw_union) { + return parseagg(P, tok.loc, :EUnion, #null, &decl); + } else { + return parseenum(P, #null, #{lax?} #f); + } + case else; fatal(P, tok.loc, "expected type (near %qT)", tok); } @@ -1388,7 +1412,7 @@ fn pexprimary(P *Parser) Expr { } fatal(P, tok.loc, "%t has no such variant %qT", ty, tok); } while #f; - ex = { tok.loc, ty, :EnumIni { name, i }}; + ex = { tok.loc, ty, :EnumIni(i) }; } else if ty->is(:Agg) and ty.u.Agg.kind == :EUnion { let name = (tok = lexexpects(P, :ident, "variant name")).u.ident; let fld = findaggfield(ty, name); @@ -2610,7 +2634,7 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool) } } else { let name = lexexpect(P, :ident).u.ident; - let ty = parseenum(P, name, #{lax} #f); + let ty = parseenum(P, name, (attr & ATTR_LAX) != 0); decl = putdecl(P, loc, { name, loc, .u: :Ty(ty) }); } diff --git a/src/type.cff b/src/type.cff index b0cb259..a07ea0d 100644 --- a/src/type.cff +++ b/src/type.cff @@ -208,6 +208,9 @@ extern fn mkslicetype(child *const Type) *const Type { fn numtype2rank(ty *const Type) int { ty = unconstify(ty); switch { + case ty->is(:Enum); + assert(ty.u.Enum.lax, "lax"); + return numtype2rank(ty.u.Enum.intty); case ty->is(:Int) and (ty == ty_int or ty.size < ty_int.size); return 0; case ty == ty_uint; return 1; -- cgit v1.2.3