diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2025-07-05 11:43:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-05 11:43:12 +0200 |
| commit | 09b1c91170d9e011316fa93dc7e98069dcdc6625 (patch) | |
| tree | 78960751e7082cdde5a39f1527193c4f271c1281 /src | |
| parent | c7c76658be61af1532c0320dc0029e5b39f1c6fd (diff) | |
| parent | 067efb7e8e3901eb9eaf0de8050997d4d4d07498 (diff) | |
Merge pull request #719 from BradLewis/feat/bit-field-improvements
Bit field improvements
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/analysis.odin | 27 | ||||
| -rw-r--r-- | src/server/ast.odin | 34 | ||||
| -rw-r--r-- | src/server/collector.odin | 31 | ||||
| -rw-r--r-- | src/server/documentation.odin | 152 | ||||
| -rw-r--r-- | src/server/hover.odin | 54 | ||||
| -rw-r--r-- | src/server/symbol.odin | 78 |
6 files changed, 304 insertions, 72 deletions
diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 597c2cd..766913d 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -940,7 +940,7 @@ internal_resolve_type_expression :: proc(ast_context: ^AstContext, node: ^ast.Ex case ^Proc_Type: return make_symbol_procedure_from_ast(ast_context, node, v^, ast_context.field_name, {}, true), true case ^Bit_Field_Type: - return make_symbol_bit_field_from_ast(ast_context, v^, ast_context.field_name, true), true + return make_symbol_bit_field_from_ast(ast_context, v, ast_context.field_name, true), true case ^Basic_Directive: return resolve_basic_directive(ast_context, v^) case ^Binary_Expr: @@ -1409,7 +1409,7 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide return_symbol, ok = make_symbol_bitset_from_ast(ast_context, v^, node), true return_symbol.name = node.name case ^Bit_Field_Type: - return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v^, node), true + return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true return_symbol.name = node.name case ^Proc_Lit: if is_procedure_generic(v.type) { @@ -1536,7 +1536,7 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide return_symbol, ok = make_symbol_enum_from_ast(ast_context, v^, node), true return_symbol.name = node.name case ^Bit_Field_Type: - return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v^, node), true + return_symbol, ok = make_symbol_bit_field_from_ast(ast_context, v, node), true return_symbol.name = node.name case ^Proc_Lit: if is_procedure_generic(v.type) { @@ -2836,17 +2836,18 @@ make_symbol_struct_from_ast :: proc( } b := symbol_struct_value_builder_make(symbol, ast_context.allocator) - write_struct_type(ast_context, &b, v^, ident, attributes, -1, inlined) + write_struct_type(ast_context, &b, v, ident, attributes, -1, inlined) symbol = to_symbol(b) return symbol } make_symbol_bit_field_from_ast :: proc( ast_context: ^AstContext, - v: ast.Bit_Field_Type, + v: ^ast.Bit_Field_Type, ident: ast.Ident, inlined := false, ) -> Symbol { + construct_bit_field_field_docs(ast_context.file, v) symbol := Symbol { range = common.get_token_range(v, ast_context.file.src), type = .Struct, @@ -2862,19 +2863,29 @@ make_symbol_bit_field_from_ast :: proc( names := make([dynamic]string, ast_context.allocator) types := make([dynamic]^ast.Expr, ast_context.allocator) ranges := make([dynamic]common.Range, 0, ast_context.allocator) + docs := make([dynamic]^ast.Comment_Group, 0, ast_context.allocator) + comments := make([dynamic]^ast.Comment_Group, 0, ast_context.allocator) + bit_sizes := make([dynamic]^ast.Expr, 0, ast_context.allocator) for field in v.fields { if identifier, ok := field.name.derived.(^ast.Ident); ok && field.type != nil { append(&names, identifier.name) append(&types, field.type) append(&ranges, common.get_token_range(identifier, ast_context.file.src)) + append(&docs, field.docs) + append(&comments, field.comments) + append(&bit_sizes, field.bit_size) } } symbol.value = SymbolBitFieldValue { - names = names[:], - types = types[:], - ranges = ranges[:], + backing_type = v.backing_type, + names = names[:], + types = types[:], + ranges = ranges[:], + docs = docs[:], + comments = comments[:], + bit_sizes = bit_sizes[:], } return symbol diff --git a/src/server/ast.odin b/src/server/ast.odin index 9abc1e5..81ec5c7 100644 --- a/src/server/ast.odin +++ b/src/server/ast.odin @@ -1236,6 +1236,40 @@ construct_struct_field_docs :: proc(file: ast.File, v: ^ast.Struct_Type) { } } +construct_bit_field_field_docs :: proc(file: ast.File, v: ^ast.Bit_Field_Type) { + for field, i in v.fields { + // There is currently a bug in the odin parser where it adds line comments for a field to the + // docs of the following field, we address this problem here. + // see https://github.com/odin-lang/Odin/issues/5353 + if field.comments == nil { + // We check if the comment is at the start of the next field + if i != len(v.fields) - 1 { + next_field := v.fields[i + 1] + if next_field.docs != nil && len(next_field.docs.list) > 0 { + list := next_field.docs.list + if list[0].pos.line == field.pos.line { + field.comments = ast.new(ast.Comment_Group, list[0].pos, parser.end_pos(list[0])) + field.comments.list = list[:1] + if len(list) > 1 { + next_field.docs = ast.new( + ast.Comment_Group, + list[1].pos, + parser.end_pos(list[len(list) - 2]), + ) + next_field.docs.list = list[1:] + } else { + next_field.docs = nil + } + } + } + } else { + // We need to check the file to see if it contains a line comment as there is no next field + field.comments = get_file_comment(file, field.pos.line) + } + } + } +} + // Retrives the comment group from the specified line of the file get_file_comment :: proc(file: ast.File, line: int) -> ^ast.Comment_Group { // TODO: linear scan might be a bit slow for files with lots of comments? diff --git a/src/server/collector.odin b/src/server/collector.odin index 22aba08..f4e4a1c 100644 --- a/src/server/collector.odin +++ b/src/server/collector.odin @@ -158,15 +158,19 @@ collect_struct_fields :: proc( collect_bit_field_fields :: proc( collection: ^SymbolCollection, - fields: []^ast.Bit_Field_Field, + bit_field_type: ^ast.Bit_Field_Type, package_map: map[string]string, file: ast.File, ) -> SymbolBitFieldValue { - names := make([dynamic]string, 0, len(fields), collection.allocator) - types := make([dynamic]^ast.Expr, 0, len(fields), collection.allocator) - ranges := make([dynamic]common.Range, 0, len(fields), collection.allocator) - - for field, i in fields { + construct_bit_field_field_docs(file, bit_field_type) + names := make([dynamic]string, 0, len(bit_field_type.fields), collection.allocator) + types := make([dynamic]^ast.Expr, 0, len(bit_field_type.fields), collection.allocator) + ranges := make([dynamic]common.Range, 0, len(bit_field_type.fields), collection.allocator) + docs := make([dynamic]^ast.Comment_Group, 0, collection.allocator) + comments := make([dynamic]^ast.Comment_Group, 0, collection.allocator) + bit_sizes := make([dynamic]^ast.Expr, 0, collection.allocator) + + for field, i in bit_field_type.fields { if ident, ok := field.name.derived.(^ast.Ident); ok { append(&names, get_index_unique_string(collection, ident.name)) @@ -175,13 +179,20 @@ collect_bit_field_fields :: proc( append(&types, cloned) append(&ranges, common.get_token_range(ident, file.src)) + append(&docs, clone_comment_group(field.docs, collection.allocator, &collection.unique_strings)) + append(&comments, clone_comment_group(field.comments, collection.allocator, &collection.unique_strings)) + append(&bit_sizes, clone_type(field.bit_size, collection.allocator, &collection.unique_strings)) } } value := SymbolBitFieldValue { - names = names[:], - types = types[:], - ranges = ranges[:], + backing_type = clone_type(bit_field_type.backing_type, collection.allocator, &collection.unique_strings), + names = names[:], + types = types[:], + ranges = ranges[:], + docs = docs[:], + comments = comments[:], + bit_sizes = bit_sizes[:], } return value @@ -547,7 +558,7 @@ collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: stri case ^ast.Bit_Field_Type: token = v^ token_type = .Struct - symbol.value = collect_bit_field_fields(collection, v.fields, package_map, file) + symbol.value = collect_bit_field_fields(collection, v, package_map, file) symbol.signature = "bit_field" case ^ast.Map_Type: token = v^ diff --git a/src/server/documentation.odin b/src/server/documentation.odin index b52d259..b7196e5 100644 --- a/src/server/documentation.odin +++ b/src/server/documentation.odin @@ -2,6 +2,7 @@ package server import "core:fmt" import "core:log" +import "core:odin/ast" import path "core:path/slashpath" import "core:strings" @@ -9,8 +10,7 @@ import "core:strings" get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { is_variable := symbol.type == .Variable - pointer_prefix := repeat("^", symbol.pointers, context.temp_allocator) - + pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator) #partial switch v in symbol.value { case SymbolEnumValue: @@ -19,6 +19,13 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) strings.write_string(&sb, " :: ") } + if len(v.names) == 0 { + strings.write_string(&sb, "enum {}") + if symbol.comment != "" { + fmt.sbprintf(&sb, " %s", symbol.comment) + } + return strings.to_string(sb) + } longestNameLen := 0 for name in v.names { @@ -71,6 +78,10 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) strings.write_string(&sb, " :: ") } + if len(v.types) == 0 { + strings.write_string(&sb, "union {}") + return strings.to_string(sb) + } strings.write_string(&sb, "union {\n") for i in 0 ..< len(v.types) { strings.write_string(&sb, "\t") @@ -80,7 +91,7 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { strings.write_string(&sb, "}") return strings.to_string(sb) case SymbolAggregateValue: - sb := strings.builder_make(context.temp_allocator) + sb := strings.builder_make(ast_context.allocator) strings.write_string(&sb, "proc {\n") for symbol in v.symbols { if value, ok := symbol.value.(SymbolProcedureValue); ok { @@ -91,6 +102,53 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { } strings.write_string(&sb, "}") return strings.to_string(sb) + case SymbolBitFieldValue: + sb := strings.builder_make(ast_context.allocator) + if is_variable { + append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) + strings.write_string(&sb, " :: ") + } else if symbol.type_name != "" { + if symbol.type_pkg == "" { + fmt.sbprintf(&sb, "%s%s :: ", pointer_prefix, symbol.type_name) + } else { + pkg_name := get_pkg_name(ast_context, symbol.type_pkg) + fmt.sbprintf(&sb, "%s%s.%s :: ", pointer_prefix, pkg_name, symbol.type_name) + } + } + strings.write_string(&sb, "bit_field ") + build_string_node(v.backing_type, &sb, false) + if len(v.names) == 0 { + strings.write_string(&sb, " {}") + return strings.to_string(sb) + } + strings.write_string(&sb, " {\n") + longest_name_len := 0 + for name in v.names { + if len(name) > longest_name_len { + longest_name_len = len(name) + } + } + longest_type_len := 0 + type_names := make([dynamic]string, 0, len(v.types), ast_context.allocator) + for t in v.types { + type_name := node_to_string(t) + append(&type_names, type_name) + if len(type_name) > longest_type_len { + longest_type_len = len(type_name) + } + } + + for name, i in v.names { + append_docs(&sb, v.docs, i) + fmt.sbprintf(&sb, "\t%s:%*s", v.names[i], longest_name_len - len(name) + 1, "") + fmt.sbprintf(&sb, "%s%*s| ", type_names[i], longest_type_len - len(type_names[i]) + 1, "") + build_string_node(v.bit_sizes[i], &sb, false) + strings.write_string(&sb, ",") + append_comments(&sb, v.comments, i) + strings.write_string(&sb, "\n") + } + strings.write_string(&sb, "}") + return strings.to_string(sb) } return get_short_signature(ast_context, symbol) @@ -99,7 +157,7 @@ get_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string { is_variable := symbol.type == .Variable - pointer_prefix := repeat("^", symbol.pointers, context.temp_allocator) + pointer_prefix := repeat("^", symbol.pointers, ast_context.allocator) #partial switch v in symbol.value { case SymbolBasicValue: sb := strings.builder_make(ast_context.allocator) @@ -139,7 +197,7 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string allocator = ast_context.allocator, ) case SymbolProcedureValue: - sb := strings.builder_make(context.temp_allocator) + sb := strings.builder_make(ast_context.allocator) if symbol.type_pkg != "" && symbol.type_name != "" { pkg_name := get_pkg_name(ast_context, symbol.type_pkg) fmt.sbprintf(&sb, "%s%s.%s :: ", pointer_prefix, pkg_name, symbol.type_name) @@ -170,11 +228,20 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string } return strings.to_string(sb) case SymbolBitFieldValue: + sb := strings.builder_make(ast_context.allocator) if is_variable { - return strings.concatenate({pointer_prefix, symbol.name}, ast_context.allocator) + append_variable_full_name(&sb, ast_context, symbol, pointer_prefix) + } else if symbol.type_name != "" { + write_symbol_type_information(ast_context, &sb, symbol, pointer_prefix) } else { - return "bit_field" + strings.write_string(&sb, "bit_field ") + build_string_node(v.backing_type, &sb, false) + } + if symbol.comment != "" { + fmt.sbprintf(&sb, " %s", symbol.comment) } + return strings.to_string(sb) + case SymbolMultiPointerValue: return strings.concatenate( a = {pointer_prefix, "[^]", node_to_string(v.expr)}, @@ -227,8 +294,8 @@ get_short_signature :: proc(ast_context: ^AstContext, symbol: Symbol) -> string return "" } -get_enum_field_signature :: proc(value: SymbolEnumValue, index: int) -> string { - sb := strings.builder_make(context.temp_allocator) +get_enum_field_signature :: proc(value: SymbolEnumValue, index: int, allocator := context.temp_allocator) -> string { + sb := strings.builder_make(allocator) fmt.sbprintf(&sb, ".%s", value.names[index]) if index < len(value.values) && value.values[index] != nil { strings.write_string(&sb, " = ") @@ -237,6 +304,15 @@ get_enum_field_signature :: proc(value: SymbolEnumValue, index: int) -> string { return strings.to_string(sb) } +get_bit_field_field_signature :: proc(value: SymbolBitFieldValue, index: int, allocator := context.temp_allocator) -> string { + sb := strings.builder_make(allocator) + build_string_node(value.types[index], &sb, false) + strings.write_string(&sb, " | ") + build_string_node(value.bit_sizes[index], &sb, false) + append_comments(&sb, value.comments, index) + return strings.to_string(sb) +} + write_symbol_type_information :: proc(ast_context: ^AstContext, sb: ^strings.Builder, symbol: Symbol, pointer_prefix: string) { append_type_pkg := false pkg_name := get_pkg_name(ast_context, symbol.type_pkg) @@ -294,7 +370,17 @@ write_struct_hover :: proc(ast_context: ^AstContext, sb: ^strings.Builder, v: Sy l += len(using_prefix) } if l > longestNameLen { - longestNameLen = len(name) + longestNameLen = l + } + } + + longest_type_len := 0 + type_names := make([dynamic]string, 0, len(v.types), ast_context.allocator) + for t in v.types { + type_name := node_to_string(t) + append(&type_names, type_name) + if len(type_name) > longest_type_len { + longest_type_len = len(type_name) } } @@ -338,16 +424,16 @@ write_struct_hover :: proc(ast_context: ^AstContext, sb: ^strings.Builder, v: Sy if index := v.from_usings[i]; index != using_index { fmt.sbprintf(sb, "\n\t// from `using %s: ", v.names[index]) build_string_node(v.types[index], sb, false) + if backing_type, ok := v.backing_types[index]; ok { + strings.write_string(sb, " (bit_field ") + build_string_node(backing_type, sb, false) + strings.write_string(sb, ")") + } strings.write_string(sb, "`\n") using_index = index } } - if i < len(v.docs) && v.docs[i] != nil { - for c in v.docs[i].list { - fmt.sbprintf(sb, "\t%s\n", c.text) - } - } - + append_docs(sb, v.docs, i) strings.write_string(sb, "\t") name_len := len(v.names[i]) @@ -355,18 +441,14 @@ write_struct_hover :: proc(ast_context: ^AstContext, sb: ^strings.Builder, v: Sy strings.write_string(sb, using_prefix) name_len += len(using_prefix) } - strings.write_string(sb, v.names[i]) - fmt.sbprintf(sb, ":%*s", longestNameLen - name_len + 1, "") - build_string_node(v.types[i], sb, false) - strings.write_string(sb, ",") - - if i < len(v.comments) && v.comments[i] != nil { - for c in v.comments[i].list { - fmt.sbprintf(sb, " %s\n", c.text) - } - } else { - strings.write_string(sb, "\n") + fmt.sbprintf(sb, "%s:%*s%s", v.names[i], longestNameLen - name_len + 1, "", type_names[i]) + if bit_size, ok := v.bit_sizes[i]; ok { + fmt.sbprintf(sb, "%*s| ", longest_type_len - len(type_names[i]) + 1, "") + build_string_node(bit_size, sb, false) } + strings.write_string(sb, ",") + append_comments(sb, v.comments, i) + strings.write_string(sb, "\n") } strings.write_string(sb, "}") } @@ -386,6 +468,22 @@ append_variable_full_name :: proc( return } +append_docs :: proc(sb: ^strings.Builder, docs: []^ast.Comment_Group, index: int) { + if index < len(docs) && docs[index] != nil { + for c in docs[index].list { + fmt.sbprintf(sb, "\t%s\n", c.text) + } + } +} + +append_comments :: proc(sb: ^strings.Builder, comments: []^ast.Comment_Group, index: int) { + if index < len(comments) && comments[index] != nil { + for c in comments[index].list { + fmt.sbprintf(sb, " %s", c.text) + } + } +} + concatenate_symbol_information :: proc { concatenate_raw_symbol_information, concatenate_raw_string_information, diff --git a/src/server/hover.odin b/src/server/hover.odin index 4965621..fafc023 100644 --- a/src/server/hover.odin +++ b/src/server/hover.odin @@ -156,8 +156,8 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> } if position_context.struct_type != nil { - for field in position_context.struct_type.fields.list { - for name in field.names { + for field, field_index in position_context.struct_type.fields.list { + for name, name_index in field.names { if position_in_node(name, position_context.position) { if identifier, ok := name.derived.(^ast.Ident); ok && field.type != nil { if symbol, ok := resolve_type_expression(&ast_context, field.type); ok { @@ -171,21 +171,8 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> symbol.type_pkg = symbol.pkg symbol.pkg = struct_symbol.name symbol.name = identifier.name - - // Get the inline comment from the field definition if it exists if value, ok := struct_symbol.value.(SymbolStructValue); ok { - index := -1 - for n, i in value.names { - if n == symbol.name { - index = i - break - } - } - if index != -1 && - value.comments[index] != nil && - len(value.comments[index].list) > 0 { - symbol.comment = value.comments[index].list[0].text - } + symbol.comment = get_comment(value.comments[field_index + name_index]) } symbol.signature = get_short_signature(&ast_context, symbol) @@ -198,6 +185,37 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> } } } + + if position_context.bit_field_type != nil { + for field, i in position_context.bit_field_type.fields { + if position_in_node(field.name, position_context.position) { + if identifier, ok := field.name.derived.(^ast.Ident); ok && field.type != nil { + if symbol, ok := resolve_type_expression(&ast_context, field.type); ok { + if bit_field_symbol, ok := resolve_type_expression( + &ast_context, + position_context.value_decl.names[0], + ); ok { + if value, ok := bit_field_symbol.value.(SymbolBitFieldValue); ok { + symbol.type = .Field + symbol.range = common.get_token_range(field.node, ast_context.file.src) + symbol.type_name = symbol.name + symbol.type_pkg = symbol.pkg + symbol.pkg = bit_field_symbol.name + symbol.name = identifier.name + symbol.signature = get_bit_field_field_signature(value, i) + + if value, ok := bit_field_symbol.value.(SymbolBitFieldValue); ok { + symbol.comment = get_comment(value.comments[i]) + } + hover.contents = write_hover_content(&ast_context, symbol) + return hover, true, true + } + } + } + } + } + } + } } if position_context.field_value != nil && position_context.comp_lit != nil { @@ -220,6 +238,7 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> } else if v, ok := comp_symbol.value.(SymbolBitFieldValue); ok { for name, i in v.names { if name == field.name { + log.info("here?") if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { symbol.name = name symbol.pkg = comp_symbol.name @@ -314,7 +333,8 @@ get_hover_information :: proc(document: ^Document, position: common.Position) -> if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok { symbol.name = name symbol.pkg = selector.name - symbol.signature = node_to_string(v.types[i]) + symbol.signature = get_bit_field_field_signature(v, i) + symbol.doc = get_doc(v.docs[i], ast_context.allocator) hover.contents = write_hover_content(&ast_context, symbol) return hover, true, true } diff --git a/src/server/symbol.odin b/src/server/symbol.odin index fddc775..d1e88ad 100644 --- a/src/server/symbol.odin +++ b/src/server/symbol.odin @@ -36,12 +36,20 @@ SymbolStructValue :: struct { args: []^ast.Expr, //The arguments in the call expression for poly docs: []^ast.Comment_Group, comments: []^ast.Comment_Group, + + // Extra fields for embedded bit fields via usings + backing_types: map[int]^ast.Expr, // the base type for the bit field + bit_sizes: map[int]^ast.Expr, // the bit size of the bit field field } SymbolBitFieldValue :: struct { - names: []string, - ranges: []common.Range, - types: []^ast.Expr, + backing_type: ^ast.Expr, + names: []string, + ranges: []common.Range, + types: []^ast.Expr, + docs: []^ast.Comment_Group, + comments: []^ast.Comment_Group, + bit_sizes: []^ast.Expr, } SymbolPackageValue :: struct { @@ -212,6 +220,8 @@ SymbolStructValueBuilder :: struct { unexpanded_usings: [dynamic]int, poly: ^ast.Field_List, poly_names: [dynamic]string, + backing_types: map[int]^ast.Expr, + bit_sizes: map[int]^ast.Expr, } symbol_struct_value_builder_make_none :: proc(allocator := context.allocator) -> SymbolStructValueBuilder { @@ -226,6 +236,8 @@ symbol_struct_value_builder_make_none :: proc(allocator := context.allocator) -> from_usings = make([dynamic]int, allocator), unexpanded_usings = make([dynamic]int, allocator), poly_names = make([dynamic]string, allocator), + backing_types = make(map[int]^ast.Expr, allocator), + bit_sizes = make(map[int]^ast.Expr, allocator), } } @@ -245,6 +257,8 @@ symbol_struct_value_builder_make_symbol :: proc( from_usings = make([dynamic]int, allocator), unexpanded_usings = make([dynamic]int, allocator), poly_names = make([dynamic]string, allocator), + backing_types = make(map[int]^ast.Expr, allocator), + bit_sizes = make(map[int]^ast.Expr, allocator), } } @@ -265,6 +279,8 @@ symbol_struct_value_builder_make_symbol_symbol_struct_value :: proc( from_usings = slice.to_dynamic(v.from_usings, allocator), unexpanded_usings = slice.to_dynamic(v.unexpanded_usings, allocator), poly_names = slice.to_dynamic(v.poly_names, allocator), + backing_types = v.backing_types, + bit_sizes = v.bit_sizes, } } @@ -293,21 +309,22 @@ to_symbol_struct_value :: proc(b: SymbolStructValueBuilder) -> SymbolStructValue unexpanded_usings = b.unexpanded_usings[:], poly = b.poly, poly_names = b.poly_names[:], + backing_types = b.backing_types, + bit_sizes = b.bit_sizes, } } write_struct_type :: proc( ast_context: ^AstContext, b: ^SymbolStructValueBuilder, - v: ast.Struct_Type, + v: ^ast.Struct_Type, ident: ast.Ident, attributes: []^ast.Attribute, base_using_index: int, inlined := false, ) { b.poly = v.poly_params - v := v - construct_struct_field_docs(ast_context.file, &v) + construct_struct_field_docs(ast_context.file, v) for field, i in v.fields.list { for n in field.names { if identifier, ok := n.derived.(^ast.Ident); ok && field.type != nil { @@ -381,12 +398,49 @@ write_symbol_struct_value :: proc( for u in v.unexpanded_usings { append(&b.unexpanded_usings, u+base_index) } + for k, value in v.backing_types { + b.backing_types[k+base_index] = value + } + for k, value in v.bit_sizes { + b.bit_sizes[k+base_index] = value + } for k in v.usings { b.usings[k+base_index] = struct{}{} } expand_usings(ast_context, b) } +write_symbol_bitfield_value :: proc( + ast_context: ^AstContext, + b: ^SymbolStructValueBuilder, + v: SymbolBitFieldValue, + base_using_index: int, +) { + base_index := len(b.names) + for name, i in v.names { + append(&b.names, name) + append(&b.from_usings, base_using_index) + } + for type in v.types { + append(&b.types, type) + } + for range in v.ranges { + append(&b.ranges, range) + } + for doc in v.docs { + append(&b.docs, doc) + } + for comment in v.comments { + append(&b.comments, comment) + } + b.backing_types[base_using_index] = v.backing_type + for bit_size, i in v.bit_sizes { + b.bit_sizes[i+base_index] = bit_size + } + expand_usings(ast_context, b) + +} + expand_usings :: proc(ast_context: ^AstContext, b: ^SymbolStructValueBuilder) { base := len(b.names) - 1 for len(b.unexpanded_usings) > 0 { @@ -405,23 +459,27 @@ expand_usings :: proc(ast_context: ^AstContext, b: ^SymbolStructValueBuilder) { if ident, ok := field_expr.derived.(^ast.Ident); ok { if v, ok := struct_type_from_identifier(ast_context, ident^); ok { - write_struct_type(ast_context, b, v^, ident^, {}, u, true) + write_struct_type(ast_context, b, v, ident^, {}, u, true) } else { clear(&ast_context.recursion_map) if symbol, ok := resolve_type_identifier(ast_context, ident^); ok { if v, ok := symbol.value.(SymbolStructValue); ok { write_symbol_struct_value(ast_context, b, v, u) + } else if v, ok := symbol.value.(SymbolBitFieldValue); ok { + write_symbol_bitfield_value(ast_context, b, v, u) } } } } else if selector, ok := field_expr.derived.(^ast.Selector_Expr); ok { - if s, ok := resolve_selector_expression(ast_context, selector); ok { - if v, ok := s.value.(SymbolStructValue); ok { + if symbol, ok := resolve_selector_expression(ast_context, selector); ok { + if v, ok := symbol.value.(SymbolStructValue); ok { write_symbol_struct_value(ast_context, b, v, u) + } else if v, ok := symbol.value.(SymbolBitFieldValue); ok { + write_symbol_bitfield_value(ast_context, b, v, u) } } } else if v, ok := field_expr.derived.(^ast.Struct_Type); ok { - write_struct_type(ast_context, b, v^, ast_context.field_name, {}, u) + write_struct_type(ast_context, b, v, ast_context.field_name, {}, u) } delete_key(&ast_context.recursion_map, b.types[u]) } |