aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/container/intrusive/list/intrusive_list.odin46
-rw-r--r--core/encoding/json/marshal.odin12
-rw-r--r--core/fmt/doc.odin3
-rw-r--r--core/fmt/fmt.odin61
-rw-r--r--core/mem/doc.odin2
-rw-r--r--core/mem/mem.odin2
-rw-r--r--core/odin/ast/ast.odin28
-rw-r--r--core/odin/parser/parser.odin5
-rw-r--r--core/os/os_linux.odin4
-rw-r--r--core/runtime/core.odin2
-rw-r--r--core/sys/windows/kernel32.odin15
11 files changed, 152 insertions, 28 deletions
diff --git a/core/container/intrusive/list/intrusive_list.odin b/core/container/intrusive/list/intrusive_list.odin
index 88e21edc5..7302f24f5 100644
--- a/core/container/intrusive/list/intrusive_list.odin
+++ b/core/container/intrusive/list/intrusive_list.odin
@@ -20,10 +20,10 @@ List :: struct {
Node :: struct {
- next, prev: ^Node,
+ prev, next: ^Node,
}
-push_front :: proc(list: ^List, node: ^Node) {
+push_front :: proc "contextless" (list: ^List, node: ^Node) {
if list.head != nil {
list.head.prev = node
node.prev, node.next = nil, list.head
@@ -34,7 +34,7 @@ push_front :: proc(list: ^List, node: ^Node) {
}
}
-push_back :: proc(list: ^List, node: ^Node) {
+push_back :: proc "contextless" (list: ^List, node: ^Node) {
if list.tail != nil {
list.tail.next = node
node.prev, node.next = list.tail, nil
@@ -45,7 +45,7 @@ push_back :: proc(list: ^List, node: ^Node) {
}
}
-remove :: proc(list: ^List, node: ^Node) {
+remove :: proc "contextless" (list: ^List, node: ^Node) {
if node != nil {
if node.next != nil {
node.next.prev = node.prev
@@ -83,12 +83,34 @@ remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
}
}
+remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^Node) -> bool) {
+ for node := list.head; node != nil; {
+ next := node.next
+ if to_erase(node) {
+ if node.next != nil {
+ node.next.prev = node.prev
+ }
+ if node.prev != nil {
+ node.prev.next = node.next
+ }
+ if list.head == node {
+ list.head = node.next
+ }
+ if list.tail == node {
+ list.tail = node.prev
+ }
+ }
+ node = next
+ }
+}
+
+
-is_empty :: proc(list: ^List) -> bool {
+is_empty :: proc "contextless" (list: ^List) -> bool {
return list.head == nil
}
-pop_front :: proc(list: ^List) -> ^Node {
+pop_front :: proc "contextless" (list: ^List) -> ^Node {
link := list.head
if link == nil {
return nil
@@ -108,7 +130,7 @@ pop_front :: proc(list: ^List) -> ^Node {
return link
}
-pop_back :: proc(list: ^List) -> ^Node {
+pop_back :: proc "contextless" (list: ^List) -> ^Node {
link := list.tail
if link == nil {
return nil
@@ -134,25 +156,25 @@ Iterator :: struct($T: typeid) {
offset: uintptr,
}
-iterator_head :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
+iterator_head :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.head, offset_of_by_string(T, field_name)}
}
-iterator_tail :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
+iterator_tail :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.tail, offset_of_by_string(T, field_name)}
}
-iterator_from_node :: proc(node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
+iterator_from_node :: proc "contextless" (node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {node, offset_of_by_string(T, field_name)}
}
-iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
+iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
@@ -162,7 +184,7 @@ iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
return (^T)(uintptr(node) - it.offset), true
}
-iterate_prev :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
+iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin
index 77a5bf8df..43f464bdb 100644
--- a/core/encoding/json/marshal.odin
+++ b/core/encoding/json/marshal.odin
@@ -404,7 +404,7 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
switch opt.spec {
case .JSON, .JSON5:
io.write_quoted_string(w, name) or_return
- io.write_string(w, ": ") or_return
+ io.write_string(w, ": " if opt.pretty else ":") or_return
case .MJSON:
if opt.mjson_keys_use_quotes {
@@ -412,11 +412,11 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
} else {
io.write_string(w, name) or_return
}
-
+
if opt.mjson_keys_use_equal_sign {
- io.write_string(w, " = ") or_return
+ io.write_string(w, " = " if opt.pretty else "=") or_return
} else {
- io.write_string(w, ": ") or_return
+ io.write_string(w, ": " if opt.pretty else ":") or_return
}
}
@@ -446,7 +446,7 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
switch opt.spec {
case .JSON, .JSON5:
if iteration > 0 {
- io.write_string(w, ", ") or_return
+ io.write_byte(w, ',') or_return
if opt.pretty {
io.write_byte(w, '\n') or_return
@@ -462,7 +462,7 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
io.write_byte(w, '\n') or_return
} else {
// comma separation necessary for non pretty output!
- io.write_string(w, ", ") or_return
+ io.write_byte(w, ',') or_return
}
}
diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin
index 991058661..597342e76 100644
--- a/core/fmt/doc.odin
+++ b/core/fmt/doc.odin
@@ -35,6 +35,8 @@ Floating-point, complex numbers, and quaternions:
%F synonym for %f
%h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd)
%H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD)
+ %m number of bytes in the best unit of measurement, e.g. 123.45mib
+ %M number of bytes in the best unit of measurement, e.g. 123.45MiB
String and slice of bytes
%s the uninterpreted bytes of the string or slice
%q a double-quoted string safely escaped with Odin syntax
@@ -85,6 +87,7 @@ Other flags:
add leading 0z for dozenal (%#z)
add leading 0x or 0X for hexadecimal (%#x or %#X)
remove leading 0x for %p (%#p)
+ add a space between bytes and the unit of measurement (%#m or %#M)
' ' (space) leave a space for elided sign in numbers (% d)
0 pad with leading zeros rather than spaces
diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin
index b3b8067e8..ab57209c3 100644
--- a/core/fmt/fmt.odin
+++ b/core/fmt/fmt.odin
@@ -1048,6 +1048,65 @@ _fmt_int_128 :: proc(fi: ^Info, u: u128, base: int, is_signed: bool, bit_size: i
fi.zero = false
_pad(fi, s)
}
+// Units of measurements:
+__MEMORY_LOWER := " b kib mib gib tib pib eib"
+__MEMORY_UPPER := " B KiB MiB GiB TiB PiB EiB"
+// Formats an integer value as bytes with the best representation.
+//
+// Inputs:
+// - fi: A pointer to an Info structure
+// - u: The integer value to format
+// - is_signed: A boolean indicating if the integer is signed
+// - bit_size: The bit size of the integer
+// - digits: A string containing the digits for formatting
+//
+_fmt_memory :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, units: string) {
+ abs, neg := strconv.is_integer_negative(u, is_signed, bit_size)
+
+ // Default to a precision of 2, but if less than a kb, 0
+ prec := fi.prec if (fi.prec_set || abs < mem.Kilobyte) else 2
+
+ div, off, unit_len := 1, 0, 1
+ for n := abs; n >= mem.Kilobyte; n /= mem.Kilobyte {
+ div *= mem.Kilobyte
+ off += 4
+
+ // First iteration is slightly different because you go from
+ // units of length 1 to units of length 2.
+ if unit_len == 1 {
+ off = 2
+ unit_len = 3
+ }
+ }
+
+ // If hash, we add a space between the value and the suffix.
+ if fi.hash {
+ unit_len += 1
+ } else {
+ off += 1
+ }
+
+ amt := f64(abs) / f64(div)
+ if neg {
+ amt = -amt
+ }
+
+ buf: [256]byte
+ str := strconv.append_float(buf[:], amt, 'f', prec, 64)
+
+ // Add the unit at the end.
+ copy(buf[len(str):], units[off:off+unit_len])
+ str = string(buf[:len(str)+unit_len])
+
+ if !fi.plus {
+ // Strip sign from "+<value>" but not "+Inf".
+ if str[0] == '+' && str[1] != 'I' {
+ str = str[1:]
+ }
+ }
+
+ _pad(fi, str)
+}
// Hex Values:
__DIGITS_LOWER := "0123456789abcdefx"
__DIGITS_UPPER := "0123456789ABCDEFX"
@@ -1096,6 +1155,8 @@ fmt_int :: proc(fi: ^Info, u: u64, is_signed: bool, bit_size: int, verb: rune) {
io.write_string(fi.writer, "U+", &fi.n)
_fmt_int(fi, u, 16, false, bit_size, __DIGITS_UPPER)
}
+ case 'm': _fmt_memory(fi, u, is_signed, bit_size, __MEMORY_LOWER)
+ case 'M': _fmt_memory(fi, u, is_signed, bit_size, __MEMORY_UPPER)
case:
fmt_bad_verb(fi, verb)
diff --git a/core/mem/doc.odin b/core/mem/doc.odin
index 295a69e96..e232428c2 100644
--- a/core/mem/doc.odin
+++ b/core/mem/doc.odin
@@ -24,7 +24,7 @@ main :: proc() {
_main()
for _, leak in track.allocation_map {
- fmt.printf("%v leaked %v bytes\n", leak.location, leak.size)
+ fmt.printf("%v leaked %m\n", leak.location, leak.size)
}
for bad_free in track.bad_free_array {
fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
diff --git a/core/mem/mem.odin b/core/mem/mem.odin
index a06579d71..dd985d5dd 100644
--- a/core/mem/mem.odin
+++ b/core/mem/mem.odin
@@ -8,6 +8,8 @@ Kilobyte :: runtime.Kilobyte
Megabyte :: runtime.Megabyte
Gigabyte :: runtime.Gigabyte
Terabyte :: runtime.Terabyte
+Petabyte :: runtime.Petabyte
+Exabyte :: runtime.Exabyte
set :: proc "contextless" (data: rawptr, value: byte, len: int) -> rawptr {
return runtime.memset(data, i32(value), len)
diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin
index f2c3e029b..b462a3107 100644
--- a/core/odin/ast/ast.odin
+++ b/core/odin/ast/ast.odin
@@ -553,6 +553,27 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
return
}
+strip_or_return_expr :: proc(expr: ^Expr) -> (val: ^Expr) {
+ val = expr
+ if expr == nil {
+ return
+ }
+ for {
+ inner: ^Expr
+ #partial switch e in val.derived {
+ case ^Or_Return_Expr:
+ inner = e.expr
+ case ^Paren_Expr:
+ inner = e.expr
+ }
+ if inner == nil {
+ break
+ }
+ val = inner
+ }
+ return
+}
+
Field_Flags :: distinct bit_set[Field_Flag]
Field_Flag :: enum {
@@ -563,7 +584,7 @@ Field_Flag :: enum {
Using,
No_Alias,
C_Vararg,
- Auto_Cast,
+ Const,
Any_Int,
Subtype,
By_Ptr,
@@ -582,7 +603,7 @@ field_flag_strings := [Field_Flag]string{
.Using = "using",
.No_Alias = "#no_alias",
.C_Vararg = "#c_vararg",
- .Auto_Cast = "auto_cast",
+ .Const = "#const",
.Any_Int = "#any_int",
.Subtype = "#subtype",
.By_Ptr = "#by_ptr",
@@ -596,6 +617,7 @@ field_flag_strings := [Field_Flag]string{
field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
{"no_alias", .No_Alias},
{"c_vararg", .C_Vararg},
+ {"const", .Const},
{"any_int", .Any_Int},
{"subtype", .Subtype},
{"by_ptr", .By_Ptr},
@@ -616,7 +638,7 @@ Field_Flags_Signature :: Field_Flags{
.Using,
.No_Alias,
.C_Vararg,
- .Auto_Cast,
+ .Const,
.Any_Int,
.By_Ptr,
.Default_Parameters,
diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin
index da6530911..39280061f 100644
--- a/core/odin/parser/parser.odin
+++ b/core/odin/parser/parser.odin
@@ -1666,9 +1666,6 @@ is_token_field_prefix :: proc(p: ^Parser) -> ast.Field_Flag {
case .Using:
advance_token(p)
return .Using
- case .Auto_Cast:
- advance_token(p)
- return .Auto_Cast
case .Hash:
tok: tokenizer.Token
advance_token(p)
@@ -2153,7 +2150,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
}
}
- #partial switch e in ast.unparen_expr(expr).derived_expr {
+ #partial switch e in ast.strip_or_return_expr(expr).derived_expr {
case ^ast.Proc_Lit:
if e.inlining != .None && e.inlining != pi {
error(p, expr.pos, "both 'inline' and 'no_inline' cannot be applied to a procedure literal")
diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin
index 1a4c1fddb..51a14ab44 100644
--- a/core/os/os_linux.odin
+++ b/core/os/os_linux.odin
@@ -441,7 +441,7 @@ pollfd :: struct {
sigset_t :: distinct u64
foreign libc {
- @(link_name="__errno_location") __errno_location :: proc() -> ^int ---
+ @(link_name="__errno_location") __errno_location :: proc() -> ^c.int ---
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
@(link_name="get_nprocs") _unix_get_nprocs :: proc() -> c.int ---
@@ -488,7 +488,7 @@ _get_errno :: proc(res: int) -> Errno {
// get errno from libc
get_last_error :: proc "contextless" () -> int {
- return __errno_location()^
+ return int(__errno_location()^)
}
personality :: proc(persona: u64) -> (Errno) {
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index 4f85cf50e..0634f573a 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -337,6 +337,8 @@ Kilobyte :: 1024 * Byte
Megabyte :: 1024 * Kilobyte
Gigabyte :: 1024 * Megabyte
Terabyte :: 1024 * Gigabyte
+Petabyte :: 1024 * Terabyte
+Exabyte :: 1024 * Petabyte
// Logging stuff
diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin
index 2b63595a4..0c612a974 100644
--- a/core/sys/windows/kernel32.odin
+++ b/core/sys/windows/kernel32.odin
@@ -132,6 +132,21 @@ foreign kernel32 {
SetThreadPriority :: proc(thread: HANDLE, priority: c_int) -> BOOL ---
GetExitCodeThread :: proc(thread: HANDLE, exit_code: ^DWORD) -> BOOL ---
TerminateThread :: proc(thread: HANDLE, exit_code: DWORD) -> BOOL ---
+ SuspendThread :: proc(hThread: HANDLE) -> DWORD ---
+
+ GetProcessAffinityMask :: proc(
+ hProcess: HANDLE,
+ lpProcessAffinityMask: PDWORD_PTR,
+ lpSystemAffinityMask: PDWORD_PTR,
+ ) -> BOOL ---
+ SetProcessAffinityMask :: proc(
+ hProcess: HANDLE,
+ dwProcessAffinityMask: DWORD_PTR,
+ ) -> BOOL ---
+ SetThreadAffinityMask :: proc(
+ hThread: HANDLE,
+ dwThreadAffinityMask: DWORD_PTR,
+ ) -> DWORD_PTR ---
CreateSemaphoreW :: proc(attributes: LPSECURITY_ATTRIBUTES, initial_count, maximum_count: LONG, name: LPCWSTR) -> HANDLE ---
ReleaseSemaphore :: proc(semaphore: HANDLE, release_count: LONG, previous_count: ^LONG) -> BOOL ---