Skip to content

Commit

Permalink
Merge pull request #351 from laytan/bit-field-support
Browse files Browse the repository at this point in the history
support bit_fields
  • Loading branch information
DanielGavin authored Apr 15, 2024
2 parents 63758da + 25de95d commit 4c4b525
Show file tree
Hide file tree
Showing 12 changed files with 719 additions and 7 deletions.
38 changes: 38 additions & 0 deletions src/common/ast.odin
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,13 @@ free_ast_node :: proc(node: ^ast.Node, allocator: mem.Allocator) {
case ^Relative_Type:
free_ast(n.tag, allocator)
free_ast(n.type, allocator)
case ^Bit_Field_Type:
free_ast(n.backing_type, allocator)
for field in n.fields do free_ast(field, allocator)
case ^Bit_Field_Field:
free_ast(n.name, allocator)
free_ast(n.type, allocator)
free_ast(n.bit_size, allocator)
case:
panic(fmt.aprintf("free Unhandled node kind: %v", node.derived))
}
Expand Down Expand Up @@ -913,6 +920,22 @@ node_equal_node :: proc(a, b: ^ast.Node) -> bool {
ret &= node_equal(n.args, m.args)
return ret
}
case ^Bit_Field_Type:
if n, ok := a.derived.(^Bit_Field_Type); ok {
if len(n.fields) != len(m.fields) do return false
ret := node_equal(n.backing_type, m.backing_type)
for i in 0..<len(n.fields) {
ret &= node_equal(n.fields[i], m.fields[i])
}
return ret
}
case ^Bit_Field_Field:
if n, ok := a.derived.(^Bit_Field_Field); ok {
ret := node_equal(n.name, m.name)
ret &= node_equal(n.type, m.type)
ret &= node_equal(n.bit_size, m.bit_size)
return ret
}
case ^Typeid_Type:
return true
case:
Expand Down Expand Up @@ -1148,6 +1171,21 @@ build_string_node :: proc(
case ^ast.Multi_Pointer_Type:
strings.write_string(builder, "[^]")
build_string(n.elem, builder, remove_pointers)
case ^ast.Bit_Field_Type:
strings.write_string(builder, "bit_field")
build_string(n.backing_type, builder, remove_pointers)
for field, i in n.fields {
build_string(field, builder, remove_pointers)
if len(n.fields) - 1 != i {
strings.write_string(builder, ",")
}
}
case ^ast.Bit_Field_Field:
build_string(n.name, builder, remove_pointers)
strings.write_string(builder, ": ")
build_string(n.type, builder, remove_pointers)
strings.write_string(builder, " | ")
build_string(n.bit_size, builder, remove_pointers)
}
}

Expand Down
128 changes: 128 additions & 0 deletions src/odin/printer/visit.odin
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,94 @@ visit_enum_exprs :: proc(
return document
}

@(private)
visit_bit_field_fields :: proc(
p: ^Printer,
bit_field_type: ast.Bit_Field_Type,
options := List_Options{},
) -> ^Document {
if len(bit_field_type.fields) == 0 {
return empty()
}

document := empty()

name_alignment, type_alignment := get_possible_bit_field_alignment(bit_field_type.fields)

for field, i in bit_field_type.fields {
if i == 0 && .Enforce_Newline in options {
comment, _ := visit_comments(p, bit_field_type.fields[i].pos)
if _, is_nil := comment.(Document_Nil); !is_nil {
comment = cons(comment, newline(1))
}
document = cons(comment, document)
}

if (.Enforce_Newline in options) {
document = cons(
document,
cons_with_nopl(
cons(
visit_expr(p, field.name),
text_position(p, ":", field.name.end),
),
cons_with_nopl(
cons(
repeat_space(
name_alignment - get_node_length(field.name),
),
visit_expr(p, field.type),
),
cons_with_nopl(
cons(
repeat_space(
type_alignment - get_node_length(field.type),
),
text_position(p, "|", field.type.end),
),
visit_expr(p, field.bit_size),
),
),
),
)
} else {
document = group(
cons_with_opl(
document,
cons_with_nopl(
cons(
visit_expr(p, field.name),
text_position(p, ":", field.name.end),
),
cons_with_nopl(
cons_with_nopl(
visit_expr(p, field.type),
text_position(p, "|", field.type.end),
),
visit_expr(p, field.bit_size),
),
),
),
)
}

if (i != len(bit_field_type.fields) - 1 || .Trailing in options) &&
.Add_Comma in options {
document = cons(document, text(","))
}

if (i != len(bit_field_type.fields) - 1 && .Enforce_Newline in options) {
comment, _ := visit_comments(p, bit_field_type.fields[i + 1].pos)
document = cons(document, comment, newline(1))
} else if .Enforce_Newline in options {
comment, _ := visit_comments(p, bit_field_type.end)
document = cons(document, comment)
}
}

return document
}

@(private)
visit_union_exprs :: proc(
p: ^Printer,
Expand Down Expand Up @@ -1850,6 +1938,36 @@ visit_expr :: proc(
document = cons(document, newline(1), text_position(p, "}", v.end))
}

set_source_position(p, v.end)
case ^Bit_Field_Type:
document = text_position(p, "bit_field", v.pos)

document = cons_with_nopl(document, visit_expr(p, v.backing_type))

if len(v.fields) == 0 {
document = cons_with_nopl(document, text("{"))
document = cons(document, text("}"))
} else {
document = cons(document, break_with_space(), visit_begin_brace(p, v.pos, .Generic))
set_source_position(p, v.fields[0].pos)
document = cons(
document,
nest(
cons(
newline_position(p, 1, v.open),
visit_bit_field_fields(
p,
v^,
{.Add_Comma, .Trailing, .Enforce_Newline},
),
),
),
)
set_source_position(p, v.end)

document = cons(document, newline(1), text_position(p, "}", v.end))
}

set_source_position(p, v.end)
case ^Proc_Lit:
switch v.inlining {
Expand Down Expand Up @@ -2845,3 +2963,13 @@ get_possible_enum_alignment :: proc(exprs: []^ast.Expr) -> int {

return longest_name
}

@(private)
get_possible_bit_field_alignment :: proc(fields: []^ast.Bit_Field_Field) -> (longest_name: int, longest_type: int) {
for field in fields {
longest_name = max(longest_name, get_node_length(field.name))
longest_type = max(longest_type, get_node_length(field.type))
}

return
}
Loading

0 comments on commit 4c4b525

Please sign in to comment.