From 66e4aaffc5d29710360ae238ab0c1285642ab6b8 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Mon, 10 Jul 2017 13:49:50 +0100 Subject: [PATCH] Use semicolons as field delimiters in records --- code/demo.odin | 48 +++++------ core/_preload.odin | 176 ++++++++++++++++++++-------------------- core/_soft_numbers.odin | 8 +- core/decimal.odin | 8 +- core/fmt.odin | 30 +++---- core/mem.odin | 14 ++-- core/os_linux.odin | 40 ++++----- core/os_x.odin | 40 ++++----- core/raw.odin | 26 +++--- core/strconv.odin | 26 +++--- core/sync_linux.odin | 10 +-- core/sync_windows.odin | 12 +-- core/sys/wgl.odin | 62 +++++++------- core/sys/windows.odin | 164 ++++++++++++++++++------------------- src/parser.cpp | 139 ++++++++++++++++++++++++++++--- 15 files changed, 460 insertions(+), 343 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index e2825c5fa..7e330eefa 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -42,9 +42,9 @@ general_stuff :: proc() { Foo :: struct { - x: int, - y: f32, - z: string, + x: int; + y: f32; + z: string; } foo := Foo{123, 0.513, "A string"}; x, y, z := expand_to_tuple(foo); @@ -176,8 +176,8 @@ default_return_values :: proc() { }; Entity :: struct { - name: string, - id: u32, + name: string; + id: u32; } some_thing :: proc(input: int) -> (result: ^Entity = nil, err := Error.None) { @@ -256,39 +256,39 @@ explicit_parametric_polymorphic_procedures :: proc() { Vector2 :: struct {x, y: f32}; Entity :: struct { - using position: Vector2, - flags: u64, - id: u64, - batch_index: u32, - slot_index: u32, - portable_id: u32, - derived: any, + using position: Vector2; + flags: u64; + id: u64; + batch_index: u32; + slot_index: u32; + portable_id: u32; + derived: any; } Rock :: struct { - using entity: ^Entity, - heavy: bool, + using entity: ^Entity; + heavy: bool; } Door :: struct { - using entity: ^Entity, - open: bool, + using entity: ^Entity; + open: bool; } Monster :: struct { - using entity: ^Entity, - is_robot: bool, - is_zombie: bool, + using entity: ^Entity; + is_robot: bool; + is_zombie: bool; } EntityManager :: struct { - batches: [dynamic]^EntityBatch, - next_portable_id: u32, + batches: [dynamic]^EntityBatch; + next_portable_id: u32; } ENTITIES_PER_BATCH :: 16; EntityBatch :: struct { - data: [ENTITIES_PER_BATCH]Entity, - occupied: [ENTITIES_PER_BATCH]bool, - batch_index: u32, + data: [ENTITIES_PER_BATCH]Entity; + occupied: [ENTITIES_PER_BATCH]bool; + batch_index: u32; } use_empty_slot :: proc(manager: ^EntityManager, batch: ^EntityBatch) -> ^Entity { diff --git a/core/_preload.odin b/core/_preload.odin index 203347692..bc6e1174b 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -23,12 +23,6 @@ import ( // implemented within the compiler rather than in this "preload" file -// IMPORTANT NOTE(bill): Do not change the order of any of this data -// The compiler relies upon this _exact_ order -TypeInfoEnumValue :: raw_union { - f: f64, - i: i128, -} // NOTE(bill): This must match the compiler's CallingConvention :: enum { Invalid = 0, @@ -38,75 +32,81 @@ CallingConvention :: enum { Std = 4, Fast = 5, } +// IMPORTANT NOTE(bill): Do not change the order of any of this data +// The compiler relies upon this _exact_ order +TypeInfoEnumValue :: raw_union { + f: f64; + i: i128; +} TypeInfoRecord :: struct #ordered { - types: []^TypeInfo, - names: []string, - offsets: []int, // offsets may not be used in tuples - usings: []bool, // usings may not be used in tuples - packed: bool, - ordered: bool, - custom_align: bool, + types: []^TypeInfo; + names: []string; + offsets: []int; // offsets may not be used in tuples + usings: []bool; // usings may not be used in tuples + packed: bool; + ordered: bool; + custom_align: bool; } TypeInfo :: union { - size: int, - align: int, + size: int; + align: int; - Named{name: string, base: ^TypeInfo}, - Integer{signed: bool}, - Rune{}, - Float{}, - Complex{}, - String{}, - Boolean{}, - Any{}, + Named{name: string; base: ^TypeInfo}; + Integer{signed: bool}; + Rune{}; + Float{}; + Complex{}; + String{}; + Boolean{}; + Any{}; Pointer{ - elem: ^TypeInfo, // nil -> rawptr - }, - Atomic{elem: ^TypeInfo}, + elem: ^TypeInfo; // nil -> rawptr + }; + Atomic{elem: ^TypeInfo}; Procedure{ - params: ^TypeInfo, // TypeInfo.Tuple - results: ^TypeInfo, // TypeInfo.Tuple - variadic: bool, - convention: CallingConvention, - }, + params: ^TypeInfo; // TypeInfo.Tuple + results: ^TypeInfo; // TypeInfo.Tuple + variadic: bool; + convention: CallingConvention; + }; Array{ - elem: ^TypeInfo, - elem_size: int, - count: int, - }, - DynamicArray{elem: ^TypeInfo, elem_size: int}, - Slice {elem: ^TypeInfo, elem_size: int}, - Vector {elem: ^TypeInfo, elem_size, count: int}, - Tuple {using record: TypeInfoRecord}, // Only really used for procedures - Struct {using record: TypeInfoRecord}, - RawUnion {using record: TypeInfoRecord}, + elem: ^TypeInfo; + elem_size: int; + count: int; + }; + DynamicArray{elem: ^TypeInfo; elem_size: int}; + Slice {elem: ^TypeInfo; elem_size: int}; + Vector {elem: ^TypeInfo; elem_size, count: int}; + Tuple {using record: TypeInfoRecord}; // Only really used for procedures + Struct {using record: TypeInfoRecord}; + RawUnion {using record: TypeInfoRecord}; Union{ common_fields: struct { - types: []^TypeInfo, - names: []string, - offsets: []int, // offsets may not be used in tuples - }, - variant_names: []string, - variant_types: []^TypeInfo, - }, + types: []^TypeInfo; + names: []string; + offsets: []int; // offsets may not be used in tuples + }; + variant_names: []string; + variant_types: []^TypeInfo; + }; Enum{ - base: ^TypeInfo, - names: []string, - values: []TypeInfoEnumValue, - }, + base: ^TypeInfo; + names: []string; + values: []TypeInfoEnumValue; + }; Map{ - key: ^TypeInfo, - value: ^TypeInfo, - generated_struct: ^TypeInfo, - count: int, // == 0 if dynamic - }, + key: ^TypeInfo; + value: ^TypeInfo; + generated_struct: ^TypeInfo; + count: int; // == 0 if dynamic + }; BitField{ - names: []string, - bits: []i32, - offsets: []i32, - }, + names: []string; + bits: []i32; + offsets: []i32; + }; } // NOTE(bill): only the ones that are needed (not all types) @@ -127,58 +127,58 @@ AllocatorProc :: proc(allocator_data: rawptr, mode: AllocatorMode, size, alignment: int, old_memory: rawptr, old_size: int, flags: u64 = 0) -> rawptr; Allocator :: struct #ordered { - procedure: AllocatorProc, - data: rawptr, + procedure: AllocatorProc; + data: rawptr; } Context :: struct #ordered { - thread_guid: int, - thread_index: int, + thread_guid: int; + thread_index: int; - allocator: Allocator, + allocator: Allocator; - user_data: rawptr, - user_index: int, + user_data: rawptr; + user_index: int; } DEFAULT_ALIGNMENT :: align_of([vector 4]f32); SourceCodeLocation :: struct { - fully_pathed_filename: string, - line, column: i64, - procedure: string, + fully_pathed_filename: string; + line, column: i64; + procedure: string; } __INITIAL_MAP_CAP :: 16; __MapKey :: struct #ordered { - hash: u128, - str: string, + hash: u128; + str: string; } __MapFindResult :: struct #ordered { - hash_index: int, - entry_prev: int, - entry_index: int, + hash_index: int; + entry_prev: int; + entry_index: int; } __MapEntryHeader :: struct #ordered { - key: __MapKey, - next: int, + key: __MapKey; + next: int; /* - value: Value_Type, + value: Value_Type; */ } __MapHeader :: struct #ordered { - m: ^raw.DynamicMap, - is_key_string: bool, - entry_size: int, - entry_align: int, - value_offset: int, - value_size: int, + m: ^raw.DynamicMap; + is_key_string: bool; + entry_size: int; + entry_align: int; + value_offset: int; + value_size: int; } @@ -387,9 +387,9 @@ reserve :: proc(array: ^[dynamic]$T, capacity: int) -> bool { __get_map_header :: proc(m: ^map[$K]$V) -> __MapHeader #cc_contextless { header := __MapHeader{m = ^raw.DynamicMap(m)}; Entry :: struct { - key: __MapKey, - next: int, - value: V, + key: __MapKey; + next: int; + value: V; } _, is_string := type_info_base(type_info(K)).(^TypeInfo.String); diff --git a/core/_soft_numbers.odin b/core/_soft_numbers.odin index ed4bfc133..8f6751408 100644 --- a/core/_soft_numbers.odin +++ b/core/_soft_numbers.odin @@ -7,13 +7,13 @@ __multi3 :: proc(a, b: u128) -> u128 #cc_c #link_name "__multi3" { when ODIN_ENDIAN == "bit" { TWords :: raw_union { - all: u128, - using _: struct {lo, hi: u64}, + all: u128; + using _: struct {lo, hi: u64}; }; } else { TWords :: raw_union { - all: u128, - using _: struct {hi, lo: u64}, + all: u128; + using _: struct {hi, lo: u64}; }; } diff --git a/core/decimal.odin b/core/decimal.odin index c5ded337f..ba1489fe5 100644 --- a/core/decimal.odin +++ b/core/decimal.odin @@ -3,10 +3,10 @@ // NOTE: This is only for floating point printing and nothing else Decimal :: struct { - digits: [384]u8, // big-endian digits - count: int, - decimal_point: int, - neg, trunc: bool, + digits: [384]u8; // big-endian digits + count: int; + decimal_point: int; + neg, trunc: bool; } decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string { diff --git a/core/fmt.odin b/core/fmt.odin index 6ac4a552e..98406096f 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -10,27 +10,27 @@ import ( _BUFFER_SIZE :: 1<<12; StringBuffer :: union { - Static {buf: []u8}, - Dynamic{buf: [dynamic]u8}, + Static {buf: []u8}; + Dynamic{buf: [dynamic]u8}; } FmtInfo :: struct { - minus: bool, - plus: bool, - space: bool, - zero: bool, - hash: bool, - width_set: bool, - prec_set: bool, + minus: bool; + plus: bool; + space: bool; + zero: bool; + hash: bool; + width_set: bool; + prec_set: bool; - width: int, - prec: int, + width: int; + prec: int; - reordered: bool, - good_arg_index: bool, + reordered: bool; + good_arg_index: bool; - buf: ^StringBuffer, - arg: any, // Temporary + buf: ^StringBuffer; + arg: any; // Temporary } diff --git a/core/mem.odin b/core/mem.odin index 705f30401..10b92d5fc 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -68,7 +68,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr { AllocationHeader :: struct { - size: int, + size: int; } allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) { @@ -93,15 +93,15 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader { // Custom allocators Arena :: struct { - backing: Allocator, - offset: int, - memory: []u8, - temp_count: int, + backing: Allocator; + offset: int; + memory: []u8; + temp_count: int; } ArenaTempMemory :: struct { - arena: ^Arena, - original_count: int, + arena: ^Arena; + original_count: int; } diff --git a/core/os_linux.odin b/core/os_linux.odin index 33d85634f..ab65236e2 100644 --- a/core/os_linux.odin +++ b/core/os_linux.odin @@ -41,9 +41,9 @@ RTLD_GLOBAL :: 0x100; args := _alloc_command_line_arguments(); _FileTime :: struct #ordered { - seconds: i64, - nanoseconds: i32, - reserved: i32, + seconds: i64; + nanoseconds: i32; + reserved: i32; } // Translated from @@ -51,27 +51,27 @@ _FileTime :: struct #ordered { // Validity is not guaranteed. Stat :: struct #ordered { - device_id: u64, // ID of device containing file - serial: u64, // File serial number - nlink: u32, // Number of hard links - mode: u32, // Mode of the file - uid: u32, // User ID of the file's owner - gid: u32, // Group ID of the file's group - _padding: i32, // 32 bits of padding - rdev: u64, // Device ID, if device - size: i64, // Size of the file, in bytes - block_size: i64, // Optimal bllocksize for I/O - blocks: i64, // Number of 512-byte blocks allocated + device_id: u64; // ID of device containing file + serial: u64; // File serial number + nlink: u32; // Number of hard links + mode: u32; // Mode of the file + uid: u32; // User ID of the file's owner + gid: u32; // Group ID of the file's group + _padding: i32; // 32 bits of padding + rdev: u64; // Device ID, if device + size: i64; // Size of the file, in bytes + block_size: i64; // Optimal bllocksize for I/O + blocks: i64; // Number of 512-byte blocks allocated - last_access: _FileTime, // Time of last access - modified: _FileTime, // Time of last modification - status_change: _FileTime, // Time of last status change + last_access: _FileTime; // Time of last access + modified: _FileTime; // Time of last modification + status_change: _FileTime; // Time of last status change _reserve1, _reserve2, - _reserve3: i64, - serial_numbe: u64, // File serial number...? Maybe. - _reserve4: i64, + _reserve3: i64; + serial_numbe: u64; // File serial number...? Maybe. + _reserve4: i64; }; // File type diff --git a/core/os_x.odin b/core/os_x.odin index 4ac16aaec..4d5d90435 100644 --- a/core/os_x.odin +++ b/core/os_x.odin @@ -47,32 +47,32 @@ RTLD_FIRST :: 0x100; args: [dynamic]string; _FileTime :: struct #ordered { - seconds: i64, - nanoseconds: i64 + seconds: i64; + nanoseconds: i64; } Stat :: struct #ordered { - device_id : i32, // ID of device containing file - mode : u16, // Mode of the file - nlink : u16, // Number of hard links - serial : u64, // File serial number - uid : u32, // User ID of the file's owner - gid : u32, // Group ID of the file's group - rdev : i32, // Device ID, if device + device_id: i32; // ID of device containing file + mode: u16; // Mode of the file + nlink: u16; // Number of hard links + serial: u64; // File serial number + uid: u32; // User ID of the file's owner + gid: u32; // Group ID of the file's group + rdev: i32; // Device ID, if device - last_access : FileTime, // Time of last access - modified : FileTime, // Time of last modification - status_change : FileTime, // Time of last status change - created : FileTime, // Time of creation + last_access: FileTime; // Time of last access + modified: FileTime; // Time of last modification + status_change: FileTime; // Time of last status change + created: FileTime; // Time of creation - size : i64, // Size of the file, in bytes - blocks : i64, // Number of blocks allocated for the file - block_size: i32, // Optimal blocksize for I/O - flags : u32, // User-defined flags for the file - gen_num : u32, // File generation number ...? - _spare : i32, // RESERVED + size: i64; // Size of the file, in bytes + blocks: i64; // Number of blocks allocated for the file + block_size: i32; // Optimal blocksize for I/O + flags: u32; // User-defined flags for the file + gen_num: u32; // File generation number ...? + _spare: i32; // RESERVED _reserve1, - _reserve2 : i64, // RESERVED + _reserve2: i64; // RESERVED }; // File type diff --git a/core/raw.odin b/core/raw.odin index 433fde18f..b681cbf40 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -1,28 +1,28 @@ Any :: struct #ordered { - data: rawptr, - type_info: ^TypeInfo, + data: rawptr; + type_info: ^TypeInfo; }; String :: struct #ordered { - data: ^u8, - len: int, + data: ^u8; + len: int; }; Slice :: struct #ordered { - data: rawptr, - len: int, - cap: int, + data: rawptr; + len: int; + cap: int; }; DynamicArray :: struct #ordered { - data: rawptr, - len: int, - cap: int, - allocator: Allocator, + data: rawptr; + len: int; + cap: int; + allocator: Allocator; }; DynamicMap :: struct #ordered { - hashes: [dynamic]int, - entries: DynamicArray, + hashes: [dynamic]int; + entries: DynamicArray; }; diff --git a/core/strconv.odin b/core/strconv.odin index c4c5787a9..58924100e 100644 --- a/core/strconv.odin +++ b/core/strconv.odin @@ -211,27 +211,27 @@ append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string DecimalSlice :: struct { - digits: []u8, - count: int, - decimal_point: int, - neg: bool, + digits: []u8; + count: int; + decimal_point: int; + neg: bool; } -Float_Info :: struct { - mantbits: uint, - expbits: uint, - bias: int, +FloatInfo :: struct { + mantbits: uint; + expbits: uint; + bias: int; } -_f16_info := Float_Info{10, 5, -15}; -_f32_info := Float_Info{23, 8, -127}; -_f64_info := Float_Info{52, 11, -1023}; +_f16_info := FloatInfo{10, 5, -15}; +_f32_info := FloatInfo{23, 8, -127}; +_f64_info := FloatInfo{52, 11, -1023}; generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 { bits: u64; - flt: ^Float_Info; + flt: ^FloatInfo; match bit_size { case 32: bits = u64(transmute(u32, f32(val))); @@ -346,7 +346,7 @@ format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, return buf; } -round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) { +round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^FloatInfo) { if mant == 0 { // If mantissa is zero, the number is zero d.count = 0; return; diff --git a/core/sync_linux.odin b/core/sync_linux.odin index 5874c70f0..a6c1338da 100644 --- a/core/sync_linux.odin +++ b/core/sync_linux.odin @@ -4,14 +4,14 @@ import ( ) Semaphore :: struct { - // _handle: win32.Handle, + // _handle: win32.Handle; } Mutex :: struct { - _semaphore: Semaphore, - _counter: i32, - _owner: i32, - _recursion: i32, + _semaphore: Semaphore; + _counter: i32; + _owner: i32; + _recursion: i32; } current_thread_id :: proc() -> i32 { diff --git a/core/sync_windows.odin b/core/sync_windows.odin index 71728dd32..2035fc475 100644 --- a/core/sync_windows.odin +++ b/core/sync_windows.odin @@ -4,20 +4,20 @@ import ( ) Semaphore :: struct { - _handle: win32.Handle, + _handle: win32.Handle; } /* Mutex :: struct { - _semaphore: Semaphore, - _counter: i32, - _owner: i32, - _recursion: i32, + _semaphore: Semaphore; + _counter: i32; + _owner: i32; + _recursion: i32; } */ Mutex :: struct { - _critical_section: win32.CriticalSection, + _critical_section: win32.CriticalSection; } current_thread_id :: proc() -> i32 { diff --git a/core/sys/wgl.odin b/core/sys/wgl.odin index 10d36d18a..1185c4020 100644 --- a/core/sys/wgl.odin +++ b/core/sys/wgl.odin @@ -14,42 +14,40 @@ Hglrc :: Handle; ColorRef :: u32; LayerPlaneDescriptor :: struct { - size: u16, - version: u16, - flags: u32, - pixel_type: u8, - color_bits: u8, - red_bits: u8, - red_shift: u8, - green_bits: u8, - green_shift: u8, - blue_bits: u8, - blue_shift: u8, - alpha_bits: u8, - alpha_shift: u8, - accum_bits: u8, - accum_red_bits: u8, - accum_green_bits: u8, - accum_blue_bits: u8, - accum_alpha_bits: u8, - depth_bits: u8, - stencil_bits: u8, - aux_buffers: u8, - layer_type: u8, - reserved: u8, - transparent: ColorRef, + size: u16; + version: u16; + flags: u32; + pixel_type: u8; + color_bits: u8; + red_bits: u8; + red_shift: u8; + green_bits: u8; + green_shift: u8; + blue_bits: u8; + blue_shift: u8; + alpha_bits: u8; + alpha_shift: u8; + accum_bits: u8; + accum_red_bits: u8; + accum_green_bits: u8; + accum_blue_bits: u8; + accum_alpha_bits: u8; + depth_bits: u8; + stencil_bits: u8; + aux_buffers: u8; + layer_type: u8; + reserved: u8; + transparent: ColorRef; } -PointFloat :: struct { - x, y: f32, -} +PointFloat :: struct {x, y: f32}; Glyph_MetricsFloat :: struct { - black_box_x: f32, - black_box_y: f32, - glyph_origin: PointFloat, - cell_inc_x: f32, - cell_inc_y: f32, + black_box_x: f32; + black_box_y: f32; + glyph_origin: PointFloat; + cell_inc_x: f32; + cell_inc_y: f32; } CreateContextAttribsARBType :: proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc; diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 171215800..c274e46e5 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -27,86 +27,86 @@ FALSE: Bool : 0; TRUE: Bool : 1; Point :: struct #ordered { - x, y: i32, + x, y: i32; } WndClassExA :: struct #ordered { - size, style: u32, - wnd_proc: WndProc, - cls_extra, wnd_extra: i32, - instance: Hinstance, - icon: Hicon, - cursor: Hcursor, - background: Hbrush, - menu_name, class_name: ^u8, - sm: Hicon, + size, style: u32; + wnd_proc: WndProc; + cls_extra, wnd_extra: i32; + instance: Hinstance; + icon: Hicon; + cursor: Hcursor; + background: Hbrush; + menu_name, class_name: ^u8; + sm: Hicon; } Msg :: struct #ordered { - hwnd: Hwnd, - message: u32, - wparam: Wparam, - lparam: Lparam, - time: u32, - pt: Point, + hwnd: Hwnd; + message: u32; + wparam: Wparam; + lparam: Lparam; + time: u32; + pt: Point; } Rect :: struct #ordered { - left: i32, - top: i32, - right: i32, - bottom: i32, + left: i32; + top: i32; + right: i32; + bottom: i32; } Filetime :: struct #ordered { - lo, hi: u32, + lo, hi: u32; } Systemtime :: struct #ordered { - year, month: u16, - day_of_week, day: u16, - hour, minute, second, millisecond: u16, + year, month: u16; + day_of_week, day: u16; + hour, minute, second, millisecond: u16; } ByHandleFileInformation :: struct #ordered { - file_attributes: u32, + file_attributes: u32; creation_time, last_access_time, - last_write_time: Filetime, + last_write_time: Filetime; volume_serial_number, file_size_high, file_size_low, number_of_links, file_index_high, - file_index_low: u32, + file_index_low: u32; } FileAttributeData :: struct #ordered { - file_attributes: u32, + file_attributes: u32; creation_time, last_access_time, - last_write_time: Filetime, + last_write_time: Filetime; file_size_high, - file_size_low: u32, + file_size_low: u32; } FindData :: struct #ordered { - file_attributes: u32, - creation_time: Filetime, - last_access_time: Filetime, - last_write_time: Filetime, - file_size_high: u32, - file_size_low: u32, - reserved0: u32, - reserved1: u32, - file_name: [MAX_PATH]u8, - alternate_file_name: [14]u8, + file_attributes: u32; + creation_time: Filetime; + last_access_time: Filetime; + last_write_time: Filetime; + file_size_high: u32; + file_size_low: u32; + reserved0: u32; + reserved1: u32; + file_name: [MAX_PATH]u8; + alternate_file_name: [14]u8; } SecurityAttributes :: struct #ordered { - length: u32, - security_descriptor: rawptr, - inherit_handle: Bool, + length: u32; + security_descriptor: rawptr; + inherit_handle: Bool; } @@ -114,7 +114,7 @@ SecurityAttributes :: struct #ordered { PixelFormatDescriptor :: struct #ordered { size, version, - flags: u32, + flags: u32; pixel_type, color_bits, @@ -135,33 +135,33 @@ PixelFormatDescriptor :: struct #ordered { stencil_bits, aux_buffers, layer_type, - reserved: u8, + reserved: u8; layer_mask, visible_mask, - damage_mask: u32, + damage_mask: u32; } CriticalSection :: struct #ordered { - debug_info: ^CriticalSectionDebug, + debug_info: ^CriticalSectionDebug; - lock_count: i32, - recursion_count: i32, - owning_thread: Handle, - lock_semaphore: Handle, - spin_count: ^u32, + lock_count: i32; + recursion_count: i32; + owning_thread: Handle; + lock_semaphore: Handle; + spin_count: ^u32; } CriticalSectionDebug :: struct #ordered { - typ: u16, - creator_back_trace_index: u16, - critical_section: ^CriticalSection, - process_locks_list: ^ListEntry, - entry_count: u32, - contention_count: u32, - flags: u32, - creator_back_trace_index_high: u16, - spare_word: u16, + typ: u16; + creator_back_trace_index: u16; + critical_section: ^CriticalSection; + process_locks_list: ^ListEntry; + entry_count: u32; + contention_count: u32; + flags: u32; + creator_back_trace_index_high: u16; + spare_word: u16; } ListEntry :: struct #ordered {flink, blink: ^ListEntry}; @@ -546,35 +546,35 @@ FILE_TYPE_PIPE :: 0x0003; MonitorInfo :: struct #ordered { - size: u32, - monitor: Rect, - work: Rect, - flags: u32, + size: u32; + monitor: Rect; + work: Rect; + flags: u32; } WindowPlacement :: struct #ordered { - length: u32, - flags: u32, - show_cmd: u32, - min_pos: Point, - max_pos: Point, - normal_pos: Rect, + length: u32; + flags: u32; + show_cmd: u32; + min_pos: Point; + max_pos: Point; + normal_pos: Rect; } BitmapInfoHeader :: struct #ordered { - size: u32, - width, height: i32, - planes, bit_count: i16, - compression: u32, - size_image: u32, - x_pels_per_meter: i32, - y_pels_per_meter: i32, - clr_used: u32, - clr_important: u32, + size: u32; + width, height: i32; + planes, bit_count: i16; + compression: u32; + size_image: u32; + x_pels_per_meter: i32; + y_pels_per_meter: i32; + clr_used: u32; + clr_important: u32; } BitmapInfo :: struct #ordered { - using header: BitmapInfoHeader, - colors: [1]RgbQuad, + using header: BitmapInfoHeader; + colors: [1]RgbQuad; } diff --git a/src/parser.cpp b/src/parser.cpp index c2286e25b..a40f8266e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3354,6 +3354,123 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) { return false; } +bool parse_expect_struct_separator(AstFile *f, AstNode *param) { + Token token = f->curr_token; + if (allow_token(f, Token_Semicolon)) { + return true; + } + + if (token.kind == Token_Colon) { + next_token(f); + error(f->curr_token, "Expected a semicolon, got a comma"); + return true; + } + + if (token.kind == Token_CloseBrace) { + if (token.pos.line == f->prev_token.pos.line) { + return true; + } + } + expect_token_after(f, Token_Semicolon, "field list"); + + return false; +} + + +AstNode *parse_struct_field_list(AstFile *f, isize *name_count_) { + CommentGroup docs = f->lead_comment; + Token start_token = f->curr_token; + + Array params = make_ast_node_array(f); + Array list = {}; array_init(&list, heap_allocator()); + defer (array_free(&list)); + + isize total_name_count = 0; + + while (f->curr_token.kind != Token_CloseBrace && + f->curr_token.kind != Token_Colon && + f->curr_token.kind != Token_EOF) { + u32 flags = parse_field_prefixes(f); + AstNode *param = parse_var_type(f, false, false); + AstNodeAndFlags naf = {param, flags}; + array_add(&list, naf); + if (f->curr_token.kind != Token_Comma) { + break; + } + next_token(f); + } + + if (f->curr_token.kind == Token_Colon) { + Array names = convert_to_ident_list(f, list, true); // Copy for semantic reasons + if (names.count == 0) { + syntax_error(f->curr_token, "Empty field declaration"); + } + u32 set_flags = 0; + if (list.count > 0) { + set_flags = list[0].flags; + } + set_flags = check_field_prefixes(f, names.count, FieldFlag_using, set_flags); + total_name_count += names.count; + + AstNode *type = nullptr; + + expect_token_after(f, Token_Colon, "field list"); + type = parse_var_type(f, false, false); + + parse_expect_struct_separator(f, type); + AstNode *param = ast_field(f, names, type, nullptr, set_flags, docs, f->line_comment); + array_add(¶ms, param); + + + while (f->curr_token.kind != Token_CloseBrace && + f->curr_token.kind != Token_EOF) { + CommentGroup docs = f->lead_comment; + + u32 set_flags = parse_field_prefixes(f); + Array names = parse_ident_list(f); + if (names.count == 0) { + syntax_error(f->curr_token, "Empty field declaration"); + break; + } + set_flags = check_field_prefixes(f, names.count, FieldFlag_using, set_flags); + total_name_count += names.count; + + AstNode *type = nullptr; + + expect_token_after(f, Token_Colon, "field list"); + type = parse_var_type(f, false, false); + + bool ok = parse_expect_struct_separator(f, param); + AstNode *param = ast_field(f, names, type, nullptr, set_flags, docs, f->line_comment); + array_add(¶ms, param); + + if (!ok) { + break; + } + } + + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); + } + + for_array(i, list) { + Array names = {}; + AstNode *type = list[i].node; + Token token = blank_token; + + array_init_count(&names, heap_allocator(), 1); + token.pos = ast_node_token(type).pos; + names[0] = ast_ident(f, token); + u32 flags = check_field_prefixes(f, list.count, FieldFlag_using, list[i].flags); + + AstNode *param = ast_field(f, names, list[i].node, nullptr, flags, docs, f->line_comment); + array_add(¶ms, param); + } + + if (name_count_) *name_count_ = total_name_count; + return ast_field_list(f, start_token, params); +} + AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters) { TokenKind separator = Token_Comma; Token start_token = f->curr_token; @@ -3629,9 +3746,10 @@ AstNode *parse_type_or_ident(AstFile *f) { } Token open = expect_token_after(f, Token_OpenBrace, "struct"); - isize decl_count = 0; - AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct")); - Token close = expect_token(f, Token_CloseBrace); + + isize name_count = 0; + AstNode *fields = parse_struct_field_list(f, &name_count); + Token close = expect_token(f, Token_CloseBrace); Array decls = {}; if (fields != nullptr) { @@ -3639,7 +3757,7 @@ AstNode *parse_type_or_ident(AstFile *f) { decls = fields->FieldList.list; } - return ast_struct_type(f, token, decls, decl_count, is_packed, is_ordered, align); + return ast_struct_type(f, token, decls, name_count, is_packed, is_ordered, align); } break; case Token_union: { @@ -3678,16 +3796,16 @@ AstNode *parse_type_or_ident(AstFile *f) { AstNode *name = names[0]; Token open = expect_token(f, Token_OpenBrace); isize decl_count = 0; - AstNode *list = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("union")); + AstNode *list = parse_struct_field_list(f, &decl_count); + // AstNode *list = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("union")); Token close = expect_token(f, Token_CloseBrace); array_add(&variants, ast_union_field(f, name, list)); } } - if (f->curr_token.kind != Token_Comma) { + if (!parse_expect_struct_separator(f, nullptr)) { break; } - next_token(f); } Token close = expect_token(f, Token_CloseBrace); @@ -3699,9 +3817,10 @@ AstNode *parse_type_or_ident(AstFile *f) { case Token_raw_union: { Token token = expect_token(f, Token_raw_union); Token open = expect_token_after(f, Token_OpenBrace, "raw_union"); - isize decl_count = 0; - AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("raw_union")); - Token close = expect_token(f, Token_CloseBrace); + + isize decl_count = 0; + AstNode *fields = parse_struct_field_list(f, &decl_count); + Token close = expect_token(f, Token_CloseBrace); Array decls = {}; if (fields != nullptr) {