mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
Merge branch 'master' into parsing-package-fixes
This commit is contained in:
+31
-6
@@ -597,6 +597,7 @@ Field_Flag :: enum {
|
||||
Any_Int,
|
||||
Subtype,
|
||||
By_Ptr,
|
||||
No_Broadcast,
|
||||
|
||||
Results,
|
||||
Tags,
|
||||
@@ -616,6 +617,7 @@ field_flag_strings := [Field_Flag]string{
|
||||
.Any_Int = "#any_int",
|
||||
.Subtype = "#subtype",
|
||||
.By_Ptr = "#by_ptr",
|
||||
.No_Broadcast = "#no_broadcast",
|
||||
|
||||
.Results = "results",
|
||||
.Tags = "field tag",
|
||||
@@ -624,12 +626,13 @@ field_flag_strings := [Field_Flag]string{
|
||||
}
|
||||
|
||||
field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
|
||||
{"no_alias", .No_Alias},
|
||||
{"c_vararg", .C_Vararg},
|
||||
{"const", .Const},
|
||||
{"any_int", .Any_Int},
|
||||
{"subtype", .Subtype},
|
||||
{"by_ptr", .By_Ptr},
|
||||
{"no_alias", .No_Alias},
|
||||
{"c_vararg", .C_Vararg},
|
||||
{"const", .Const},
|
||||
{"any_int", .Any_Int},
|
||||
{"subtype", .Subtype},
|
||||
{"by_ptr", .By_Ptr},
|
||||
{"no_broadcast", .No_Broadcast},
|
||||
}
|
||||
|
||||
|
||||
@@ -650,6 +653,7 @@ Field_Flags_Signature :: Field_Flags{
|
||||
.Const,
|
||||
.Any_Int,
|
||||
.By_Ptr,
|
||||
.No_Broadcast,
|
||||
.Default_Parameters,
|
||||
}
|
||||
|
||||
@@ -768,6 +772,7 @@ Struct_Type :: struct {
|
||||
tok_pos: tokenizer.Pos,
|
||||
poly_params: ^Field_List,
|
||||
align: ^Expr,
|
||||
field_align: ^Expr,
|
||||
where_token: tokenizer.Token,
|
||||
where_clauses: []^Expr,
|
||||
is_packed: bool,
|
||||
@@ -837,6 +842,23 @@ Matrix_Type :: struct {
|
||||
elem: ^Expr,
|
||||
}
|
||||
|
||||
Bit_Field_Type :: struct {
|
||||
using node: Expr,
|
||||
tok_pos: tokenizer.Pos,
|
||||
backing_type: ^Expr,
|
||||
open: tokenizer.Pos,
|
||||
fields: []^Bit_Field_Field,
|
||||
close: tokenizer.Pos,
|
||||
}
|
||||
|
||||
Bit_Field_Field :: struct {
|
||||
using node: Node,
|
||||
docs: ^Comment_Group,
|
||||
name: ^Expr,
|
||||
type: ^Expr,
|
||||
bit_size: ^Expr,
|
||||
comments: ^Comment_Group,
|
||||
}
|
||||
|
||||
Any_Node :: union {
|
||||
^Package,
|
||||
@@ -893,6 +915,7 @@ Any_Node :: union {
|
||||
^Map_Type,
|
||||
^Relative_Type,
|
||||
^Matrix_Type,
|
||||
^Bit_Field_Type,
|
||||
|
||||
^Bad_Stmt,
|
||||
^Empty_Stmt,
|
||||
@@ -923,6 +946,7 @@ Any_Node :: union {
|
||||
^Attribute,
|
||||
^Field,
|
||||
^Field_List,
|
||||
^Bit_Field_Field,
|
||||
}
|
||||
|
||||
|
||||
@@ -977,6 +1001,7 @@ Any_Expr :: union {
|
||||
^Map_Type,
|
||||
^Relative_Type,
|
||||
^Matrix_Type,
|
||||
^Bit_Field_Type,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package odin_ast
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
import "core:fmt"
|
||||
import "core:reflect"
|
||||
@@ -314,6 +314,7 @@ clone_node :: proc(node: ^Node) -> ^Node {
|
||||
case ^Struct_Type:
|
||||
r.poly_params = auto_cast clone(r.poly_params)
|
||||
r.align = clone(r.align)
|
||||
r.field_align = clone(r.field_align)
|
||||
r.fields = auto_cast clone(r.fields)
|
||||
case ^Union_Type:
|
||||
r.poly_params = auto_cast clone(r.poly_params)
|
||||
@@ -335,6 +336,13 @@ clone_node :: proc(node: ^Node) -> ^Node {
|
||||
case ^Relative_Type:
|
||||
r.tag = clone(r.tag)
|
||||
r.type = clone(r.type)
|
||||
case ^Bit_Field_Type:
|
||||
r.backing_type = clone(r.backing_type)
|
||||
r.fields = auto_cast clone(r.fields)
|
||||
case ^Bit_Field_Field:
|
||||
r.name = clone(r.name)
|
||||
r.type = clone(r.type)
|
||||
r.bit_size = clone(r.bit_size)
|
||||
case:
|
||||
fmt.panicf("Unhandled node kind: %v", r)
|
||||
}
|
||||
|
||||
@@ -414,7 +414,15 @@ walk :: proc(v: ^Visitor, node: ^Node) {
|
||||
walk(v, n.row_count)
|
||||
walk(v, n.column_count)
|
||||
walk(v, n.elem)
|
||||
|
||||
case ^Bit_Field_Type:
|
||||
walk(v, n.backing_type)
|
||||
for f in n.fields {
|
||||
walk(v, f)
|
||||
}
|
||||
case ^Bit_Field_Field:
|
||||
walk(v, n.name)
|
||||
walk(v, n.type)
|
||||
walk(v, n.bit_size)
|
||||
case:
|
||||
fmt.panicf("ast.walk: unexpected node type %T", n)
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ Array :: struct($T: typeid) {
|
||||
String :: distinct Array(byte)
|
||||
|
||||
Version_Type_Major :: 0
|
||||
Version_Type_Minor :: 2
|
||||
Version_Type_Patch :: 4
|
||||
Version_Type_Minor :: 3
|
||||
Version_Type_Patch :: 1
|
||||
|
||||
Version_Type :: struct {
|
||||
major, minor, patch: u8,
|
||||
@@ -102,13 +102,17 @@ Entity_Flag :: enum u32le {
|
||||
Foreign = 0,
|
||||
Export = 1,
|
||||
|
||||
Param_Using = 2, // using
|
||||
Param_Const = 3, // #const
|
||||
Param_Auto_Cast = 4, // auto_cast
|
||||
Param_Ellipsis = 5, // Variadic parameter
|
||||
Param_CVararg = 6, // #c_vararg
|
||||
Param_No_Alias = 7, // #no_alias
|
||||
Param_Any_Int = 8, // #any_int
|
||||
Param_Using = 2, // using
|
||||
Param_Const = 3, // #const
|
||||
Param_Auto_Cast = 4, // auto_cast
|
||||
Param_Ellipsis = 5, // Variadic parameter
|
||||
Param_CVararg = 6, // #c_vararg
|
||||
Param_No_Alias = 7, // #no_alias
|
||||
Param_Any_Int = 8, // #any_int
|
||||
Param_By_Ptr = 9, // #by_ptr
|
||||
Param_No_Broadcast = 10, // #no_broadcast
|
||||
|
||||
Bit_Field_Field = 19,
|
||||
|
||||
Type_Alias = 20,
|
||||
|
||||
@@ -137,6 +141,7 @@ Entity :: struct {
|
||||
// May be used by (Struct fields and procedure fields):
|
||||
// .Variable
|
||||
// .Constant
|
||||
// This is equal to the negative of the "bit size" it this is a `bit_field`s field
|
||||
field_group_index: i32le,
|
||||
|
||||
// May used by:
|
||||
@@ -187,6 +192,7 @@ Type_Kind :: enum u32le {
|
||||
Multi_Pointer = 22,
|
||||
Matrix = 23,
|
||||
Soa_Pointer = 24,
|
||||
Bit_Field = 25,
|
||||
}
|
||||
|
||||
Type_Elems_Cap :: 4
|
||||
@@ -243,10 +249,10 @@ Type :: struct {
|
||||
// .Bit_Set - <=2 types: 0=element type, 1=underlying type (Underlying_Type flag will be set)
|
||||
// .Simd_Vector - 1 type: 0=element
|
||||
// .Relative_Pointer - 2 types: 0=pointer type, 1=base integer
|
||||
// .Relative_Slice - 2 types: 0=slice type, 1=base integer
|
||||
// .Multi_Pointer - 1 type: 0=element
|
||||
// .Matrix - 1 type: 0=element
|
||||
// .Soa_Pointer - 1 type: 0=element
|
||||
// .Bit_Field - 1 type: 0=backing type
|
||||
types: Array(Type_Index),
|
||||
|
||||
// Used by:
|
||||
|
||||
@@ -440,6 +440,24 @@ expect_closing_token_of_field_list :: proc(p: ^Parser, closing_kind: tokenizer.T
|
||||
return expect_closing
|
||||
}
|
||||
|
||||
expect_closing_parentheses_of_field_list :: proc(p: ^Parser) -> tokenizer.Token {
|
||||
token := p.curr_tok
|
||||
if allow_token(p, .Close_Paren) {
|
||||
return token
|
||||
}
|
||||
|
||||
if allow_token(p, .Semicolon) && !tokenizer.is_newline(token) {
|
||||
str := tokenizer.token_to_string(token)
|
||||
error(p, end_of_line_pos(p, p.prev_tok), "expected a comma, got %s", str)
|
||||
}
|
||||
|
||||
for p.curr_tok.kind != .Close_Paren && p.curr_tok.kind != .EOF && !is_non_inserted_semicolon(p.curr_tok) {
|
||||
advance_token(p)
|
||||
}
|
||||
|
||||
return expect_token(p, .Close_Paren)
|
||||
}
|
||||
|
||||
is_non_inserted_semicolon :: proc(tok: tokenizer.Token) -> bool {
|
||||
return tok.kind == .Semicolon && tok.text != "\n"
|
||||
}
|
||||
@@ -517,7 +535,7 @@ is_semicolon_optional_for_node :: proc(p: ^Parser, node: ^ast.Node) -> bool {
|
||||
return is_semicolon_optional_for_node(p, n.type)
|
||||
case ^ast.Pointer_Type:
|
||||
return is_semicolon_optional_for_node(p, n.elem)
|
||||
case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type:
|
||||
case ^ast.Struct_Type, ^ast.Union_Type, ^ast.Enum_Type, ^ast.Bit_Set_Type, ^ast.Bit_Field_Type:
|
||||
// Require semicolon within a procedure body
|
||||
return p.curr_proc == nil
|
||||
case ^ast.Proc_Lit:
|
||||
@@ -2100,7 +2118,7 @@ parse_proc_type :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Proc_Type {
|
||||
|
||||
expect_token(p, .Open_Paren)
|
||||
params, _ := parse_field_list(p, .Close_Paren, ast.Field_Flags_Signature_Params)
|
||||
expect_token(p, .Close_Paren)
|
||||
expect_closing_parentheses_of_field_list(p)
|
||||
results, diverging := parse_results(p)
|
||||
|
||||
is_generic := false
|
||||
@@ -2534,6 +2552,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
|
||||
poly_params: ^ast.Field_List
|
||||
align: ^ast.Expr
|
||||
field_align: ^ast.Expr
|
||||
is_packed: bool
|
||||
is_raw_union: bool
|
||||
is_no_copy: bool
|
||||
@@ -2565,6 +2584,11 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
}
|
||||
align = parse_expr(p, true)
|
||||
case "field_align":
|
||||
if field_align != nil {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
}
|
||||
field_align = parse_expr(p, true)
|
||||
case "raw_union":
|
||||
if is_raw_union {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
@@ -2607,6 +2631,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
st := ast.new(ast.Struct_Type, tok.pos, end_pos(close))
|
||||
st.poly_params = poly_params
|
||||
st.align = align
|
||||
st.field_align = field_align
|
||||
st.is_packed = is_packed
|
||||
st.is_raw_union = is_raw_union
|
||||
st.is_no_copy = is_no_copy
|
||||
@@ -2770,6 +2795,48 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
mt.column_count = column_count
|
||||
mt.elem = elem
|
||||
return mt
|
||||
|
||||
case .Bit_Field:
|
||||
tok := expect_token(p, .Bit_Field)
|
||||
|
||||
backing_type := parse_type_or_ident(p)
|
||||
if backing_type == nil {
|
||||
token := advance_token(p)
|
||||
error(p, token.pos, "Expected a backing type for a 'bit_field'")
|
||||
}
|
||||
|
||||
skip_possible_newline_for_literal(p)
|
||||
open := expect_token_after(p, .Open_Brace, "bit_field")
|
||||
|
||||
fields: [dynamic]^ast.Bit_Field_Field
|
||||
for p.curr_tok.kind != .Close_Brace && p.curr_tok.kind != .EOF {
|
||||
name := parse_ident(p)
|
||||
expect_token(p, .Colon)
|
||||
type := parse_type(p)
|
||||
expect_token(p, .Or)
|
||||
bit_size := parse_expr(p, true)
|
||||
|
||||
field := ast.new(ast.Bit_Field_Field, name.pos, bit_size)
|
||||
|
||||
field.name = name
|
||||
field.type = type
|
||||
field.bit_size = bit_size
|
||||
|
||||
append(&fields, field)
|
||||
|
||||
allow_token(p, .Comma) or_break
|
||||
}
|
||||
|
||||
close := expect_closing_brace_of_field_list(p)
|
||||
|
||||
bf := ast.new(ast.Bit_Field_Type, tok.pos, close.pos)
|
||||
|
||||
bf.tok_pos = tok.pos
|
||||
bf.backing_type = backing_type
|
||||
bf.open = open.pos
|
||||
bf.fields = fields[:]
|
||||
bf.close = close.pos
|
||||
return bf
|
||||
|
||||
case .Asm:
|
||||
tok := expect_token(p, .Asm)
|
||||
@@ -2877,7 +2944,8 @@ is_literal_type :: proc(expr: ^ast.Expr) -> bool {
|
||||
^ast.Map_Type,
|
||||
^ast.Bit_Set_Type,
|
||||
^ast.Matrix_Type,
|
||||
^ast.Call_Expr:
|
||||
^ast.Call_Expr,
|
||||
^ast.Bit_Field_Type:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -2927,6 +2995,7 @@ parse_literal_value :: proc(p: ^Parser, type: ^ast.Expr) -> ^ast.Comp_Lit {
|
||||
}
|
||||
p.expr_level -= 1
|
||||
|
||||
skip_possible_newline(p)
|
||||
close := expect_closing_brace_of_field_list(p);
|
||||
|
||||
pos := type.pos if type != nil else open.pos
|
||||
|
||||
@@ -643,7 +643,7 @@ align_switch_stmt :: proc(p: ^Printer, index: int) {
|
||||
format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator)
|
||||
|
||||
//find all the switch cases that are one lined
|
||||
for line, line_index in p.lines[brace_line + 1:] {
|
||||
for line in p.lines[brace_line + 1:] {
|
||||
|
||||
case_found := false
|
||||
colon_found := false
|
||||
@@ -716,7 +716,7 @@ align_enum :: proc(p: ^Printer, index: int) {
|
||||
|
||||
format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator)
|
||||
|
||||
for line, line_index in p.lines[brace_line + 1:] {
|
||||
for line in p.lines[brace_line + 1:] {
|
||||
length := 0
|
||||
|
||||
for format_token, i in line.format_tokens {
|
||||
@@ -880,7 +880,7 @@ align_comments :: proc(p: ^Printer) {
|
||||
|
||||
length := 0
|
||||
|
||||
for format_token, i in line.format_tokens {
|
||||
for format_token in line.format_tokens {
|
||||
if format_token.kind == .Comment {
|
||||
current_info.length = max(current_info.length, length)
|
||||
current_info.end = line_index
|
||||
|
||||
@@ -445,7 +445,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) {
|
||||
|
||||
for value in v.values {
|
||||
#partial switch a in value.derived {
|
||||
case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type:
|
||||
case ^ast.Union_Type, ^ast.Enum_Type, ^ast.Struct_Type, ^ast.Bit_Field_Type:
|
||||
add_semicolon = false || called_in_stmt
|
||||
case ^ast.Proc_Lit:
|
||||
add_semicolon = false
|
||||
@@ -488,6 +488,37 @@ visit_exprs :: proc(p: ^Printer, list: []^ast.Expr, options := List_Options{}) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
visit_bit_field_fields :: proc(p: ^Printer, list: []^ast.Bit_Field_Field, options := List_Options{}) {
|
||||
if len(list) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// we have to newline the expressions to respect the source
|
||||
for v, i in list {
|
||||
// Don't move the first expression, it looks bad
|
||||
if i != 0 && .Enforce_Newline in options {
|
||||
newline_position(p, 1)
|
||||
} else if i != 0 {
|
||||
move_line_limit(p, v.pos, 1)
|
||||
}
|
||||
|
||||
visit_expr(p, v.name, options)
|
||||
push_generic_token(p, .Colon, 0)
|
||||
visit_expr(p, v.type, options)
|
||||
push_generic_token(p, .Or, 1)
|
||||
visit_expr(p, v.bit_size, options)
|
||||
|
||||
if (i != len(list) - 1 || .Trailing in options) && .Add_Comma in options {
|
||||
push_generic_token(p, .Comma, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if len(list) > 1 && .Enforce_Newline in options {
|
||||
newline_position(p, 1)
|
||||
}
|
||||
}
|
||||
|
||||
@(private)
|
||||
visit_attributes :: proc(p: ^Printer, attributes: [dynamic]^ast.Attribute) {
|
||||
if len(attributes) == 0 {
|
||||
@@ -1293,6 +1324,25 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) {
|
||||
visit_expr(p, v.column_count)
|
||||
push_generic_token(p, .Close_Bracket, 0)
|
||||
visit_expr(p, v.elem)
|
||||
case ^ast.Bit_Field_Type:
|
||||
push_generic_token(p, .Bit_Field, 1)
|
||||
|
||||
visit_expr(p, v.backing_type)
|
||||
|
||||
if len(v.fields) == 0 || v.pos.line == v.close.line {
|
||||
push_generic_token(p, .Open_Brace, 1)
|
||||
visit_bit_field_fields(p, v.fields, {.Add_Comma})
|
||||
push_generic_token(p, .Close_Brace, 0)
|
||||
} else {
|
||||
visit_begin_brace(p, v.pos, .Generic, len(v.fields))
|
||||
newline_position(p, 1)
|
||||
set_source_position(p, v.fields[0].pos)
|
||||
visit_bit_field_fields(p, v.fields, {.Add_Comma, .Trailing, .Enforce_Newline})
|
||||
set_source_position(p, v.close)
|
||||
visit_end_brace(p, v.close)
|
||||
}
|
||||
|
||||
set_source_position(p, v.close)
|
||||
case:
|
||||
panic(fmt.aprint(expr.derived))
|
||||
}
|
||||
@@ -1462,9 +1512,9 @@ visit_binary_expr :: proc(p: ^Printer, binary: ^ast.Binary_Expr) {
|
||||
}
|
||||
|
||||
either_implicit_selector := false
|
||||
if _, ok := binary.left.derived.(^ast.Implicit_Selector_Expr); ok {
|
||||
if _, lok := binary.left.derived.(^ast.Implicit_Selector_Expr); lok {
|
||||
either_implicit_selector = true
|
||||
} else if _, ok := binary.right.derived.(^ast.Implicit_Selector_Expr); ok {
|
||||
} else if _, rok := binary.right.derived.(^ast.Implicit_Selector_Expr); rok {
|
||||
either_implicit_selector = true
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ Token_Kind :: enum u32 {
|
||||
Union, // union
|
||||
Enum, // enum
|
||||
Bit_Set, // bit_set
|
||||
Bit_Field, // bit_field
|
||||
Map, // map
|
||||
Dynamic, // dynamic
|
||||
Auto_Cast, // auto_cast
|
||||
@@ -270,6 +271,7 @@ tokens := [Token_Kind.COUNT]string {
|
||||
"union",
|
||||
"enum",
|
||||
"bit_set",
|
||||
"bit_field",
|
||||
"map",
|
||||
"dynamic",
|
||||
"auto_cast",
|
||||
|
||||
Reference in New Issue
Block a user