close some gaps in the type system
This commit is contained in:
@@ -379,6 +379,13 @@ parse_type_atom :: proc(parser: ^Parser) -> ast.Type_Syntax {
|
||||
case .Keyword_Bool:
|
||||
advance(parser)
|
||||
return types.BOOL
|
||||
case .Left_Paren:
|
||||
advance(parser)
|
||||
grouped := parse_type(parser)
|
||||
if _, ok := allow(parser, .Right_Paren); !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected ')' after grouped type")
|
||||
}
|
||||
return grouped
|
||||
case .Keyword_Func, .Keyword_C_Func:
|
||||
c_abi := tok.kind == .Keyword_C_Func
|
||||
advance(parser)
|
||||
@@ -447,6 +454,24 @@ parse_type_atom :: proc(parser: ^Parser) -> ast.Type_Syntax {
|
||||
return types.INVALID
|
||||
}
|
||||
|
||||
sum_syntax_requires_resolution :: proc(parser: ^Parser, value: types.Type, depth := 0) -> bool {
|
||||
if depth > 64 {
|
||||
return true
|
||||
}
|
||||
item, ok := types.node(&parser.module.type_store, value)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if item.kind == .Named || item.kind == .Type_Call {
|
||||
return true
|
||||
}
|
||||
if item.kind == .Alias || item.kind == .Sum {
|
||||
return sum_syntax_requires_resolution(parser, item.child, depth+1) ||
|
||||
sum_syntax_requires_resolution(parser, item.extra, depth+1)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
parse_type_pipe_tail :: proc(parser: ^Parser, left: ast.Type_Syntax) -> ast.Type_Syntax {
|
||||
result := left
|
||||
for current(parser).kind == .Pipe {
|
||||
@@ -454,8 +479,12 @@ parse_type_pipe_tail :: proc(parser: ^Parser, left: ast.Type_Syntax) -> ast.Type
|
||||
right := parse_type_atom(parser)
|
||||
composed, compose_error := types.compose_sum(&parser.module.type_store, result, right)
|
||||
if compose_error == .Unsupported {
|
||||
source.add(parser.diagnostics, operator.span, "only native unbacked enums and tagged unions can be composed with '|'")
|
||||
result = types.INVALID
|
||||
if sum_syntax_requires_resolution(parser, result) || sum_syntax_requires_resolution(parser, right) {
|
||||
result = types.sum_syntax(&parser.module.type_store, result, right)
|
||||
} else {
|
||||
source.add(parser.diagnostics, operator.span, "only native unbacked enums and tagged unions can be composed with '|'")
|
||||
result = types.INVALID
|
||||
}
|
||||
} else if compose_error == .Conflict {
|
||||
source.add(parser.diagnostics, operator.span, "sum composition contains the same variant name with different payload types")
|
||||
result = types.INVALID
|
||||
@@ -738,9 +767,15 @@ parse_anonymous_struct_type_expr :: proc(parser: ^Parser) -> ast.Expr_Id {
|
||||
start := advance(parser)
|
||||
fields: [dynamic]types.Field
|
||||
fields.allocator = parser.module.allocator
|
||||
defaults: [dynamic]ast.Expr_Id
|
||||
defaults.allocator = parser.module.allocator
|
||||
tuple := false
|
||||
if !parse_record_body(parser, &fields, "expected '{' after anonymous struct type", tuple_result=&tuple) {
|
||||
if !parse_record_body(
|
||||
parser, &fields, "expected '{' after anonymous struct type",
|
||||
tuple_result=&tuple, defaults=&defaults,
|
||||
) {
|
||||
delete(fields)
|
||||
delete(defaults)
|
||||
return invalid_expr(parser, start.span, "invalid anonymous struct type")
|
||||
}
|
||||
end := previous(parser)
|
||||
@@ -752,6 +787,7 @@ parse_anonymous_struct_type_expr :: proc(parser: ^Parser) -> ast.Expr_Id {
|
||||
kind=.Anonymous_Struct_Type,
|
||||
span=span_from(start.span, end.span),
|
||||
integer=u64(field_start)<<32 | u64(field_count),
|
||||
args=defaults[:],
|
||||
tuple=tuple,
|
||||
left=ast.INVALID_EXPR,
|
||||
right=ast.INVALID_EXPR,
|
||||
|
||||
Reference in New Issue
Block a user