upgrade enum discriminants
This commit is contained in:
@@ -2783,6 +2783,8 @@ parse_enum_body :: proc(
|
||||
explicit_backing: bool,
|
||||
backing: ^types.Type,
|
||||
members: ^[dynamic]types.Enum_Member,
|
||||
values: ^[dynamic]ast.Enum_Value,
|
||||
deferred: ^bool,
|
||||
expected_open: string,
|
||||
) -> bool {
|
||||
skip_newlines(parser)
|
||||
@@ -2793,6 +2795,7 @@ parse_enum_body :: proc(
|
||||
next_value: i128
|
||||
previous_value: i128
|
||||
has_previous := false
|
||||
order_known := true
|
||||
skip_newlines(parser)
|
||||
for current(parser).kind != .Right_Brace && current(parser).kind != .Eof {
|
||||
member, member_ok := parse_member_name(parser)
|
||||
@@ -2817,18 +2820,20 @@ parse_enum_body :: proc(
|
||||
source.addf(parser.diagnostics, member.span, "duplicate enum member '%s'", token_text(parser, member))
|
||||
}
|
||||
value := next_value
|
||||
explicit := false
|
||||
value_expr := ast.INVALID_EXPR
|
||||
if _, ok := allow(parser, .Equal); ok {
|
||||
explicit = true
|
||||
if !explicit_backing {
|
||||
source.add(parser.diagnostics, member.span, "explicit enum values require a backing type")
|
||||
}
|
||||
saved := parser.cursor
|
||||
negative := false
|
||||
if _, minus_ok := allow(parser, .Minus); minus_ok {
|
||||
negative = true
|
||||
}
|
||||
literal := current(parser)
|
||||
if literal.kind != .Integer {
|
||||
source.add(parser.diagnostics, literal.span, "expected a decimal integer literal for enum value")
|
||||
} else {
|
||||
if literal.kind == .Integer {
|
||||
advance(parser)
|
||||
magnitude, magnitude_ok := parse_integer_magnitude(token_text(parser, literal))
|
||||
if !magnitude_ok {
|
||||
@@ -2839,13 +2844,19 @@ parse_enum_body :: proc(
|
||||
value = -value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parser.cursor = saved
|
||||
value_expr = parse_expression(parser)
|
||||
deferred^ = true
|
||||
order_known = false
|
||||
}
|
||||
}
|
||||
if has_previous && value <= previous_value {
|
||||
if order_known && has_previous && value <= previous_value {
|
||||
source.add(parser.diagnostics, member.span, "enum values must be strictly increasing")
|
||||
}
|
||||
if !duplicate {
|
||||
append(members, types.Enum_Member{name=u32(member.symbol), value=value})
|
||||
append(values, ast.Enum_Value{expr=value_expr, span=member.span, explicit=explicit})
|
||||
}
|
||||
previous_value = value
|
||||
has_previous = true
|
||||
@@ -2890,7 +2901,11 @@ parse_inline_enum_type :: proc(parser: ^Parser) -> types.Type {
|
||||
members: [dynamic]types.Enum_Member
|
||||
members.allocator = parser.module.allocator
|
||||
defer delete(members)
|
||||
if !parse_enum_body(parser, start.span, false, &backing, &members, "expected '{' after inline enum error type") || !valid {
|
||||
values: [dynamic]ast.Enum_Value
|
||||
values.allocator = parser.module.allocator
|
||||
defer delete(values)
|
||||
deferred := false
|
||||
if !parse_enum_body(parser, start.span, false, &backing, &members, &values, &deferred, "expected '{' after inline enum error type") || !valid {
|
||||
return types.INVALID
|
||||
}
|
||||
return types.enum_anonymous(&parser.module.type_store, members[:], backing)
|
||||
@@ -2910,7 +2925,11 @@ parse_enum :: proc(parser: ^Parser, name: token.Token, file_hidden: bool) {
|
||||
members: [dynamic]types.Enum_Member
|
||||
members.allocator = parser.module.allocator
|
||||
defer delete(members)
|
||||
if !parse_enum_body(parser, start.span, explicit_backing, &backing, &members, "expected '{' after enum declaration") {
|
||||
values: [dynamic]ast.Enum_Value
|
||||
values.allocator = parser.module.allocator
|
||||
defer delete(values)
|
||||
deferred := false
|
||||
if !parse_enum_body(parser, start.span, explicit_backing, &backing, &members, &values, &deferred, "expected '{' after enum declaration") {
|
||||
_ = finish_statement(parser)
|
||||
return
|
||||
}
|
||||
@@ -2918,6 +2937,16 @@ parse_enum :: proc(parser: ^Parser, name: token.Token, file_hidden: bool) {
|
||||
if !types.define_enum(&parser.module.type_store, id, backing, members[:], explicit_backing) {
|
||||
source.addf(parser.diagnostics, name.span, "duplicate type declaration '%s'", token_text(parser, name))
|
||||
}
|
||||
if explicit_backing && deferred {
|
||||
stored := make([]ast.Enum_Value, len(values), parser.module.allocator)
|
||||
copy(stored, values[:])
|
||||
append(&parser.module.enum_declarations, ast.Enum_Declaration{
|
||||
type=id,
|
||||
pkg=parser.pkg,
|
||||
file=parser.file,
|
||||
values=stored,
|
||||
})
|
||||
}
|
||||
_ = finish_statement(parser)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user