diff --git a/code/demo.odin b/code/demo.odin index 141788416..9a16c56c2 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,15 +1,13 @@ -import { - "atomic.odin"; - "fmt.odin"; - "hash.odin"; - "math.odin"; - "mem.odin"; - "opengl.odin"; - "os.odin"; - "sync.odin"; - "utf8.odin"; - win32 "sys/windows.odin"; -} +import "atomic.odin"; +import "fmt.odin"; +import "hash.odin"; +import "math.odin"; +import "mem.odin"; +import "opengl.odin"; +import "os.odin"; +import "sync.odin"; +import "utf8.odin"; +import win32 "sys/windows.odin"; Thing :: enum f64 { _, // Ignore first value diff --git a/core/_preload.odin b/core/_preload.odin index c8fb77009..78de6d2e0 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -12,74 +12,72 @@ import "mem.odin"; // IMPORTANT NOTE(bill): Do not change the order of any of this data // The compiler relies upon this _exact_ order -type { - Type_Info_Member struct #ordered { - name string; // can be empty if tuple - type_info ^Type_Info; - offset int; // offsets are not used in tuples - } - Type_Info_Record struct #ordered { - fields []Type_Info_Member; - size int; // in bytes - align int; // in bytes - packed bool; - ordered bool; - } - - Type_Info union { - Named struct #ordered { - name string; - base ^Type_Info; // This will _not_ be a Type_Info.Named - }; - Integer struct #ordered { - size int; // in bytes - signed bool; - }; - Float struct #ordered { - size int; // in bytes - }; - Any struct #ordered {}; - String struct #ordered {}; - Boolean struct #ordered {}; - Pointer struct #ordered { - elem ^Type_Info; // nil -> rawptr - }; - Maybe struct #ordered { - elem ^Type_Info; - }; - Procedure struct #ordered { - params ^Type_Info; // Type_Info.Tuple - results ^Type_Info; // Type_Info.Tuple - variadic bool; - }; - Array struct #ordered { - elem ^Type_Info; - elem_size int; - count int; - }; - Slice struct #ordered { - elem ^Type_Info; - elem_size int; - }; - Vector struct #ordered { - elem ^Type_Info; - elem_size int; - count int; - align int; - }; - Tuple Type_Info_Record; - Struct Type_Info_Record; - Union Type_Info_Record; - Raw_Union Type_Info_Record; - Enum struct #ordered { - base ^Type_Info; - names []string; - // TODO(bill): store values some how. Maybe using a raw_union - }; - } +Type_Info_Member :: struct #ordered { + name string; // can be empty if tuple + type_info ^Type_Info; + offset int; // offsets are not used in tuples +} +Type_Info_Record :: struct #ordered { + fields []Type_Info_Member; + size int; // in bytes + align int; // in bytes + packed bool; + ordered bool; } -proc type_info_base(info ^Type_Info) -> ^Type_Info { +Type_Info :: union { + Named struct #ordered { + name string; + base ^Type_Info; // This will _not_ be a Type_Info.Named + }; + Integer struct #ordered { + size int; // in bytes + signed bool; + }; + Float struct #ordered { + size int; // in bytes + }; + Any struct #ordered {}; + String struct #ordered {}; + Boolean struct #ordered {}; + Pointer struct #ordered { + elem ^Type_Info; // nil -> rawptr + }; + Maybe struct #ordered { + elem ^Type_Info; + }; + Procedure struct #ordered { + params ^Type_Info; // Type_Info.Tuple + results ^Type_Info; // Type_Info.Tuple + variadic bool; + }; + Array struct #ordered { + elem ^Type_Info; + elem_size int; + count int; + }; + Slice struct #ordered { + elem ^Type_Info; + elem_size int; + }; + Vector struct #ordered { + elem ^Type_Info; + elem_size int; + count int; + align int; + }; + Tuple Type_Info_Record; + Struct Type_Info_Record; + Union Type_Info_Record; + Raw_Union Type_Info_Record; + Enum struct #ordered { + base ^Type_Info; + names []string; + // TODO(bill): store values some how. Maybe using a raw_union + }; +} + +type_info_base :: proc(info ^Type_Info) -> ^Type_Info { if info == nil { return nil; } @@ -93,51 +91,49 @@ proc type_info_base(info ^Type_Info) -> ^Type_Info { -proc assume(cond bool) #foreign "llvm.assume" +assume :: proc(cond bool) #foreign "llvm.assume" -proc __debug_trap () #foreign "llvm.debugtrap" -proc __trap () #foreign "llvm.trap" -proc read_cycle_counter() -> u64 #foreign "llvm.readcyclecounter" +__debug_trap :: proc() #foreign "llvm.debugtrap" +__trap :: proc() #foreign "llvm.trap" +read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter" -proc bit_reverse16(b u16) -> u16 #foreign "llvm.bitreverse.i16" -proc bit_reverse32(b u32) -> u32 #foreign "llvm.bitreverse.i32" -proc bit_reverse64(b u64) -> u64 #foreign "llvm.bitreverse.i64" +bit_reverse16 :: proc(b u16) -> u16 #foreign "llvm.bitreverse.i16" +bit_reverse32 :: proc(b u32) -> u32 #foreign "llvm.bitreverse.i32" +bit_reverse64 :: proc(b u64) -> u64 #foreign "llvm.bitreverse.i64" -proc byte_swap16(b u16) -> u16 #foreign "llvm.bswap.i16" -proc byte_swap32(b u32) -> u32 #foreign "llvm.bswap.i32" -proc byte_swap64(b u64) -> u64 #foreign "llvm.bswap.i64" +byte_swap16 :: proc(b u16) -> u16 #foreign "llvm.bswap.i16" +byte_swap32 :: proc(b u32) -> u32 #foreign "llvm.bswap.i32" +byte_swap64 :: proc(b u64) -> u64 #foreign "llvm.bswap.i64" -proc fmuladd32(a, b, c f32) -> f32 #foreign "llvm.fmuladd.f32" -proc fmuladd64(a, b, c f64) -> f64 #foreign "llvm.fmuladd.f64" +fmuladd32 :: proc(a, b, c f32) -> f32 #foreign "llvm.fmuladd.f32" +fmuladd64 :: proc(a, b, c f64) -> f64 #foreign "llvm.fmuladd.f64" -type Allocator_Mode enum u8 { +Allocator_Mode :: enum u8 { ALLOC = iota, FREE, FREE_ALL, RESIZE, } -type { - Allocator_Proc proc(allocator_data rawptr, mode Allocator_Mode, - size, alignment int, - old_memory rawptr, old_size int, flags u64) -> rawptr; - Allocator struct #ordered { - procedure Allocator_Proc; - data rawptr; - } +Allocator_Proc :: type proc(allocator_data rawptr, mode Allocator_Mode, + size, alignment int, + old_memory rawptr, old_size int, flags u64) -> rawptr; +Allocator :: struct #ordered { + procedure Allocator_Proc; + data rawptr; +} - Context struct #ordered { - thread_id int; +Context :: struct #ordered { + thread_id int; - allocator Allocator; + allocator Allocator; - user_data rawptr; - user_index int; - } + user_data rawptr; + user_index int; } #thread_local __context: Context; @@ -146,7 +142,7 @@ type { DEFAULT_ALIGNMENT :: align_of([vector 4]f32); -proc __check_context() { +__check_context:: proc() { c := ^__context; if c.allocator.procedure == nil { @@ -157,30 +153,30 @@ proc __check_context() { } } -proc alloc(size int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); } +alloc:: proc(size int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); } -proc alloc_align(size, alignment int) -> rawptr #inline { +alloc_align:: proc(size, alignment int) -> rawptr #inline { __check_context(); a := context.allocator; return a.procedure(a.data, Allocator_Mode.ALLOC, size, alignment, nil, 0, 0); } -proc free(ptr rawptr) #inline { +free:: proc(ptr rawptr) #inline { __check_context(); a := context.allocator; if ptr != nil { a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0); } } -proc free_all() #inline { +free_all:: proc() #inline { __check_context(); a := context.allocator; a.procedure(a.data, Allocator_Mode.FREE_ALL, 0, 0, nil, 0, 0); } -proc resize (ptr rawptr, old_size, new_size int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); } -proc resize_align(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inline { +resize:: proc (ptr rawptr, old_size, new_size int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); } +resize_align:: proc(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inline { __check_context(); a := context.allocator; return a.procedure(a.data, Allocator_Mode.RESIZE, new_size, alignment, ptr, old_size, 0); @@ -188,7 +184,7 @@ proc resize_align(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inli -proc default_resize_align(old_memory rawptr, old_size, new_size, alignment int) -> rawptr { +default_resize_align:: proc(old_memory rawptr, old_size, new_size, alignment int) -> rawptr { if old_memory == nil { return alloc_align(new_size, alignment); } @@ -213,7 +209,7 @@ proc default_resize_align(old_memory rawptr, old_size, new_size, alignment int) } -proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode, +default_allocator_proc:: proc(allocator_data rawptr, mode Allocator_Mode, size, alignment int, old_memory rawptr, old_size int, flags u64) -> rawptr { using Allocator_Mode; @@ -263,7 +259,7 @@ proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode, return nil; } -proc default_allocator() -> Allocator { +default_allocator:: proc() -> Allocator { return Allocator{ procedure = default_allocator_proc, data = nil, @@ -280,7 +276,7 @@ proc default_allocator() -> Allocator { -proc __string_eq(a, b string) -> bool { +__string_eq:: proc(a, b string) -> bool { if a.count != b.count { return false; } @@ -290,24 +286,24 @@ proc __string_eq(a, b string) -> bool { return mem.compare(a.data, b.data, a.count) == 0; } -proc __string_cmp(a, b string) -> int { +__string_cmp:: proc(a, b string) -> int { return mem.compare(a.data, b.data, min(a.count, b.count)); } -proc __string_ne(a, b string) -> bool #inline { return !__string_eq(a, b); } -proc __string_lt(a, b string) -> bool #inline { return __string_cmp(a, b) < 0; } -proc __string_gt(a, b string) -> bool #inline { return __string_cmp(a, b) > 0; } -proc __string_le(a, b string) -> bool #inline { return __string_cmp(a, b) <= 0; } -proc __string_ge(a, b string) -> bool #inline { return __string_cmp(a, b) >= 0; } +__string_ne:: proc(a, b string) -> bool #inline { return !__string_eq(a, b); } +__string_lt:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) < 0; } +__string_gt:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) > 0; } +__string_le:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) <= 0; } +__string_ge:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) >= 0; } -proc __assert(file string, line, column int, msg string) #inline { +__assert:: proc(file string, line, column int, msg string) #inline { fmt.fprintf(os.stderr, "%(%:%) Runtime assertion: %\n", file, line, column, msg); __debug_trap(); } -proc __bounds_check_error(file string, line, column int, index, count int) { +__bounds_check_error:: proc(file string, line, column int, index, count int) { if 0 <= index && index < count { return; } @@ -316,7 +312,7 @@ proc __bounds_check_error(file string, line, column int, index, count int) { __debug_trap(); } -proc __slice_expr_error(file string, line, column int, low, high, max int) { +__slice_expr_error:: proc(file string, line, column int, low, high, max int) { if 0 <= low && low <= high && high <= max { return; } @@ -324,7 +320,7 @@ proc __slice_expr_error(file string, line, column int, low, high, max int) { file, line, column, low, high, max); __debug_trap(); } -proc __substring_expr_error(file string, line, column int, low, high int) { +__substring_expr_error:: proc(file string, line, column int, low, high int) { if 0 <= low && low <= high { return; } diff --git a/core/atomic.odin b/core/atomic.odin index 08fb48795..5fa50a649 100644 --- a/core/atomic.odin +++ b/core/atomic.odin @@ -5,36 +5,36 @@ import win32 "sys/windows.odin" when ODIN_OS == "windows"; _ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version -proc yield_thread() { win32._mm_pause(); } -proc mfence () { win32.ReadWriteBarrier(); } -proc sfence () { win32.WriteBarrier(); } -proc lfence () { win32.ReadBarrier(); } +yield_thread :: proc() { win32._mm_pause(); } +mfence :: proc() { win32.ReadWriteBarrier(); } +sfence :: proc() { win32.WriteBarrier(); } +lfence :: proc() { win32.ReadBarrier(); } -proc load32(a ^i32) -> i32 { +load32 :: proc(a ^i32) -> i32 { return a^; } -proc store32(a ^i32, value i32) { +store32 :: proc(a ^i32, value i32) { a^ = value; } -proc compare_exchange32(a ^i32, expected, desired i32) -> i32 { +compare_exchange32 :: proc(a ^i32, expected, desired i32) -> i32 { return win32.InterlockedCompareExchange(a, desired, expected); } -proc exchanged32(a ^i32, desired i32) -> i32 { +exchanged32 :: proc(a ^i32, desired i32) -> i32 { return win32.InterlockedExchange(a, desired); } -proc fetch_add32(a ^i32, operand i32) -> i32 { +fetch_add32 :: proc(a ^i32, operand i32) -> i32 { return win32.InterlockedExchangeAdd(a, operand); } -proc fetch_and32(a ^i32, operand i32) -> i32 { +fetch_and32 :: proc(a ^i32, operand i32) -> i32 { return win32.InterlockedAnd(a, operand); } -proc fetch_or32(a ^i32, operand i32) -> i32 { +fetch_or32 :: proc(a ^i32, operand i32) -> i32 { return win32.InterlockedOr(a, operand); } -proc spin_lock32(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1 as default +spin_lock32 :: proc(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1 as default old_value := compare_exchange32(a, 1, 0); counter := 0; for old_value != 0 && (time_out < 0 || counter < time_out) { @@ -45,11 +45,11 @@ proc spin_lock32(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1 as } return old_value == 0; } -proc spin_unlock32(a ^i32) { +spin_unlock32 :: proc(a ^i32) { store32(a, 0); mfence(); } -proc try_acquire_lock32(a ^i32) -> bool { +try_acquire_lock32 :: proc(a ^i32) -> bool { yield_thread(); old_value := compare_exchange32(a, 1, 0); mfence(); @@ -57,28 +57,28 @@ proc try_acquire_lock32(a ^i32) -> bool { } -proc load64(a ^i64) -> i64 { +load64 :: proc(a ^i64) -> i64 { return a^; } -proc store64(a ^i64, value i64) { +store64 :: proc(a ^i64, value i64) { a^ = value; } -proc compare_exchange64(a ^i64, expected, desired i64) -> i64 { +compare_exchange64 :: proc(a ^i64, expected, desired i64) -> i64 { return win32.InterlockedCompareExchange64(a, desired, expected); } -proc exchanged64(a ^i64, desired i64) -> i64 { +exchanged64 :: proc(a ^i64, desired i64) -> i64 { return win32.InterlockedExchange64(a, desired); } -proc fetch_add64(a ^i64, operand i64) -> i64 { +fetch_add64 :: proc(a ^i64, operand i64) -> i64 { return win32.InterlockedExchangeAdd64(a, operand); } -proc fetch_and64(a ^i64, operand i64) -> i64 { +fetch_and64 :: proc(a ^i64, operand i64) -> i64 { return win32.InterlockedAnd64(a, operand); } -proc fetch_or64(a ^i64, operand i64) -> i64 { +fetch_or64 :: proc(a ^i64, operand i64) -> i64 { return win32.InterlockedOr64(a, operand); } -proc spin_lock64(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1 as default +spin_lock64 :: proc(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1 as default old_value := compare_exchange64(a, 1, 0); counter := 0; for old_value != 0 && (time_out < 0 || counter < time_out) { @@ -89,11 +89,11 @@ proc spin_lock64(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1 as } return old_value == 0; } -proc spin_unlock64(a ^i64) { +spin_unlock64 :: proc(a ^i64) { store64(a, 0); mfence(); } -proc try_acquire_lock64(a ^i64) -> bool { +try_acquire_lock64 :: proc(a ^i64) -> bool { yield_thread(); old_value := compare_exchange64(a, 1, 0); mfence(); diff --git a/core/fmt.odin b/core/fmt.odin index 5e3db4235..11afcf889 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -6,23 +6,23 @@ import { PRINT_BUF_SIZE :: 1<<12; -proc fprint(fd os.Handle, args ..any) -> int { - data :[PRINT_BUF_SIZE]byte; +fprint :: proc(fd os.Handle, args ..any) -> int { + data: [PRINT_BUF_SIZE]byte; buf := data[:0]; bprint(^buf, ..args); os.write(fd, buf); return buf.count; } -proc fprintln(fd os.Handle, args ..any) -> int { - data :[PRINT_BUF_SIZE]byte; +fprintln :: proc(fd os.Handle, args ..any) -> int { + data: [PRINT_BUF_SIZE]byte; buf := data[:0]; bprintln(^buf, ..args); os.write(fd, buf); return buf.count; } -proc fprintf(fd os.Handle, fmt string, args ..any) -> int { - data :[PRINT_BUF_SIZE]byte; +fprintf :: proc(fd os.Handle, fmt string, args ..any) -> int { + data: [PRINT_BUF_SIZE]byte; buf := data[:0]; bprintf(^buf, fmt, ..args); os.write(fd, buf); @@ -30,20 +30,20 @@ proc fprintf(fd os.Handle, fmt string, args ..any) -> int { } -proc print(args ..any) -> int { +print :: proc(args ..any) -> int { return fprint(os.stdout, ..args); } -proc println(args ..any) -> int { +println :: proc(args ..any) -> int { return fprintln(os.stdout, ..args); } -proc printf(fmt string, args ..any) -> int { +printf :: proc(fmt string, args ..any) -> int { return fprintf(os.stdout, fmt, ..args); } -proc fprint_type(fd os.Handle, info ^Type_Info) { - data :[PRINT_BUF_SIZE]byte; +fprint_type :: proc(fd os.Handle, info ^Type_Info) { + data: [PRINT_BUF_SIZE]byte; buf := data[:0]; bprint_type(^buf, info); os.write(fd, buf); @@ -51,7 +51,7 @@ proc fprint_type(fd os.Handle, info ^Type_Info) { -proc print_byte_buffer(buf ^[]byte, b []byte) { +print_byte_buffer :: proc(buf ^[]byte, b []byte) { if buf.count < buf.capacity { n := min(buf.capacity-buf.count, b.count); if n > 0 { @@ -61,29 +61,29 @@ proc print_byte_buffer(buf ^[]byte, b []byte) { } } -proc bprint_string(buf ^[]byte, s string) { +bprint_string :: proc(buf ^[]byte, s string) { print_byte_buffer(buf, s as []byte); } -proc byte_reverse(b []byte) { +byte_reverse :: proc(b []byte) { n := b.count; for i := 0; i < n/2; i++ { b[i], b[n-1-i] = b[n-1-i], b[i]; } } -proc bprint_rune(buf ^[]byte, r rune) { +bprint_rune :: proc(buf ^[]byte, r rune) { b, n := utf8.encode_rune(r); bprint_string(buf, b[:n] as string); } -proc bprint_space(buf ^[]byte) { bprint_rune(buf, ' '); } -proc bprint_nl (buf ^[]byte) { bprint_rune(buf, '\n'); } +bprint_space :: proc(buf ^[]byte) { bprint_rune(buf, ' '); } +bprint_nl :: proc (buf ^[]byte) { bprint_rune(buf, '\n'); } __NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"; -proc bprint_bool(buffer ^[]byte, b bool) { +bprint_bool :: proc(buffer ^[]byte, b bool) { if b { bprint_string(buffer, "true"); } else { @@ -91,15 +91,15 @@ proc bprint_bool(buffer ^[]byte, b bool) { } } -proc bprint_pointer(buffer ^[]byte, p rawptr) #inline { +bprint_pointer :: proc(buffer ^[]byte, p rawptr) #inline { bprint_string(buffer, "0x"); bprint_u64(buffer, p as uint as u64); } -proc bprint_f16 (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 4); } -proc bprint_f32 (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 7); } -proc bprint_f64 (buffer ^[]byte, f f64) #inline { print__f64(buffer, f as f64, 16); } -proc bprint_u64(buffer ^[]byte, value u64) { +bprint_f16 :: proc (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 4); } +bprint_f32 :: proc (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 7); } +bprint_f64 :: proc (buffer ^[]byte, f f64) #inline { print__f64(buffer, f as f64, 16); } +bprint_u64 :: proc(buffer ^[]byte, value u64) { i := value; buf :[20]byte; len := 0; @@ -115,7 +115,7 @@ proc bprint_u64(buffer ^[]byte, value u64) { byte_reverse(buf[:len]); bprint_string(buffer, buf[:len] as string); } -proc bprint_i64(buffer ^[]byte, value i64) { +bprint_i64 :: proc(buffer ^[]byte, value i64) { // TODO(bill): Cleanup printing i := value; if i < 0 { @@ -126,14 +126,14 @@ proc bprint_i64(buffer ^[]byte, value i64) { } /* -proc bprint_u128(buffer ^[]byte, value u128) { +bprint_u128 :: proc(buffer ^[]byte, value u128) { a := value transmute [2]u64; if a[1] != 0 { bprint_u64(buffer, a[1]); } bprint_u64(buffer, a[0]); } -proc bprint_i128(buffer ^[]byte, value i128) { +bprint_i128 :: proc(buffer ^[]byte, value i128) { i := value; if i < 0 { i = -i; @@ -144,7 +144,7 @@ proc bprint_i128(buffer ^[]byte, value i128) { */ -proc print__f64(buffer ^[]byte, value f64, decimal_places int) { +print__f64 :: proc(buffer ^[]byte, value f64, decimal_places int) { f := value; if f == 0 { bprint_rune(buffer, '0'); @@ -170,7 +170,7 @@ proc print__f64(buffer ^[]byte, value f64, decimal_places int) { } } -proc bprint_type(buf ^[]byte, ti ^Type_Info) { +bprint_type :: proc(buf ^[]byte, ti ^Type_Info) { if ti == nil { return; } @@ -302,14 +302,14 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) { } -proc make_any(type_info ^Type_Info, data rawptr) -> any { +make_any :: proc(type_info ^Type_Info, data rawptr) -> any { a :any; a.type_info = type_info; a.data = data; return a; } -proc bprint_any(buf ^[]byte, arg any) { +bprint_any :: proc(buf ^[]byte, arg any) { if arg.type_info == nil { bprint_string(buf, ""); return; @@ -423,7 +423,7 @@ proc bprint_any(buf ^[]byte, arg any) { } case Vector: - proc is_bool(type_info ^Type_Info) -> bool { + is_bool :: proc(type_info ^Type_Info) -> bool { match type info : type_info { case Named: return is_bool(info.base); @@ -481,12 +481,12 @@ proc bprint_any(buf ^[]byte, arg any) { } -proc bprintf(buf ^[]byte, fmt string, args ..any) -> int { - proc is_digit(r rune) -> bool #inline { +bprintf :: proc(buf ^[]byte, fmt string, args ..any) -> int { + is_digit :: proc(r rune) -> bool #inline { return '0' <= r && r <= '9'; } - proc parse_int(s string, offset int) -> (int, int) { + parse_int :: proc(s string, offset int) -> (int, int) { result := 0; for ; offset < s.count; offset++ { @@ -546,8 +546,8 @@ proc bprintf(buf ^[]byte, fmt string, args ..any) -> int { } -proc bprint(buf ^[]byte, args ..any) -> int { - proc is_type_string(info ^Type_Info) -> bool { +bprint :: proc(buf ^[]byte, args ..any) -> int { + is_type_string :: proc(info ^Type_Info) -> bool { using Type_Info; if info == nil { return false; @@ -574,7 +574,7 @@ proc bprint(buf ^[]byte, args ..any) -> int { return buf.count; } -proc bprintln(buf ^[]byte, args ..any) -> int { +bprintln :: proc(buf ^[]byte, args ..any) -> int { for i := 0; i < args.count; i++ { if i > 0 { append(buf, ' '); diff --git a/core/hash.odin b/core/hash.odin index 8ef10f7df..dd579b89d 100644 --- a/core/hash.odin +++ b/core/hash.odin @@ -1,4 +1,4 @@ -proc crc32(data rawptr, len int) -> u32 { +crc32 :: proc(data rawptr, len int) -> u32 { result := ~(0 as u32); s := slice_ptr(data as ^u8, len); for i := 0; i < len; i++ { @@ -7,7 +7,7 @@ proc crc32(data rawptr, len int) -> u32 { } return ~result; } -proc crc64(data rawptr, len int) -> u64 { +crc64 :: proc(data rawptr, len int) -> u64 { result := ~(0 as u64); s := slice_ptr(data as ^u8, len); for i := 0; i < len; i++ { @@ -17,7 +17,7 @@ proc crc64(data rawptr, len int) -> u64 { return ~result; } -proc fnv32(data rawptr, len int) -> u32 { +fnv32 :: proc(data rawptr, len int) -> u32 { s := slice_ptr(data as ^u8, len); h :u32 = 0x811c9dc5; @@ -27,7 +27,7 @@ proc fnv32(data rawptr, len int) -> u32 { return h; } -proc fnv64(data rawptr, len int) -> u64 { +fnv64 :: proc(data rawptr, len int) -> u64 { s := slice_ptr(data as ^u8, len); h :u64 = 0xcbf29ce484222325; @@ -37,7 +37,7 @@ proc fnv64(data rawptr, len int) -> u64 { return h; } -proc fnv32a(data rawptr, len int) -> u32 { +fnv32a :: proc(data rawptr, len int) -> u32 { s := slice_ptr(data as ^u8, len); h :u32 = 0x811c9dc5; @@ -47,7 +47,7 @@ proc fnv32a(data rawptr, len int) -> u32 { return h; } -proc fnv64a(data rawptr, len int) -> u64 { +fnv64a :: proc(data rawptr, len int) -> u64 { s := slice_ptr(data as ^u8, len); h :u64 = 0xcbf29ce484222325; @@ -58,7 +58,7 @@ proc fnv64a(data rawptr, len int) -> u64 { } -proc murmur64(data_ rawptr, len int) -> u64 { +murmur64 :: proc(data_ rawptr, len int) -> u64 { SEED :: 0x9747b28c; when size_of(int) == 8 { diff --git a/core/math.odin b/core/math.odin index d0efe6444..2ff9340e9 100644 --- a/core/math.odin +++ b/core/math.odin @@ -16,67 +16,65 @@ EPSILON :: 1.19209290e-7; τ :: TAU; π :: PI; -type { - Vec2 [vector 2]f32; - Vec3 [vector 3]f32; - Vec4 [vector 4]f32; +Vec2 :: [vector 2]f32; +Vec3 :: [vector 3]f32; +Vec4 :: [vector 4]f32; - Mat2 [2]Vec2; - Mat3 [3]Vec3; - Mat4 [4]Vec4; -} +Mat2 :: [2]Vec2; +Mat3 :: [3]Vec3; +Mat4 :: [4]Vec4; -proc sqrt32(x f32) -> f32 #foreign "llvm.sqrt.f32" -proc sqrt64(x f64) -> f64 #foreign "llvm.sqrt.f64" +sqrt32 :: proc(x f32) -> f32 #foreign "llvm.sqrt.f32" +sqrt64 :: proc(x f64) -> f64 #foreign "llvm.sqrt.f64" -proc sin32(x f32) -> f32 #foreign "llvm.sin.f32" -proc sin64(x f64) -> f64 #foreign "llvm.sin.f64" +sin32 :: proc(x f32) -> f32 #foreign "llvm.sin.f32" +sin64 :: proc(x f64) -> f64 #foreign "llvm.sin.f64" -proc cos32(x f32) -> f32 #foreign "llvm.cos.f32" -proc cos64(x f64) -> f64 #foreign "llvm.cos.f64" +cos32 :: proc(x f32) -> f32 #foreign "llvm.cos.f32" +cos64 :: proc(x f64) -> f64 #foreign "llvm.cos.f64" -proc tan32(x f32) -> f32 #inline { return sin32(x)/cos32(x); } -proc tan64(x f64) -> f64 #inline { return sin64(x)/cos64(x); } +tan32 :: proc(x f32) -> f32 #inline { return sin32(x)/cos32(x); } +tan64 :: proc(x f64) -> f64 #inline { return sin64(x)/cos64(x); } -proc lerp32(a, b, t f32) -> f32 { return a*(1-t) + b*t; } -proc lerp64(a, b, t f64) -> f64 { return a*(1-t) + b*t; } +lerp32 :: proc(a, b, t f32) -> f32 { return a*(1-t) + b*t; } +lerp64 :: proc(a, b, t f64) -> f64 { return a*(1-t) + b*t; } -proc sign32(x f32) -> f32 { if x >= 0 { return +1; } return -1; } -proc sign64(x f64) -> f64 { if x >= 0 { return +1; } return -1; } +sign32 :: proc(x f32) -> f32 { if x >= 0 { return +1; } return -1; } +sign64 :: proc(x f64) -> f64 { if x >= 0 { return +1; } return -1; } -proc copy_sign32(x, y f32) -> f32 { +copy_sign32 :: proc(x, y f32) -> f32 { ix := x transmute u32; iy := y transmute u32; ix &= 0x7fffffff; ix |= iy & 0x80000000; return ix transmute f32; } -proc round32(x f32) -> f32 { +round32 :: proc(x f32) -> f32 { if x >= 0 { return floor32(x + 0.5); } return ceil32(x - 0.5); } -proc floor32(x f32) -> f32 { +floor32 :: proc(x f32) -> f32 { if x >= 0 { return x as int as f32; } return (x-0.5) as int as f32; } -proc ceil32(x f32) -> f32 { +ceil32 :: proc(x f32) -> f32 { if x < 0 { return x as int as f32; } return ((x as int)+1) as f32; } -proc remainder32(x, y f32) -> f32 { +remainder32 :: proc(x, y f32) -> f32 { return x - round32(x/y) * y; } -proc fmod32(x, y f32) -> f32 { +fmod32 :: proc(x, y f32) -> f32 { y = abs(y); result := remainder32(abs(x), y); if sign32(result) < 0 { @@ -86,32 +84,32 @@ proc fmod32(x, y f32) -> f32 { } -proc to_radians(degrees f32) -> f32 { return degrees * TAU / 360; } -proc to_degrees(radians f32) -> f32 { return radians * 360 / TAU; } +to_radians :: proc(degrees f32) -> f32 { return degrees * TAU / 360; } +to_degrees :: proc(radians f32) -> f32 { return radians * 360 / TAU; } -proc dot2(a, b Vec2) -> f32 { c := a*b; return c.x + c.y; } -proc dot3(a, b Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; } -proc dot4(a, b Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; } +dot2 :: proc(a, b Vec2) -> f32 { c := a*b; return c.x + c.y; } +dot3 :: proc(a, b Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; } +dot4 :: proc(a, b Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; } -proc cross3(x, y Vec3) -> Vec3 { +cross3 :: proc(x, y Vec3) -> Vec3 { a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1); b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0); return a - b; } -proc vec2_mag(v Vec2) -> f32 { return sqrt32(dot2(v, v)); } -proc vec3_mag(v Vec3) -> f32 { return sqrt32(dot3(v, v)); } -proc vec4_mag(v Vec4) -> f32 { return sqrt32(dot4(v, v)); } +vec2_mag :: proc(v Vec2) -> f32 { return sqrt32(dot2(v, v)); } +vec3_mag :: proc(v Vec3) -> f32 { return sqrt32(dot3(v, v)); } +vec4_mag :: proc(v Vec4) -> f32 { return sqrt32(dot4(v, v)); } -proc vec2_norm(v Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; } -proc vec3_norm(v Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; } -proc vec4_norm(v Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; } +vec2_norm :: proc(v Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; } +vec3_norm :: proc(v Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; } +vec4_norm :: proc(v Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; } -proc vec2_norm0(v Vec2) -> Vec2 { +vec2_norm0 :: proc(v Vec2) -> Vec2 { m := vec2_mag(v); if m == 0 { return Vec2{0}; @@ -119,7 +117,7 @@ proc vec2_norm0(v Vec2) -> Vec2 { return v / Vec2{m}; } -proc vec3_norm0(v Vec3) -> Vec3 { +vec3_norm0 :: proc(v Vec3) -> Vec3 { m := vec3_mag(v); if m == 0 { return Vec3{0}; @@ -127,7 +125,7 @@ proc vec3_norm0(v Vec3) -> Vec3 { return v / Vec3{m}; } -proc vec4_norm0(v Vec4) -> Vec4 { +vec4_norm0 :: proc(v Vec4) -> Vec4 { m := vec4_mag(v); if m == 0 { return Vec4{0}; @@ -137,7 +135,7 @@ proc vec4_norm0(v Vec4) -> Vec4 { -proc mat4_identity() -> Mat4 { +mat4_identity :: proc() -> Mat4 { return Mat4{ {1, 0, 0, 0}, {0, 1, 0, 0}, @@ -146,7 +144,7 @@ proc mat4_identity() -> Mat4 { }; } -proc mat4_transpose(m Mat4) -> Mat4 { +mat4_transpose :: proc(m Mat4) -> Mat4 { for j := 0; j < 4; j++ { for i := 0; i < 4; i++ { m[i][j], m[j][i] = m[j][i], m[i][j]; @@ -155,7 +153,7 @@ proc mat4_transpose(m Mat4) -> Mat4 { return m; } -proc mat4_mul(a, b Mat4) -> Mat4 { +mat4_mul :: proc(a, b Mat4) -> Mat4 { c: Mat4; for j := 0; j < 4; j++ { for i := 0; i < 4; i++ { @@ -168,7 +166,7 @@ proc mat4_mul(a, b Mat4) -> Mat4 { return c; } -proc mat4_mul_vec4(m Mat4, v Vec4) -> Vec4 { +mat4_mul_vec4 :: proc(m Mat4, v Vec4) -> Vec4 { return Vec4{ m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w, m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w, @@ -177,7 +175,7 @@ proc mat4_mul_vec4(m Mat4, v Vec4) -> Vec4 { }; } -proc mat4_inverse(m Mat4) -> Mat4 { +mat4_inverse :: proc(m Mat4) -> Mat4 { o: Mat4; sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3]; @@ -246,7 +244,7 @@ proc mat4_inverse(m Mat4) -> Mat4 { } -proc mat4_translate(v Vec3) -> Mat4 { +mat4_translate :: proc(v Vec3) -> Mat4 { m := mat4_identity(); m[3][0] = v.x; m[3][1] = v.y; @@ -255,7 +253,7 @@ proc mat4_translate(v Vec3) -> Mat4 { return m; } -proc mat4_rotate(v Vec3, angle_radians f32) -> Mat4 { +mat4_rotate :: proc(v Vec3, angle_radians f32) -> Mat4 { c := cos32(angle_radians); s := sin32(angle_radians); @@ -282,14 +280,14 @@ proc mat4_rotate(v Vec3, angle_radians f32) -> Mat4 { return rot; } -proc mat4_scale(m Mat4, v Vec3) -> Mat4 { +mat4_scale :: proc(m Mat4, v Vec3) -> Mat4 { m[0][0] *= v.x; m[1][1] *= v.y; m[2][2] *= v.z; return m; } -proc mat4_scalef(m Mat4, s f32) -> Mat4 { +mat4_scalef :: proc(m Mat4, s f32) -> Mat4 { m[0][0] *= s; m[1][1] *= s; m[2][2] *= s; @@ -297,7 +295,7 @@ proc mat4_scalef(m Mat4, s f32) -> Mat4 { } -proc mat4_look_at(eye, centre, up Vec3) -> Mat4 { +mat4_look_at :: proc(eye, centre, up Vec3) -> Mat4 { f := vec3_norm(centre - eye); s := vec3_norm(cross3(f, up)); u := cross3(s, f); @@ -311,7 +309,7 @@ proc mat4_look_at(eye, centre, up Vec3) -> Mat4 { return m; } -proc mat4_perspective(fovy, aspect, near, far f32) -> Mat4 { +mat4_perspective :: proc(fovy, aspect, near, far f32) -> Mat4 { m: Mat4; tan_half_fovy := tan32(0.5 * fovy); m[0][0] = 1.0 / (aspect*tan_half_fovy); @@ -323,7 +321,7 @@ proc mat4_perspective(fovy, aspect, near, far f32) -> Mat4 { } -proc mat4_ortho3d(left, right, bottom, top, near, far f32) -> Mat4 { +mat4_ortho3d :: proc(left, right, bottom, top, near, far f32) -> Mat4 { m := mat4_identity(); m[0][0] = +2.0 / (right - left); m[1][1] = +2.0 / (top - bottom); diff --git a/core/mem.odin b/core/mem.odin index d36a9b43d..d481fe014 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -3,32 +3,31 @@ import { "os.odin"; } -proc set(data rawptr, value i32, len int) -> rawptr #link_name "__mem_set" { - proc llvm_memset_64bit(dst rawptr, val byte, len int, align i32, is_volatile bool) #foreign "llvm.memset.p0i8.i64" +set :: proc(data rawptr, value i32, len int) -> rawptr #link_name "__mem_set" { + llvm_memset_64bit :: proc(dst rawptr, val byte, len int, align i32, is_volatile bool) #foreign "llvm.memset.p0i8.i64" llvm_memset_64bit(data, value as byte, len, 1, false); return data; } -proc zero(data rawptr, len int) -> rawptr #link_name "__mem_zero" { +zero :: proc(data rawptr, len int) -> rawptr #link_name "__mem_zero" { return set(data, 0, len); } -proc copy(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy" { +copy :: proc(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy" { // NOTE(bill): This _must_ implemented like C's memmove - proc llvm_memmove_64bit(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memmove.p0i8.p0i8.i64" + llvm_memmove_64bit :: proc(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memmove.p0i8.p0i8.i64" llvm_memmove_64bit(dst, src, len, 1, false); return dst; } -proc copy_non_overlapping(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy_non_overlapping" { +copy_non_overlapping :: proc(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy_non_overlapping" { // NOTE(bill): This _must_ implemented like C's memcpy - proc llvm_memcpy_64bit(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memcpy.p0i8.p0i8.i64" + llvm_memcpy_64bit :: proc(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memcpy.p0i8.p0i8.i64" llvm_memcpy_64bit(dst, src, len, 1, false); return dst; } - -proc compare(dst, src rawptr, n int) -> int #link_name "__mem_compare" { +compare :: proc(dst, src rawptr, n int) -> int #link_name "__mem_compare" { // Translation of http://mgronhol.github.io/fast-strcmp/ a := slice_ptr(dst as ^byte, n); b := slice_ptr(src as ^byte, n); @@ -65,19 +64,19 @@ proc compare(dst, src rawptr, n int) -> int #link_name "__mem_compare" { -proc kilobytes(x int) -> int #inline { return (x) * 1024; } -proc megabytes(x int) -> int #inline { return kilobytes(x) * 1024; } -proc gigabytes(x int) -> int #inline { return gigabytes(x) * 1024; } -proc terabytes(x int) -> int #inline { return terabytes(x) * 1024; } +kilobytes :: proc(x int) -> int #inline { return (x) * 1024; } +megabytes :: proc(x int) -> int #inline { return kilobytes(x) * 1024; } +gigabytes :: proc(x int) -> int #inline { return gigabytes(x) * 1024; } +terabytes :: proc(x int) -> int #inline { return terabytes(x) * 1024; } -proc is_power_of_two(x int) -> bool { +is_power_of_two :: proc(x int) -> bool { if x <= 0 { return false; } return (x & (x-1)) == 0; } -proc align_forward(ptr rawptr, align int) -> rawptr { +align_forward :: proc(ptr rawptr, align int) -> rawptr { assert(is_power_of_two(align)); a := align as uint; @@ -91,11 +90,11 @@ proc align_forward(ptr rawptr, align int) -> rawptr { -type Allocation_Header struct { +Allocation_Header :: struct { size int; } -proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) { +allocation_header_fill :: proc(header ^Allocation_Header, data rawptr, size int) { header.size = size; ptr := (header+1) as ^int; @@ -103,7 +102,7 @@ proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) { (ptr+i)^ = -1; } } -proc allocation_header(data rawptr) -> ^Allocation_Header { +allocation_header :: proc(data rawptr) -> ^Allocation_Header { p := data as ^int; for (p-1)^ == -1 { p = (p-1); @@ -116,35 +115,34 @@ proc allocation_header(data rawptr) -> ^Allocation_Header { // Custom allocators -type { - Arena struct { - backing Allocator; - memory []byte; - temp_count int; - } +Arena :: struct { + backing Allocator; + memory []byte; + temp_count int; +} - Arena_Temp_Memory struct { - arena ^Arena; - original_count int; - } +Arena_Temp_Memory :: struct { + arena ^Arena; + original_count int; } -proc init_arena_from_memory(using a ^Arena, data []byte) { + +init_arena_from_memory :: proc(using a ^Arena, data []byte) { backing = Allocator{}; memory = data[:0]; temp_count = 0; } -proc init_arena_from_context(using a ^Arena, size int) { +init_arena_from_context :: proc(using a ^Arena, size int) { backing = context.allocator; memory = new_slice(byte, 0, size); temp_count = 0; } -proc free_arena(using a ^Arena) { +free_arena :: proc(using a ^Arena) { if backing.procedure != nil { push_allocator backing { free(memory.data); @@ -153,14 +151,14 @@ proc free_arena(using a ^Arena) { } } -proc arena_allocator(arena ^Arena) -> Allocator { +arena_allocator :: proc(arena ^Arena) -> Allocator { return Allocator{ procedure = arena_allocator_proc, data = arena, }; } -proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode, +arena_allocator_proc :: proc(allocator_data rawptr, mode Allocator_Mode, size, alignment int, old_memory rawptr, old_size int, flags u64) -> rawptr { using Allocator_Mode; @@ -195,7 +193,7 @@ proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode, return nil; } -proc begin_arena_temp_memory(a ^Arena) -> Arena_Temp_Memory { +begin_arena_temp_memory :: proc(a ^Arena) -> Arena_Temp_Memory { tmp: Arena_Temp_Memory; tmp.arena = a; tmp.original_count = a.memory.count; @@ -203,7 +201,7 @@ proc begin_arena_temp_memory(a ^Arena) -> Arena_Temp_Memory { return tmp; } -proc end_arena_temp_memory(using tmp Arena_Temp_Memory) { +end_arena_temp_memory :: proc(using tmp Arena_Temp_Memory) { assert(arena.memory.count >= original_count); assert(arena.temp_count > 0); arena.memory.count = original_count; @@ -216,8 +214,8 @@ proc end_arena_temp_memory(using tmp Arena_Temp_Memory) { -proc align_of_type_info(type_info ^Type_Info) -> int { - proc prev_pow2(n i64) -> i64 { +align_of_type_info :: proc(type_info ^Type_Info) -> int { + prev_pow2 :: proc(n i64) -> i64 { if n <= 0 { return 0; } @@ -271,12 +269,12 @@ proc align_of_type_info(type_info ^Type_Info) -> int { return 0; } -proc align_formula(size, align int) -> int { +align_formula :: proc(size, align int) -> int { result := size + align-1; return result - result%align; } -proc size_of_type_info(type_info ^Type_Info) -> int { +size_of_type_info :: proc(type_info ^Type_Info) -> int { WORD_SIZE :: size_of(int); using Type_Info; match type info : type_info { @@ -310,7 +308,7 @@ proc size_of_type_info(type_info ^Type_Info) -> int { case Slice: return 3*WORD_SIZE; case Vector: - proc is_bool(type_info ^Type_Info) -> bool { + is_bool :: proc(type_info ^Type_Info) -> bool { match type info : type_info { case Named: return is_bool(info.base); diff --git a/core/opengl.odin b/core/opengl.odin index 272effe0f..91b23f8e7 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -2,37 +2,37 @@ import win32 "sys/windows.odin" when ODIN_OS == "windows"; include "opengl_constants.odin"; -proc Clear (mask u32) #foreign "glClear" -proc ClearColor (r, g, b, a f32) #foreign "glClearColor" -proc Begin (mode i32) #foreign "glBegin" -proc End () #foreign "glEnd" -proc Finish () #foreign "glFinish" -proc BlendFunc (sfactor, dfactor i32) #foreign "glBlendFunc" -proc Enable (cap i32) #foreign "glEnable" -proc Disable (cap i32) #foreign "glDisable" -proc GenTextures (count i32, result ^u32) #foreign "glGenTextures" -proc DeleteTextures(count i32, result ^u32) #foreign "glDeleteTextures" -proc TexParameteri (target, pname, param i32) #foreign "glTexParameteri" -proc TexParameterf (target i32, pname i32, param f32) #foreign "glTexParameterf" -proc BindTexture (target i32, texture u32) #foreign "glBindTexture" -proc LoadIdentity () #foreign "glLoadIdentity" -proc Viewport (x, y, width, height i32) #foreign "glViewport" -proc Ortho (left, right, bottom, top, near, far f64) #foreign "glOrtho" -proc Color3f (r, g, b f32) #foreign "glColor3f" -proc Vertex3f (x, y, z f32) #foreign "glVertex3f" -proc TexImage2D (target, level, internal_format, - width, height, border, - format, _type i32, pixels rawptr) #foreign "glTexImage2D" +Clear :: proc(mask u32) #foreign "glClear" +ClearColor :: proc(r, g, b, a f32) #foreign "glClearColor" +Begin :: proc(mode i32) #foreign "glBegin" +End :: proc() #foreign "glEnd" +Finish :: proc() #foreign "glFinish" +BlendFunc :: proc(sfactor, dfactor i32) #foreign "glBlendFunc" +Enable :: proc(cap i32) #foreign "glEnable" +Disable :: proc(cap i32) #foreign "glDisable" +GenTextures :: proc(count i32, result ^u32) #foreign "glGenTextures" +DeleteTextures:: proc(count i32, result ^u32) #foreign "glDeleteTextures" +TexParameteri :: proc(target, pname, param i32) #foreign "glTexParameteri" +TexParameterf :: proc(target i32, pname i32, param f32) #foreign "glTexParameterf" +BindTexture :: proc(target i32, texture u32) #foreign "glBindTexture" +LoadIdentity :: proc() #foreign "glLoadIdentity" +Viewport :: proc(x, y, width, height i32) #foreign "glViewport" +Ortho :: proc(left, right, bottom, top, near, far f64) #foreign "glOrtho" +Color3f :: proc(r, g, b f32) #foreign "glColor3f" +Vertex3f :: proc(x, y, z f32) #foreign "glVertex3f" +TexImage2D :: proc(target, level, internal_format, + width, height, border, + format, _type i32, pixels rawptr) #foreign "glTexImage2D" -proc GetError () -> i32 #foreign "glGetError" -proc GetString (name i32) -> ^byte #foreign "glGetString" -proc GetIntegerv(name i32, v ^i32) #foreign "glGetIntegerv" +GetError :: proc() -> i32 #foreign "glGetError" +GetString :: proc(name i32) -> ^byte #foreign "glGetString" +GetIntegerv :: proc(name i32, v ^i32) #foreign "glGetIntegerv" _libgl := win32.LoadLibraryA(("opengl32.dll\x00" as string).data); -proc GetProcAddress(name string) -> proc() #cc_c { +GetProcAddress :: proc(name string) -> proc() #cc_c { assert(name[name.count-1] == 0); res := win32.wglGetProcAddress(name.data); if res == nil { @@ -99,8 +99,8 @@ UniformMatrix4fv: proc(loc i32, count u32, transpose i32, value ^f32) #cc_c; GetUniformLocation: proc(program u32, name ^byte) -> i32 #cc_c; -proc init() { - proc set_proc_address(p rawptr, name string) #inline { (p as ^(proc() #cc_c))^ = GetProcAddress(name); } +init :: proc() { + set_proc_address :: proc(p rawptr, name string) #inline { (p as ^(proc() #cc_c))^ = GetProcAddress(name); } set_proc_address(^GenBuffers, "glGenBuffers\x00"); set_proc_address(^GenVertexArrays, "glGenVertexArrays\x00"); diff --git a/core/os_windows.odin b/core/os_windows.odin index 0be905d7a..8921588f1 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -4,11 +4,9 @@ import { } -type { - Handle uint; - File_Time u64; - Error int; -} +Handle :: uint; +File_Time :: u64; +Error :: int; INVALID_HANDLE: Handle : ~(0 as Handle); @@ -56,7 +54,7 @@ ERROR_FILE_IS_PIPE : Error : 1<<29 + 0; -proc open(path string, mode int, perm u32) -> (Handle, Error) { +open :: proc(path string, mode int, perm u32) -> (Handle, Error) { using win32; if path.count == 0 { return INVALID_HANDLE, ERROR_FILE_NOT_FOUND; @@ -109,11 +107,11 @@ proc open(path string, mode int, perm u32) -> (Handle, Error) { return INVALID_HANDLE, err as Error; } -proc close(fd Handle) { +close :: proc(fd Handle) { win32.CloseHandle(fd as win32.HANDLE); } -proc write(fd Handle, data []byte) -> (int, Error) { +write :: proc(fd Handle, data []byte) -> (int, Error) { bytes_written: i32; e := win32.WriteFile(fd as win32.HANDLE, data.data, data.count as i32, ^bytes_written, nil); if e != 0 { @@ -122,7 +120,7 @@ proc write(fd Handle, data []byte) -> (int, Error) { return bytes_written as int, ERROR_NONE; } -proc read(fd Handle, data []byte) -> (int, Error) { +read :: proc(fd Handle, data []byte) -> (int, Error) { bytes_read: i32; e := win32.ReadFile(fd as win32.HANDLE, data.data, data.count as u32, ^bytes_read, nil); if e != win32.FALSE { @@ -132,7 +130,7 @@ proc read(fd Handle, data []byte) -> (int, Error) { return bytes_read as int, ERROR_NONE; } -proc seek(fd Handle, offset i64, whence int) -> (i64, Error) { +seek :: proc(fd Handle, offset i64, whence int) -> (i64, Error) { using win32; w: u32; match whence { @@ -161,7 +159,7 @@ stdout := get_std_handle(win32.STD_OUTPUT_HANDLE); stderr := get_std_handle(win32.STD_ERROR_HANDLE); -proc get_std_handle(h int) -> Handle { +get_std_handle :: proc(h int) -> Handle { fd := win32.GetStdHandle(h as i32); win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0); return fd as Handle; @@ -172,7 +170,7 @@ proc get_std_handle(h int) -> Handle { -proc last_write_time(fd Handle) -> File_Time { +last_write_time :: proc(fd Handle) -> File_Time { file_info: win32.BY_HANDLE_FILE_INFORMATION; win32.GetFileInformationByHandle(fd as win32.HANDLE, ^file_info); lo := file_info.last_write_time.lo as File_Time; @@ -180,7 +178,7 @@ proc last_write_time(fd Handle) -> File_Time { return lo | hi << 32; } -proc last_write_time_by_name(name string) -> File_Time { +last_write_time_by_name :: proc(name string) -> File_Time { last_write_time: win32.FILETIME; data: win32.FILE_ATTRIBUTE_DATA; buf: [1024]byte; @@ -202,7 +200,7 @@ proc last_write_time_by_name(name string) -> File_Time { -proc read_entire_file(name string) -> ([]byte, bool) { +read_entire_file :: proc(name string) -> ([]byte, bool) { buf: [300]byte; copy(buf[:], name as []byte); @@ -250,25 +248,25 @@ proc read_entire_file(name string) -> ([]byte, bool) { -proc heap_alloc(size int) -> rawptr { +heap_alloc :: proc(size int) -> rawptr { return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size); } -proc heap_resize(ptr rawptr, new_size int) -> rawptr { +heap_resize :: proc(ptr rawptr, new_size int) -> rawptr { return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size); } -proc heap_free(ptr rawptr) { +heap_free :: proc(ptr rawptr) { win32.HeapFree(win32.GetProcessHeap(), 0, ptr); } -proc exit(code int) { +exit :: proc(code int) { win32.ExitProcess(code as u32); } -proc current_thread_id() -> int { - proc GetCurrentThreadId() -> u32 #foreign #dll_import +current_thread_id :: proc() -> int { + GetCurrentThreadId :: proc() -> u32 #foreign #dll_import return GetCurrentThreadId() as int; } diff --git a/core/sync.odin b/core/sync.odin index 98322d580..28f7cbaf1 100644 --- a/core/sync.odin +++ b/core/sync.odin @@ -3,52 +3,50 @@ import { "atomic.odin"; } -type { - Semaphore struct { - handle win32.HANDLE; - } - - Mutex struct { - semaphore Semaphore; - counter i32; - owner i32; - recursion i32; - } +Semaphore :: struct { + handle win32.HANDLE; } -proc current_thread_id() -> i32 { +Mutex :: struct { + semaphore Semaphore; + counter i32; + owner i32; + recursion i32; +} + +current_thread_id :: proc() -> i32 { return win32.GetCurrentThreadId() as i32; } -proc semaphore_init(s ^Semaphore) { +semaphore_init :: proc(s ^Semaphore) { s.handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil); } -proc semaphore_destroy(s ^Semaphore) { +semaphore_destroy :: proc(s ^Semaphore) { win32.CloseHandle(s.handle); } -proc semaphore_post(s ^Semaphore, count int) { +semaphore_post :: proc(s ^Semaphore, count int) { win32.ReleaseSemaphore(s.handle, count as i32, nil); } -proc semaphore_release(s ^Semaphore) #inline { semaphore_post(s, 1); } +semaphore_release :: proc(s ^Semaphore) #inline { semaphore_post(s, 1); } -proc semaphore_wait(s ^Semaphore) { +semaphore_wait :: proc(s ^Semaphore) { win32.WaitForSingleObject(s.handle, win32.INFINITE); } -proc mutex_init(m ^Mutex) { +mutex_init :: proc(m ^Mutex) { atomic.store32(^m.counter, 0); atomic.store32(^m.owner, current_thread_id()); semaphore_init(^m.semaphore); m.recursion = 0; } -proc mutex_destroy(m ^Mutex) { +mutex_destroy :: proc(m ^Mutex) { semaphore_destroy(^m.semaphore); } -proc mutex_lock(m ^Mutex) { +mutex_lock :: proc(m ^Mutex) { thread_id := current_thread_id(); if atomic.fetch_add32(^m.counter, 1) > 0 { if thread_id != atomic.load32(^m.owner) { @@ -58,7 +56,7 @@ proc mutex_lock(m ^Mutex) { atomic.store32(^m.owner, thread_id); m.recursion++; } -proc mutex_try_lock(m ^Mutex) -> bool { +mutex_try_lock :: proc(m ^Mutex) -> bool { thread_id := current_thread_id(); if atomic.load32(^m.owner) == thread_id { atomic.fetch_add32(^m.counter, 1); @@ -75,7 +73,7 @@ proc mutex_try_lock(m ^Mutex) -> bool { m.recursion++; return true; } -proc mutex_unlock(m ^Mutex) { +mutex_unlock :: proc(m ^Mutex) { recursion: i32; thread_id := current_thread_id(); assert(thread_id == atomic.load32(^m.owner)); diff --git a/core/sys/windows.odin b/core/sys/windows.odin index a406d53ee..40839b4cd 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -1,24 +1,22 @@ #foreign_system_library "user32" when ODIN_OS == "windows"; #foreign_system_library "gdi32" when ODIN_OS == "windows"; -type { - HANDLE rawptr; - HWND HANDLE; - HDC HANDLE; - HINSTANCE HANDLE; - HICON HANDLE; - HCURSOR HANDLE; - HMENU HANDLE; - HBRUSH HANDLE; - HGDIOBJ HANDLE; - HMODULE HANDLE; - WPARAM uint; - LPARAM int; - LRESULT int; - ATOM i16; - BOOL i32; - WNDPROC proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT; -} +HANDLE :: rawptr; +HWND :: HANDLE; +HDC :: HANDLE; +HINSTANCE :: HANDLE; +HICON :: HANDLE; +HCURSOR :: HANDLE; +HMENU :: HANDLE; +HBRUSH :: HANDLE; +HGDIOBJ :: HANDLE; +HMODULE :: HANDLE; +WPARAM :: uint; +LPARAM :: int; +LRESULT :: int; +ATOM :: i16; +BOOL :: i32; +WNDPROC :: type proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT; INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE; @@ -57,137 +55,136 @@ SM_CYSCREEN :: 1; SW_SHOW :: 5; -type { - POINT struct #ordered { - 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; - } - - MSG struct #ordered { - hwnd HWND; - message u32; - wparam WPARAM; - lparam LPARAM; - time u32; - pt POINT; - } - - RECT struct #ordered { - left i32; - top i32; - right i32; - bottom i32; - } - - FILETIME struct #ordered { - lo, hi u32; - } - - BY_HANDLE_FILE_INFORMATION struct #ordered { - file_attributes u32; - creation_time, - last_access_time, - last_write_time FILETIME; - volume_serial_number, - file_size_high, - file_size_low, - number_of_links, - file_index_high, - file_index_low u32; - } - - FILE_ATTRIBUTE_DATA struct #ordered { - file_attributes u32; - creation_time, - last_access_time, - last_write_time FILETIME; - file_size_high, - file_size_low u32; - } - - GET_FILEEX_INFO_LEVELS i32; +POINT :: struct #ordered { + 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; +} + +MSG :: struct #ordered { + hwnd HWND; + message u32; + wparam WPARAM; + lparam LPARAM; + time u32; + pt POINT; +} + +RECT :: struct #ordered { + left i32; + top i32; + right i32; + bottom i32; +} + +FILETIME :: struct #ordered { + lo, hi u32; +} + +BY_HANDLE_FILE_INFORMATION :: struct #ordered { + file_attributes u32; + creation_time, + last_access_time, + last_write_time FILETIME; + volume_serial_number, + file_size_high, + file_size_low, + number_of_links, + file_index_high, + file_index_low u32; +} + +FILE_ATTRIBUTE_DATA :: struct #ordered { + file_attributes u32; + creation_time, + last_access_time, + last_write_time FILETIME; + file_size_high, + file_size_low u32; +} + +GET_FILEEX_INFO_LEVELS :: i32; + GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0; GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1; -proc GetLastError () -> i32 #foreign #dll_import -proc ExitProcess (exit_code u32) #foreign #dll_import -proc GetDesktopWindow() -> HWND #foreign #dll_import -proc GetCursorPos (p ^POINT) -> i32 #foreign #dll_import -proc ScreenToClient (h HWND, p ^POINT) -> i32 #foreign #dll_import -proc GetModuleHandleA(module_name ^u8) -> HINSTANCE #foreign #dll_import -proc GetStockObject (fn_object i32) -> HGDIOBJ #foreign #dll_import -proc PostQuitMessage (exit_code i32) #foreign #dll_import -proc SetWindowTextA (hwnd HWND, c_string ^u8) -> BOOL #foreign #dll_import +GetLastError :: proc() -> i32 #foreign #dll_import +ExitProcess :: proc(exit_code u32) #foreign #dll_import +GetDesktopWindow :: proc() -> HWND #foreign #dll_import +GetCursorPos :: proc(p ^POINT) -> i32 #foreign #dll_import +ScreenToClient :: proc(h HWND, p ^POINT) -> i32 #foreign #dll_import +GetModuleHandleA :: proc(module_name ^u8) -> HINSTANCE #foreign #dll_import +GetStockObject :: proc(fn_object i32) -> HGDIOBJ #foreign #dll_import +PostQuitMessage :: proc(exit_code i32) #foreign #dll_import +SetWindowTextA :: proc(hwnd HWND, c_string ^u8) -> BOOL #foreign #dll_import -proc QueryPerformanceFrequency(result ^i64) -> i32 #foreign #dll_import -proc QueryPerformanceCounter (result ^i64) -> i32 #foreign #dll_import +QueryPerformanceFrequency :: proc(result ^i64) -> i32 #foreign #dll_import +QueryPerformanceCounter :: proc(result ^i64) -> i32 #foreign #dll_import -proc Sleep(ms i32) -> i32 #foreign #dll_import +Sleep :: proc(ms i32) -> i32 #foreign #dll_import -proc OutputDebugStringA(c_str ^u8) #foreign #dll_import +OutputDebugStringA :: proc(c_str ^u8) #foreign #dll_import -proc RegisterClassExA(wc ^WNDCLASSEXA) -> ATOM #foreign #dll_import -proc CreateWindowExA (ex_style u32, - class_name, title ^u8, - style u32, - x, y, w, h i32, - parent HWND, menu HMENU, instance HINSTANCE, - param rawptr) -> HWND #foreign #dll_import +RegisterClassExA :: proc(wc ^WNDCLASSEXA) -> ATOM #foreign #dll_import +CreateWindowExA :: proc(ex_style u32, + class_name, title ^u8, + style u32, + x, y, w, h i32, + parent HWND, menu HMENU, instance HINSTANCE, + param rawptr) -> HWND #foreign #dll_import -proc ShowWindow (hwnd HWND, cmd_show i32) -> BOOL #foreign #dll_import -proc TranslateMessage(msg ^MSG) -> BOOL #foreign #dll_import -proc DispatchMessageA(msg ^MSG) -> LRESULT #foreign #dll_import -proc UpdateWindow (hwnd HWND) -> BOOL #foreign #dll_import -proc PeekMessageA (msg ^MSG, hwnd HWND, +ShowWindow :: proc(hwnd HWND, cmd_show i32) -> BOOL #foreign #dll_import +TranslateMessage :: proc(msg ^MSG) -> BOOL #foreign #dll_import +DispatchMessageA :: proc(msg ^MSG) -> LRESULT #foreign #dll_import +UpdateWindow :: proc(hwnd HWND) -> BOOL #foreign #dll_import +PeekMessageA :: proc(msg ^MSG, hwnd HWND, msg_filter_min, msg_filter_max, remove_msg u32) -> BOOL #foreign #dll_import -proc DefWindowProcA (hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT #foreign #dll_import +DefWindowProcA :: proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT #foreign #dll_import -proc AdjustWindowRect(rect ^RECT, style u32, menu BOOL) -> BOOL #foreign #dll_import -proc GetActiveWindow () -> HWND #foreign #dll_import +AdjustWindowRect :: proc(rect ^RECT, style u32, menu BOOL) -> BOOL #foreign #dll_import +GetActiveWindow :: proc() -> HWND #foreign #dll_import -proc GetQueryPerformanceFrequency() -> i64 { +GetQueryPerformanceFrequency :: proc() -> i64 { r: i64; QueryPerformanceFrequency(^r); return r; } -proc GetCommandLineA() -> ^u8 #foreign #dll_import -proc GetSystemMetrics(index i32) -> i32 #foreign #dll_import -proc GetCurrentThreadId() -> u32 #foreign #dll_import +GetCommandLineA :: proc() -> ^u8 #foreign #dll_import +GetSystemMetrics :: proc(index i32) -> i32 #foreign #dll_import +GetCurrentThreadId :: proc() -> u32 #foreign #dll_import // File Stuff -proc CloseHandle (h HANDLE) -> i32 #foreign #dll_import -proc GetStdHandle(h i32) -> HANDLE #foreign #dll_import -proc CreateFileA (filename ^u8, desired_access, share_mode u32, +CloseHandle :: proc(h HANDLE) -> i32 #foreign #dll_import +GetStdHandle :: proc(h i32) -> HANDLE #foreign #dll_import +CreateFileA :: proc(filename ^u8, desired_access, share_mode u32, security rawptr, creation, flags_and_attribs u32, template_file HANDLE) -> HANDLE #foreign #dll_import -proc ReadFile (h HANDLE, buf rawptr, to_read u32, bytes_read ^i32, overlapped rawptr) -> BOOL #foreign #dll_import -proc WriteFile (h HANDLE, buf rawptr, len i32, written_result ^i32, overlapped rawptr) -> i32 #foreign #dll_import +ReadFile :: proc(h HANDLE, buf rawptr, to_read u32, bytes_read ^i32, overlapped rawptr) -> BOOL #foreign #dll_import +WriteFile :: proc(h HANDLE, buf rawptr, len i32, written_result ^i32, overlapped rawptr) -> i32 #foreign #dll_import -proc GetFileSizeEx (file_handle HANDLE, file_size ^i64) -> BOOL #foreign #dll_import -proc GetFileAttributesExA (filename ^u8, info_level_id GET_FILEEX_INFO_LEVELS, file_info rawptr) -> BOOL #foreign #dll_import -proc GetFileInformationByHandle(file_handle HANDLE, file_info ^BY_HANDLE_FILE_INFORMATION) -> BOOL #foreign #dll_import +GetFileSizeEx :: proc(file_handle HANDLE, file_size ^i64) -> BOOL #foreign #dll_import +GetFileAttributesExA :: proc(filename ^u8, info_level_id GET_FILEEX_INFO_LEVELS, file_info rawptr) -> BOOL #foreign #dll_import +GetFileInformationByHandle :: proc(file_handle HANDLE, file_info ^BY_HANDLE_FILE_INFORMATION) -> BOOL #foreign #dll_import -proc GetFileType(file_handle HANDLE) -> u32 #foreign #dll_import -proc SetFilePointer(file_handle HANDLE, distance_to_move i32, distance_to_move_high ^i32, move_method u32) -> u32 #foreign #dll_import +GetFileType :: proc(file_handle HANDLE) -> u32 #foreign #dll_import +SetFilePointer :: proc(file_handle HANDLE, distance_to_move i32, distance_to_move_high ^i32, move_method u32) -> u32 #foreign #dll_import -proc SetHandleInformation(obj HANDLE, mask, flags u32) -> BOOL #foreign #dll_import +SetHandleInformation :: proc(obj HANDLE, mask, flags u32) -> BOOL #foreign #dll_import HANDLE_FLAG_INHERIT :: 1; HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2; @@ -241,17 +238,17 @@ INVALID_SET_FILE_POINTER :: ~(0 as u32); -proc HeapAlloc (h HANDLE, flags u32, bytes int) -> rawptr #foreign #dll_import -proc HeapReAlloc (h HANDLE, flags u32, memory rawptr, bytes int) -> rawptr #foreign #dll_import -proc HeapFree (h HANDLE, flags u32, memory rawptr) -> BOOL #foreign #dll_import -proc GetProcessHeap() -> HANDLE #foreign #dll_import +HeapAlloc :: proc (h HANDLE, flags u32, bytes int) -> rawptr #foreign #dll_import +HeapReAlloc :: proc (h HANDLE, flags u32, memory rawptr, bytes int) -> rawptr #foreign #dll_import +HeapFree :: proc (h HANDLE, flags u32, memory rawptr) -> BOOL #foreign #dll_import +GetProcessHeap :: proc () -> HANDLE #foreign #dll_import HEAP_ZERO_MEMORY :: 0x00000008; // Synchronization -type SECURITY_ATTRIBUTES struct #ordered { +SECURITY_ATTRIBUTES :: struct #ordered { length u32; security_descriptor rawptr; inherit_handle BOOL; @@ -259,51 +256,49 @@ type SECURITY_ATTRIBUTES struct #ordered { INFINITE :: 0xffffffff; -proc CreateSemaphoreA (attributes ^SECURITY_ATTRIBUTES, initial_count, maximum_count i32, name ^byte) -> HANDLE #foreign #dll_import -proc ReleaseSemaphore (semaphore HANDLE, release_count i32, previous_count ^i32) -> BOOL #foreign #dll_import -proc WaitForSingleObject(handle HANDLE, milliseconds u32) -> u32 #foreign #dll_import +CreateSemaphoreA :: proc(attributes ^SECURITY_ATTRIBUTES, initial_count, maximum_count i32, name ^byte) -> HANDLE #foreign #dll_import +ReleaseSemaphore :: proc(semaphore HANDLE, release_count i32, previous_count ^i32) -> BOOL #foreign #dll_import +WaitForSingleObject :: proc(handle HANDLE, milliseconds u32) -> u32 #foreign #dll_import -proc InterlockedCompareExchange(dst ^i32, exchange, comparand i32) -> i32 #foreign -proc InterlockedExchange (dst ^i32, desired i32) -> i32 #foreign -proc InterlockedExchangeAdd (dst ^i32, desired i32) -> i32 #foreign -proc InterlockedAnd (dst ^i32, desired i32) -> i32 #foreign -proc InterlockedOr (dst ^i32, desired i32) -> i32 #foreign +InterlockedCompareExchange :: proc(dst ^i32, exchange, comparand i32) -> i32 #foreign +InterlockedExchange :: proc(dst ^i32, desired i32) -> i32 #foreign +InterlockedExchangeAdd :: proc(dst ^i32, desired i32) -> i32 #foreign +InterlockedAnd :: proc(dst ^i32, desired i32) -> i32 #foreign +InterlockedOr :: proc(dst ^i32, desired i32) -> i32 #foreign -proc InterlockedCompareExchange64(dst ^i64, exchange, comparand i64) -> i64 #foreign -proc InterlockedExchange64 (dst ^i64, desired i64) -> i64 #foreign -proc InterlockedExchangeAdd64 (dst ^i64, desired i64) -> i64 #foreign -proc InterlockedAnd64 (dst ^i64, desired i64) -> i64 #foreign -proc InterlockedOr64 (dst ^i64, desired i64) -> i64 #foreign +InterlockedCompareExchange64 :: proc(dst ^i64, exchange, comparand i64) -> i64 #foreign +InterlockedExchange64 :: proc(dst ^i64, desired i64) -> i64 #foreign +InterlockedExchangeAdd64 :: proc(dst ^i64, desired i64) -> i64 #foreign +InterlockedAnd64 :: proc(dst ^i64, desired i64) -> i64 #foreign +InterlockedOr64 :: proc(dst ^i64, desired i64) -> i64 #foreign -proc _mm_pause () #foreign -proc ReadWriteBarrier() #foreign -proc WriteBarrier () #foreign -proc ReadBarrier () #foreign +_mm_pause :: proc() #foreign +ReadWriteBarrier :: proc() #foreign +WriteBarrier :: proc() #foreign +ReadBarrier :: proc() #foreign // GDI -type { - 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; - } - BITMAPINFO struct #ordered { - using header BITMAPINFOHEADER; - colors [1]RGBQUAD; - } +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; +} +BITMAPINFO :: struct #ordered { + using header BITMAPINFOHEADER; + colors [1]RGBQUAD; +} - RGBQUAD struct #ordered { - blue, green, red, reserved byte; - } +RGBQUAD :: struct #ordered { + blue, green, red, reserved byte; } BI_RGB :: 0; @@ -311,20 +306,20 @@ DIB_RGB_COLORS :: 0x00; SRCCOPY: u32 : 0x00cc0020; -proc StretchDIBits(hdc HDC, - x_dst, y_dst, width_dst, height_dst i32, - x_src, y_src, width_src, header_src i32, - bits rawptr, bits_info ^BITMAPINFO, - usage u32, - rop u32) -> i32 #foreign #dll_import +StretchDIBits :: proc (hdc HDC, + x_dst, y_dst, width_dst, height_dst i32, + x_src, y_src, width_src, header_src i32, + bits rawptr, bits_info ^BITMAPINFO, + usage u32, + rop u32) -> i32 #foreign #dll_import -proc LoadLibraryA (c_str ^u8) -> HMODULE #foreign -proc FreeLibrary (h HMODULE) #foreign -proc GetProcAddress(h HMODULE, c_str ^u8) -> PROC #foreign +LoadLibraryA :: proc (c_str ^u8) -> HMODULE #foreign +FreeLibrary :: proc (h HMODULE) #foreign +GetProcAddress :: proc (h HMODULE, c_str ^u8) -> PROC #foreign -proc GetClientRect(hwnd HWND, rect ^RECT) -> BOOL #foreign +GetClientRect :: proc(hwnd HWND, rect ^RECT) -> BOOL #foreign @@ -351,49 +346,47 @@ PFD_DEPTH_DONTCARE :: 0x20000000; PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000; PFD_STEREO_DONTCARE :: 0x80000000; -type { - HGLRC HANDLE; - PROC proc() #cc_c; - wglCreateContextAttribsARBType proc(hdc HDC, hshareContext rawptr, attribList ^i32) -> HGLRC; +HGLRC :: HANDLE; +PROC :: type proc() #cc_c; +wglCreateContextAttribsARBType :: proc(hdc HDC, hshareContext rawptr, attribList ^i32) -> HGLRC; - PIXELFORMATDESCRIPTOR struct #ordered { - size, - version, - flags u32; +PIXELFORMATDESCRIPTOR :: struct #ordered { + size, + version, + flags u32; - pixel_type, - color_bits, - red_bits, - red_shift, - green_bits, - green_shift, - blue_bits, - blue_shift, - alpha_bits, - alpha_shift, - accum_bits, - accum_red_bits, - accum_green_bits, - accum_blue_bits, - accum_alpha_bits, - depth_bits, - stencil_bits, - aux_buffers, - layer_type, - reserved byte; + pixel_type, + color_bits, + red_bits, + red_shift, + green_bits, + green_shift, + blue_bits, + blue_shift, + alpha_bits, + alpha_shift, + accum_bits, + accum_red_bits, + accum_green_bits, + accum_blue_bits, + accum_alpha_bits, + depth_bits, + stencil_bits, + aux_buffers, + layer_type, + reserved byte; - layer_mask, - visible_mask, - damage_mask u32; - } + layer_mask, + visible_mask, + damage_mask u32; } -proc GetDC (h HANDLE) -> HDC #foreign -proc SetPixelFormat (hdc HDC, pixel_format i32, pfd ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import -proc ChoosePixelFormat(hdc HDC, pfd ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import -proc SwapBuffers (hdc HDC) -> BOOL #foreign #dll_import -proc ReleaseDC (wnd HWND, hdc HDC) -> i32 #foreign #dll_import +GetDC :: proc(h HANDLE) -> HDC #foreign +SetPixelFormat :: proc(hdc HDC, pixel_format i32, pfd ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import +ChoosePixelFormat :: proc(hdc HDC, pfd ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import +SwapBuffers :: proc(hdc HDC) -> BOOL #foreign #dll_import +ReleaseDC :: proc(wnd HWND, hdc HDC) -> i32 #foreign #dll_import WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091; WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092; @@ -401,19 +394,19 @@ WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126; WGL_CONTEXT_CORE_PROFILE_BIT_ARB :: 0x0001; WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002; -proc wglCreateContext (hdc HDC) -> HGLRC #foreign #dll_import -proc wglMakeCurrent (hdc HDC, hglrc HGLRC) -> BOOL #foreign #dll_import -proc wglGetProcAddress(c_str ^u8) -> PROC #foreign #dll_import -proc wglDeleteContext (hglrc HGLRC) -> BOOL #foreign #dll_import +wglCreateContext :: proc(hdc HDC) -> HGLRC #foreign #dll_import +wglMakeCurrent :: proc(hdc HDC, hglrc HGLRC) -> BOOL #foreign #dll_import +wglGetProcAddress :: proc(c_str ^u8) -> PROC #foreign #dll_import +wglDeleteContext :: proc(hglrc HGLRC) -> BOOL #foreign #dll_import -proc GetKeyState (v_key i32) -> i16 #foreign #dll_import -proc GetAsyncKeyState(v_key i32) -> i16 #foreign #dll_import +GetKeyState :: proc(v_key i32) -> i16 #foreign #dll_import +GetAsyncKeyState :: proc(v_key i32) -> i16 #foreign #dll_import -proc is_key_down(key Key_Code) -> bool #inline { return GetAsyncKeyState(key as i32) < 0; } +is_key_down :: proc(key Key_Code) -> bool #inline { return GetAsyncKeyState(key as i32) < 0; } -type Key_Code enum i32 { +Key_Code :: enum i32 { LBUTTON = 0x01, RBUTTON = 0x02, CANCEL = 0x03, diff --git a/core/utf8.odin b/core/utf8.odin index 1c2b97867..f3de5f3d0 100644 --- a/core/utf8.odin +++ b/core/utf8.odin @@ -8,7 +8,7 @@ UTF_MAX :: 4; SURROGATE_MIN :: 0xd800; SURROGATE_MAX :: 0xdfff; -type Accept_Range struct { +Accept_Range :: struct { lo, hi u8; } @@ -40,7 +40,7 @@ accept_sizes := [256]byte{ 0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff }; -proc encode_rune(r rune) -> ([4]byte, int) { +encode_rune :: proc(r rune) -> ([4]byte, int) { buf: [4]byte; i := r as u32; mask: byte : 0x3f; @@ -74,7 +74,7 @@ proc encode_rune(r rune) -> ([4]byte, int) { return buf, 4; } -proc decode_rune(s string) -> (rune, int) { +decode_rune :: proc(s string) -> (rune, int) { n := s.count; if n < 1 { return RUNE_ERROR, 0; @@ -119,7 +119,7 @@ proc decode_rune(s string) -> (rune, int) { } -proc valid_rune(r rune) -> bool { +valid_rune :: proc(r rune) -> bool { if r < 0 { return false; } else if SURROGATE_MIN <= r && r <= SURROGATE_MAX { @@ -130,7 +130,7 @@ proc valid_rune(r rune) -> bool { return true; } -proc valid_string(s string) -> bool { +valid_string :: proc(s string) -> bool { n := s.count; for i := 0; i < n; { si := s[i]; @@ -163,7 +163,7 @@ proc valid_string(s string) -> bool { return true; } -proc rune_count(s string) -> int { +rune_count :: proc(s string) -> int { count := 0; n := s.count; for i := 0; i < n; count++ { @@ -200,7 +200,7 @@ proc rune_count(s string) -> int { } -proc rune_size(r rune) -> int { +rune_size :: proc(r rune) -> int { match { case r < 0: return -1; case r <= 1<<7 - 1: return 1; diff --git a/src/checker/checker.c b/src/checker/checker.c index 64bccbd14..ace13dcab 100644 --- a/src/checker/checker.c +++ b/src/checker/checker.c @@ -308,11 +308,6 @@ bool decl_info_has_init(DeclInfo *d) { } if (d->proc_decl != NULL) { switch (d->proc_decl->kind) { - case_ast_node(pd, ProcDecl, d->proc_decl); - if (pd->body != NULL) { - return true; - } - case_end; case_ast_node(pd, ProcLit, d->proc_decl); if (pd->body != NULL) { return true; @@ -1260,23 +1255,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As DelayedDecl di = {parent_scope, spec}; array_add(&c->delayed_imports, di); case_end; - - case_ast_node(ts, TypeSpec, spec); - if (ts->name->kind != AstNode_Ident) { - error_node(ts->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[ts->name->kind])); - continue; - } - ast_node(n, Ident, ts->name); - - Entity *e = make_entity_type_name(c->allocator, parent_scope, *n, NULL); - e->identifier = ts->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->type_expr = ts->type; - d->init_expr = ts->type; - add_entity_and_decl_info(c, ts->name, e, d); - case_end; - default: error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind])); break; @@ -1293,20 +1271,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As DelayedDecl di = {parent_scope, decl}; array_add(&c->delayed_foreign_libraries, di); case_end; - case_ast_node(pd, ProcDecl, decl); - if (pd->name->kind != AstNode_Ident) { - error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind])); - continue; - } - ast_node(n, Ident, pd->name); - Token token = *n; - Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL, pd->tags); - e->identifier = pd->name; - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->proc_decl = decl; - add_entity_and_decl_info(c, pd->name, e, d); - case_end; - default: if (parent_scope->is_file) { error_node(decl, "Only declarations are allowed at file scope"); diff --git a/src/checker/decl.c b/src/checker/decl.c index 179e6f67c..ec236ef2f 100644 --- a/src/checker/decl.c +++ b/src/checker/decl.c @@ -282,6 +282,10 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init, check_init_constant(c, e, &operand); c->context.iota = (ExactValue){0}; + + if (e->type == t_invalid) { + error(e->token, "Illegal cyclic declaration"); + } } @@ -326,224 +330,119 @@ bool are_signatures_similar_enough(Type *a_, Type *b_) { void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) { GB_ASSERT(e->type == NULL); + if (d->proc_decl->kind != AstNode_ProcLit) { + // TOOD(bill): Better error message + error_node(d->proc_decl, "Expected a procedure to check"); + return; + } Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false, ProcCC_Odin); e->type = proc_type; - if (d->proc_decl->kind == AstNode_ProcDecl) { - ast_node(pd, ProcDecl, d->proc_decl); + ast_node(pd, ProcLit, d->proc_decl); - check_open_scope(c, pd->type); - check_procedure_type(c, proc_type, pd->type); + check_open_scope(c, pd->type); + check_procedure_type(c, proc_type, pd->type); - bool is_foreign = (pd->tags & ProcTag_foreign) != 0; - bool is_link_name = (pd->tags & ProcTag_link_name) != 0; - bool is_export = (pd->tags & ProcTag_export) != 0; - bool is_inline = (pd->tags & ProcTag_inline) != 0; - bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; + bool is_foreign = (pd->tags & ProcTag_foreign) != 0; + bool is_link_name = (pd->tags & ProcTag_link_name) != 0; + bool is_export = (pd->tags & ProcTag_export) != 0; + bool is_inline = (pd->tags & ProcTag_inline) != 0; + bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; - if ((d->scope->is_file || d->scope->is_global) && - str_eq(e->token.string, str_lit("main"))) { - if (proc_type != NULL) { - TypeProc *pt = &proc_type->Proc; - if (pt->param_count != 0 || - pt->result_count != 0) { - gbString str = type_to_string(proc_type); - error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); - gb_string_free(str); - } + if ((d->scope->is_file || d->scope->is_global) && + str_eq(e->token.string, str_lit("main"))) { + if (proc_type != NULL) { + TypeProc *pt = &proc_type->Proc; + if (pt->param_count != 0 || + pt->result_count != 0) { + gbString str = type_to_string(proc_type); + error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); + gb_string_free(str); } } - - if (is_inline && is_no_inline) { - error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); - } - - if (is_foreign && is_link_name) { - error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); - } else if (is_foreign && is_export) { - error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); - } - - - if (pd->body != NULL) { - if (is_foreign) { - error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); - } - - if (proc_type->Proc.calling_convention != ProcCC_Odin) { - error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); - proc_type->Proc.calling_convention = ProcCC_Odin; - } - - d->scope = c->context.scope; - - GB_ASSERT(pd->body->kind == AstNode_BlockStmt); - check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags); - } - - if (is_foreign) { - MapEntity *fp = &c->info.foreign_procs; - AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - String name = proc_decl->name->Ident.string; - if (proc_decl->foreign_name.len > 0) { - name = proc_decl->foreign_name; - } - - e->Procedure.is_foreign = true; - e->Procedure.foreign_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - Type *this_type = base_type(e->type); - Type *other_type = base_type(f->type); - if (!are_signatures_similar_enough(this_type, other_type)) { - error_node(d->proc_decl, - "Redeclaration of #foreign procedure `%.*s` with different type signatures\n" - "\tat %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); - } - } else { - map_entity_set(fp, key, e); - } - } else { - String name = e->token.string; - if (is_link_name) { - AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl; - name = proc_decl->link_name; - } - - if (is_link_name || is_export) { - MapEntity *fp = &c->info.foreign_procs; - - e->Procedure.link_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - // TODO(bill): Better error message? - error_node(d->proc_decl, - "Non unique linking name for procedure `%.*s`\n" - "\tother at %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); - } else { - map_entity_set(fp, key, e); - } - } - } - - check_close_scope(c); - } else if (d->proc_decl->kind == AstNode_ProcLit) { - ast_node(pd, ProcLit, d->proc_decl); - - check_open_scope(c, pd->type); - check_procedure_type(c, proc_type, pd->type); - - bool is_foreign = (pd->tags & ProcTag_foreign) != 0; - bool is_link_name = (pd->tags & ProcTag_link_name) != 0; - bool is_export = (pd->tags & ProcTag_export) != 0; - bool is_inline = (pd->tags & ProcTag_inline) != 0; - bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0; - - if ((d->scope->is_file || d->scope->is_global) && - str_eq(e->token.string, str_lit("main"))) { - if (proc_type != NULL) { - TypeProc *pt = &proc_type->Proc; - if (pt->param_count != 0 || - pt->result_count != 0) { - gbString str = type_to_string(proc_type); - error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str); - gb_string_free(str); - } - } - } - - if (is_inline && is_no_inline) { - error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); - } - - if (is_foreign && is_link_name) { - error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); - } else if (is_foreign && is_export) { - error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); - } - - - if (pd->body != NULL) { - if (is_foreign) { - error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); - } - - if (proc_type->Proc.calling_convention != ProcCC_Odin) { - error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); - proc_type->Proc.calling_convention = ProcCC_Odin; - } - - d->scope = c->context.scope; - - GB_ASSERT(pd->body->kind == AstNode_BlockStmt); - check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags); - } - - if (is_foreign) { - MapEntity *fp = &c->info.foreign_procs; - String name = e->token.string; - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } - - e->Procedure.is_foreign = true; - e->Procedure.foreign_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - Type *this_type = base_type(e->type); - Type *other_type = base_type(f->type); - if (!are_signatures_similar_enough(this_type, other_type)) { - error_node(d->proc_decl, - "Redeclaration of #foreign procedure `%.*s` with different type signatures\n" - "\tat %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); - } - } else { - map_entity_set(fp, key, e); - } - } else { - String name = e->token.string; - if (is_link_name) { - name = pd->link_name; - } - - if (is_link_name || is_export) { - MapEntity *fp = &c->info.foreign_procs; - - e->Procedure.link_name = name; - - HashKey key = hash_string(name); - Entity **found = map_entity_get(fp, key); - if (found) { - Entity *f = *found; - TokenPos pos = f->token.pos; - // TODO(bill): Better error message? - error_node(d->proc_decl, - "Non unique linking name for procedure `%.*s`\n" - "\tother at %.*s(%td:%td)", - LIT(name), LIT(pos.file), pos.line, pos.column); - } else { - map_entity_set(fp, key, e); - } - } - } - - check_close_scope(c); } + + if (is_inline && is_no_inline) { + error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure"); + } + + if (is_foreign && is_link_name) { + error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure"); + } else if (is_foreign && is_export) { + error_node(pd->type, "You cannot apply both `foreign` and `export` to a procedure"); + } + + + if (pd->body != NULL) { + if (is_foreign) { + error_node(pd->body, "A procedure tagged as `#foreign` cannot have a body"); + } + + if (proc_type->Proc.calling_convention != ProcCC_Odin) { + error_node(d->proc_decl, "An internal procedure may only have the Odin calling convention"); + proc_type->Proc.calling_convention = ProcCC_Odin; + } + + d->scope = c->context.scope; + + GB_ASSERT(pd->body->kind == AstNode_BlockStmt); + check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body, pd->tags); + } + + if (is_foreign) { + MapEntity *fp = &c->info.foreign_procs; + String name = e->token.string; + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; + } + + e->Procedure.is_foreign = true; + e->Procedure.foreign_name = name; + + HashKey key = hash_string(name); + Entity **found = map_entity_get(fp, key); + if (found) { + Entity *f = *found; + TokenPos pos = f->token.pos; + Type *this_type = base_type(e->type); + Type *other_type = base_type(f->type); + if (!are_signatures_similar_enough(this_type, other_type)) { + error_node(d->proc_decl, + "Redeclaration of #foreign procedure `%.*s` with different type signatures\n" + "\tat %.*s(%td:%td)", + LIT(name), LIT(pos.file), pos.line, pos.column); + } + } else { + map_entity_set(fp, key, e); + } + } else { + String name = e->token.string; + if (is_link_name) { + name = pd->link_name; + } + + if (is_link_name || is_export) { + MapEntity *fp = &c->info.foreign_procs; + + e->Procedure.link_name = name; + + HashKey key = hash_string(name); + Entity **found = map_entity_get(fp, key); + if (found) { + Entity *f = *found; + TokenPos pos = f->token.pos; + // TODO(bill): Better error message? + error_node(d->proc_decl, + "Non unique linking name for procedure `%.*s`\n" + "\tother at %.*s(%td:%td)", + LIT(name), LIT(pos.file), pos.line, pos.column); + } else { + map_entity_set(fp, key, e); + } + } + } + + check_close_scope(c); } void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) { diff --git a/src/checker/expr.c b/src/checker/expr.c index 08f919827..33dfa9e44 100644 --- a/src/checker/expr.c +++ b/src/checker/expr.c @@ -137,43 +137,6 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie switch (spec->kind) { case_ast_node(bd, BadDecl, spec); case_end; - case_ast_node(ts, TypeSpec, spec); - if (ts->name->kind != AstNode_Ident) { - error_node(ts->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[ts->name->kind])); - break; - } - - Token name_token = ts->name->Ident; - - Entity *e = make_entity_type_name(c->allocator, c->context.scope, name_token, NULL); - e->identifier = ts->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->type_expr = ts->type; - - add_entity_and_decl_info(c, ts->name, e, d); - - DelayedEntity delay = {ts->name, e, d}; - array_add(delayed_entities, delay); - - - if (dof != NULL) { - if (str_eq(name_token.string, str_lit("_"))) { - dof->other_fields[dof->other_field_index++] = e; - } else { - HashKey key = hash_string(name_token.string); - if (map_entity_get(dof->entity_map, key) != NULL) { - // TODO(bill): Scope checking already checks the declaration - error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string)); - } else { - map_entity_set(dof->entity_map, key, e); - dof->other_fields[dof->other_field_index++] = e; - } - add_entity(c, c->context.scope, ts->name, e); - add_entity_use(c, ts->name, e); - } - } - case_end; } } case_end; @@ -975,7 +938,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) { } if (e == e_iota) { if (c->context.iota.kind == ExactValue_Invalid) { - error(e->token, "Use of `iota` outside a constant declaration is not allowed"); + error(e->token, "Use of `iota` outside a enumeration is not allowed"); return; } o->value = c->context.iota; @@ -1141,6 +1104,11 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { } case_end; + case_ast_node(ht, HelperType, e); + type = check_type(c, ht->type); + goto end; + case_end; + case_ast_node(pt, PointerType, e); Type *elem = check_type(c, pt->type); type = make_type_pointer(c->allocator, elem); @@ -4825,6 +4793,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "{"); str = gb_string_appendc(str, "}"); case_end; + + case_ast_node(ht, HelperType, node); + str = gb_string_appendc(str, "type "); + str = write_expr_to_string(str, ht->type); + case_end; } return str; diff --git a/src/checker/stmt.c b/src/checker/stmt.c index d5848a2b2..c4c7cf3f2 100644 --- a/src/checker/stmt.c +++ b/src/checker/stmt.c @@ -1170,36 +1170,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { switch (spec->kind) { case_ast_node(bd, BadDecl, spec); case_end; - case_ast_node(ts, TypeSpec, spec); - // NOTE(bill): Handled elsewhere - case_end; - default: error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind])); break; } } case_end; - - case_ast_node(pd, ProcDecl, node); - // NOTE(bill): Handled elsewhere - #if 1 - // NOTE(bill): This must be handled here so it has access to the parent scope stuff - // e.g. using - if (pd->name->kind != AstNode_Ident) { - error_node(pd->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[pd->name->kind])); - break; - } - - Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL, pd->tags); - e->identifier = pd->name; - - DeclInfo *d = make_declaration_info(c->allocator, e->scope); - d->proc_decl = node; - - add_entity_and_decl_info(c, pd->name, e, d); - check_entity_decl(c, e, d, NULL); - #endif - case_end; } } diff --git a/src/parser.c b/src/parser.c index 1a659da7a..8546e692a 100644 --- a/src/parser.c +++ b/src/parser.c @@ -281,15 +281,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \ AstNodeArray values; \ u64 tags; \ }) \ - AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \ - AstNode *name; \ - AstNode *type; \ - AstNode *body; \ - u64 tags; \ - String foreign_name; \ - String link_name; \ - AstNode *note; \ - }) \ AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \ Token token, filepath; \ String base_dir; \ @@ -303,6 +294,10 @@ AST_NODE_KIND(_DeclEnd, "", i32) \ bool is_using; \ }) \ AST_NODE_KIND(_TypeBegin, "", i32) \ + AST_NODE_KIND(HelperType, "type", struct { \ + Token token; \ + AstNode *type; \ + }) \ AST_NODE_KIND(ProcType, "procedure type", struct { \ Token token; \ AstNodeArray params; \ @@ -501,8 +496,6 @@ Token ast_node_token(AstNode *node) { return node->GenericDecl.token; case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names.e[0]); - case AstNode_ProcDecl: - return ast_node_token(node->ProcDecl.name); case AstNode_ForeignLibrary: return node->ForeignLibrary.token; @@ -519,6 +512,10 @@ Token ast_node_token(AstNode *node) { return ast_node_token(node->Field.type); } } + + + case AstNode_HelperType: + return node->HelperType.token; case AstNode_ProcType: return node->ProcType.token; case AstNode_PointerType: @@ -969,6 +966,15 @@ AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using return result; } + +AstNode *make_helper_type(AstFile *f, Token token, AstNode *type) { + AstNode *result = make_node(f, AstNode_HelperType); + result->HelperType.token = token; + result->HelperType.type = type; + return result; +} + + AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) { AstNode *result = make_node(f, AstNode_ProcType); result->ProcType.token = token; @@ -979,17 +985,6 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr return result; } -AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) { - AstNode *result = make_node(f, AstNode_ProcDecl); - result->ProcDecl.name = name; - result->ProcDecl.type = proc_type; - result->ProcDecl.body = body; - result->ProcDecl.tags = tags; - result->ProcDecl.foreign_name = foreign_name; - result->ProcDecl.link_name = link_name; - return result; -} - AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) { AstNode *result = make_node(f, AstNode_PointerType); result->PointerType.token = token; @@ -1264,6 +1259,52 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) { return expect_token(f, kind); } +bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) { + if (s == NULL) { + return false; + } + + switch (s->kind) { + case AstNode_HelperType: + return is_semicolon_optional_for_node(f, s->HelperType.type); + + case AstNode_StructType: + case AstNode_UnionType: + case AstNode_RawUnionType: + case AstNode_EnumType: + return true; + case AstNode_ProcLit: + return true; + + case AstNode_ValueDecl: + if (!s->ValueDecl.is_var) { + if (s->ValueDecl.values.count > 0) { + AstNode *last = s->ValueDecl.values.e[s->ValueDecl.values.count-1]; + return is_semicolon_optional_for_node(f, last); + } + } + break; + + case AstNode_GenericDecl: + if (s->GenericDecl.close.kind == Token_CloseBrace) { + return true; + } else if (s->GenericDecl.token.kind == Token_type) { + if (f->prev_token.kind == Token_CloseBrace) { + return true; + } + } + break; + + case AstNode_TypeSpec: + if (f->prev_token.kind == Token_CloseBrace) { + return true; + } + break; + } + + return false; +} + void expect_semicolon(AstFile *f, AstNode *s) { if (allow_token(f, Token_Semicolon)) { return; @@ -1277,24 +1318,8 @@ void expect_semicolon(AstFile *f, AstNode *s) { if (s != NULL) { if (prev_token.pos.line != f->curr_token.pos.line) { - switch (s->kind) { - case AstNode_ProcDecl: + if (is_semicolon_optional_for_node(f, s)) { return; - case AstNode_GenericDecl: - if (s->GenericDecl.close.kind == Token_CloseBrace) { - return; - } else if (s->GenericDecl.token.kind == Token_type) { - if (f->prev_token.kind == Token_CloseBrace) { - return; - } - } - break; - - case AstNode_TypeSpec: - if (f->prev_token.kind == Token_CloseBrace) { - return; - } - break; } } else { switch (s->kind) { @@ -1319,7 +1344,6 @@ AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_nam AstNodeArray parse_stmt_list(AstFile *f); AstNode * parse_stmt(AstFile *f); AstNode * parse_body(AstFile *f); -AstNode * parse_proc_decl(AstFile *f); void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results); @@ -1571,6 +1595,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n AstNodeArray parse_lhs_expr_list(AstFile *f); AstNodeArray parse_rhs_expr_list(AstFile *f); AstNode * parse_simple_stmt (AstFile *f); +AstNode * parse_type (AstFile *f); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { if (statement == NULL) { @@ -1745,10 +1770,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) { String foreign_name = {0}; String link_name = {0}; AstNode *type = parse_proc_type(f, &foreign_name, &link_name); + u64 tags = type->ProcType.tags; if (f->curr_token.kind == Token_OpenBrace) { - u64 tags = type->ProcType.tags; - if ((tags & ProcTag_foreign) != 0) { syntax_error(token, "A procedure tagged as `#foreign` cannot have a body"); } @@ -1760,6 +1784,13 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return make_proc_lit(f, type, body, tags, foreign_name, link_name); } + if ((tags & ProcTag_foreign) != 0) { + return make_proc_lit(f, type, NULL, tags, foreign_name, link_name); + } + if ((tags & ProcTag_link_name) != 0) { + syntax_error(token, "A procedure typed cannot be tagged with `#link_name`"); + } + return type; } @@ -1932,7 +1963,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { return operand; } -AstNode *parse_type(AstFile *f); AstNode *parse_unary_expr(AstFile *f, bool lhs) { switch (f->curr_token.kind) { @@ -2240,17 +2270,6 @@ PARSE_SPEC_PROC(parse_include_spec) { AstNode *parse_decl(AstFile *f) { switch (f->curr_token.kind) { - // case Token_var: - // case Token_const: - // return parse_generic_decl(f, f->curr_token.kind, parse_value_spec); - - case Token_type: - return parse_generic_decl(f, f->curr_token.kind, parse_type_spec); - - case Token_proc: - // TODO(bill): Should I allow procedures to use the generic declaration syntax? - return parse_proc_decl(f); - case Token_import: return parse_generic_decl(f, f->curr_token.kind, parse_import_spec); case Token_include: @@ -2504,6 +2523,12 @@ AstNode *parse_identifier_or_type(AstFile *f) { return e; } + case Token_type: { + Token token = expect_token(f, Token_type); + AstNode *type = parse_type(f); + return make_helper_type(f, token, type); + } + case Token_Pointer: { Token token = expect_token(f, Token_Pointer); AstNode *elem = parse_type(f); @@ -2681,7 +2706,7 @@ AstNode *parse_body(AstFile *f) { } - +/* AstNode *parse_proc_decl(AstFile *f) { if (look_ahead_token_kind(f, 1) == Token_OpenParen) { // NOTE(bill): It's an anonymous procedure @@ -2720,7 +2745,7 @@ AstNode *parse_proc_decl(AstFile *f) { } return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name); -} +} */ AstNode *parse_if_stmt(AstFile *f) { if (f->curr_proc == NULL) { diff --git a/src/ssa.c b/src/ssa.c index ca77c385c..6a2b4f8f4 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -3978,104 +3978,96 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) { } gb_temp_arena_memory_end(tmp); - } - case_end; - - case_ast_node(gd, GenericDecl, node); - for_array(spec_index, gd->specs) { - AstNode *spec = gd->specs.e[spec_index]; - switch (spec->kind) { - case_ast_node(ts, TypeSpec, spec); - // NOTE(bill): Generate a new name - // parent_proc.name-guid - String ts_name = ts->name->Ident.string; - isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1; - u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); - i32 guid = cast(i32)proc->module->members.entries.count; - name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid); - String name = make_string(name_text, name_len-1); - - Entity **found = map_entity_get(&proc->module->info->definitions, hash_pointer(ts->name)); - GB_ASSERT(found != NULL); - Entity *e = *found; - ssaValue *value = ssa_make_value_type_name(proc->module->allocator, - name, e->type); - map_string_set(&proc->module->type_names, hash_pointer(e->type), name); - ssa_gen_global_type_name(proc->module, e, name); - case_end; - } - } - case_end; - - case_ast_node(pd, ProcDecl, node); - if (pd->body != NULL) { - CheckerInfo *info = proc->module->info; - - Entity **found = map_entity_get(&info->definitions, hash_pointer(pd->name)); - GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); - Entity *e = *found; - - - if (map_entity_get(&proc->module->min_dep_map, hash_pointer(e)) == NULL) { - // NOTE(bill): Nothing depends upon it so doesn't need to be built - break; - } - - // NOTE(bill): Generate a new name - // parent.name-guid - String original_name = pd->name->Ident.string; - String pd_name = original_name; - if (pd->link_name.len > 0) { - pd_name = pd->link_name; - } - - isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1; - u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); - i32 guid = cast(i32)proc->children.count; - name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(pd_name), guid); - String name = make_string(name_text, name_len-1); - - - ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e, e->type, pd->type, pd->body, name); - - value->Proc.tags = pd->tags; - value->Proc.parent = proc; - - ssa_module_add_value(proc->module, e, value); - array_add(&proc->children, &value->Proc); - array_add(&proc->module->procs_to_generate, value); } else { - CheckerInfo *info = proc->module->info; + for_array(i, vd->names) { + AstNode *ident = vd->names.e[i]; + GB_ASSERT(ident->kind == AstNode_Ident); + Entity *e = entity_of_ident(proc->module->info, ident); + GB_ASSERT(e != NULL); + switch (e->kind) { + case Entity_TypeName: { + // NOTE(bill): Generate a new name + // parent_proc.name-guid + String ts_name = e->token.string; + isize name_len = proc->name.len + 1 + ts_name.len + 1 + 10 + 1; + u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); + i32 guid = cast(i32)proc->module->members.entries.count; + name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(ts_name), guid); + String name = make_string(name_text, name_len-1); - Entity **found = map_entity_get(&info->definitions, hash_pointer(pd->name)); - GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); - Entity *e = *found; + ssaValue *value = ssa_make_value_type_name(proc->module->allocator, + name, e->type); + map_string_set(&proc->module->type_names, hash_pointer(e->type), name); + ssa_gen_global_type_name(proc->module, e, name); + } break; + case Entity_Procedure: { + DeclInfo **decl_info = map_decl_info_get(&proc->module->info->entities, hash_pointer(e)); + GB_ASSERT(decl_info != NULL); + DeclInfo *dl = *decl_info; + ast_node(pd, ProcLit, dl->proc_decl); + if (pd->body != NULL) { + CheckerInfo *info = proc->module->info; - // FFI - Foreign function interace - String original_name = pd->name->Ident.string; - String name = original_name; - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } + if (map_entity_get(&proc->module->min_dep_map, hash_pointer(e)) == NULL) { + // NOTE(bill): Nothing depends upon it so doesn't need to be built + break; + } - ssaValue *value = ssa_make_value_procedure(proc->module->allocator, - proc->module, e, e->type, pd->type, pd->body, name); + // NOTE(bill): Generate a new name + // parent.name-guid + String original_name = e->token.string; + String pd_name = original_name; + if (pd->link_name.len > 0) { + pd_name = pd->link_name; + } - value->Proc.tags = pd->tags; + isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1; + u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); + i32 guid = cast(i32)proc->children.count; + name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(pd_name), guid); + String name = make_string(name_text, name_len-1); - ssa_module_add_value(proc->module, e, value); - ssa_build_proc(value, proc); - if (value->Proc.tags & ProcTag_foreign) { - HashKey key = hash_string(name); - ssaValue **prev_value = map_ssa_value_get(&proc->module->members, key); - if (prev_value == NULL) { - // NOTE(bill): Don't do mutliple declarations in the IR - map_ssa_value_set(&proc->module->members, key, value); + ssaValue *value = ssa_make_value_procedure(proc->module->allocator, + proc->module, e, e->type, pd->type, pd->body, name); + + value->Proc.tags = pd->tags; + value->Proc.parent = proc; + + ssa_module_add_value(proc->module, e, value); + array_add(&proc->children, &value->Proc); + array_add(&proc->module->procs_to_generate, value); + } else { + CheckerInfo *info = proc->module->info; + + // FFI - Foreign function interace + String original_name = e->token.string; + String name = original_name; + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; + } + + ssaValue *value = ssa_make_value_procedure(proc->module->allocator, + proc->module, e, e->type, pd->type, pd->body, name); + + value->Proc.tags = pd->tags; + + ssa_module_add_value(proc->module, e, value); + ssa_build_proc(value, proc); + + if (value->Proc.tags & ProcTag_foreign) { + HashKey key = hash_string(name); + ssaValue **prev_value = map_ssa_value_get(&proc->module->members, key); + if (prev_value == NULL) { + // NOTE(bill): Don't do mutliple declarations in the IR + map_ssa_value_set(&proc->module->members, key, value); + } + } else { + array_add(&proc->children, &value->Proc); + } + } + } break; } - } else { - array_add(&proc->children, &value->Proc); } } case_end; @@ -5034,48 +5026,25 @@ void ssa_gen_tree(ssaGen *s) { } break; case Entity_Procedure: { - if (decl->proc_decl->kind == AstNode_ProcDecl) { - AstNodeProcDecl *pd = &decl->proc_decl->ProcDecl; - String original_name = name; - AstNode *body = pd->body; - if (e->Procedure.is_foreign) { - name = e->token.string; // NOTE(bill): Don't use the mangled name - } - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } else if (pd->link_name.len > 0) { - name = pd->link_name; - } + ast_node(pd, ProcLit, decl->proc_decl); + String original_name = name; + AstNode *body = pd->body; + if (e->Procedure.is_foreign) { + name = e->token.string; // NOTE(bill): Don't use the mangled name + } + if (pd->foreign_name.len > 0) { + name = pd->foreign_name; + } else if (pd->link_name.len > 0) { + name = pd->link_name; + } - ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); - p->Proc.tags = pd->tags; + ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); + p->Proc.tags = pd->tags; - ssa_module_add_value(m, e, p); - HashKey hash_name = hash_string(name); - if (map_ssa_value_get(&m->members, hash_name) == NULL) { - map_ssa_value_set(&m->members, hash_name, p); - } - } else if (decl->proc_decl->kind == AstNode_ProcLit) { - AstNodeProcLit *pd = &decl->proc_decl->ProcLit; - String original_name = name; - AstNode *body = pd->body; - if (e->Procedure.is_foreign) { - name = e->token.string; // NOTE(bill): Don't use the mangled name - } - if (pd->foreign_name.len > 0) { - name = pd->foreign_name; - } else if (pd->link_name.len > 0) { - name = pd->link_name; - } - - ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); - p->Proc.tags = pd->tags; - - ssa_module_add_value(m, e, p); - HashKey hash_name = hash_string(name); - if (map_ssa_value_get(&m->members, hash_name) == NULL) { - map_ssa_value_set(&m->members, hash_name, p); - } + ssa_module_add_value(m, e, p); + HashKey hash_name = hash_string(name); + if (map_ssa_value_get(&m->members, hash_name) == NULL) { + map_ssa_value_set(&m->members, hash_name, p); } } break; }