aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-19 16:45:10 +0200
committerlemon <lsof@mailbox.org>2022-08-19 16:45:10 +0200
commita9e8fe82c8c2e6bf15df0cae861d163f668e9a5a (patch)
treef2207bcf53d4fa107912895bc550262cda7f8596 /src/parse.cff
parent80f5dca7aa8c9a7f3bf467f9ae2bdc1eae0e9a2b (diff)
change enum backing type
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff32
1 files changed, 28 insertions, 4 deletions
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) });
}