aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-07-05 11:43:12 +0200
committerGitHub <noreply@github.com>2025-07-05 11:43:12 +0200
commit09b1c91170d9e011316fa93dc7e98069dcdc6625 (patch)
tree78960751e7082cdde5a39f1527193c4f271c1281 /src
parentc7c76658be61af1532c0320dc0029e5b39f1c6fd (diff)
parent067efb7e8e3901eb9eaf0de8050997d4d4d07498 (diff)
Merge pull request #719 from BradLewis/feat/bit-field-improvements
Bit field improvements
Diffstat (limited to 'src')
-rw-r--r--src/server/analysis.odin27
-rw-r--r--src/server/ast.odin34
-rw-r--r--src/server/collector.odin31
-rw-r--r--src/server/documentation.odin152
-rw-r--r--src/server/hover.odin54
-rw-r--r--src/server/symbol.odin78
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])
}