From 0a9bb2e8e00f3b6fdb583efe96a497de438c4c08 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 14 Apr 2025 21:07:04 +0200 Subject: [PATCH] Fix to simple a += b overload fallback. Renaming and reordering in the stdlib. --- lib/std/atomic.c3 | 2 +- lib/std/core/os/{ => wasm}/wasm_memory.c3 | 0 lib/std/math/{math_complex.c3 => complex.c3} | 2 + lib/std/math/{math_easings.c3 => easing.c3} | 0 lib/std/math/{math_matrix.c3 => matrix.c3} | 0 .../{math_quaternion.c3 => quaternion.c3} | 0 .../math/runtime/{math_i128.c3 => i128.c3} | 16 +- lib/std/math/runtime/math_supplemental.c3 | 6 +- lib/std/net/http.c3 | 406 ------------------ lib/std/net/os/win32.c3 | 2 +- lib/std/net/socket.c3 | 2 +- lib/std/net/socket_private.c3 | 2 +- lib/std/os/freebsd/general.c3 | 2 + lib/std/os/macos/darwin.c3 | 12 + lib/std/os/macos/general.c3 | 2 + lib/std/os/netbsd/general.c3 | 1 + lib/std/os/openbsd/general.c3 | 2 + lib/std/os/posix/clock.c3 | 68 +++ lib/std/os/posix/general.c3 | 3 +- lib/std/os/posix/net.c3 | 1 + lib/std/os/win32/clock.c3 | 6 + lib/std/os/win32/files.c3 | 1 + lib/std/os/win32/wsa.c3 | 11 +- lib/std/text/i18n.c3 | 17 - lib/std/time/os/time_darwin.c3 | 17 +- lib/std/time/os/time_posix.c3 | 71 +-- lib/std/time/os/time_win32.c3 | 11 +- releasenotes.md | 3 +- src/compiler/sema_expr.c | 7 +- test/unit/stdlib/math/math_complex.c3 | 14 +- 30 files changed, 142 insertions(+), 545 deletions(-) rename lib/std/core/os/{ => wasm}/wasm_memory.c3 (100%) rename lib/std/math/{math_complex.c3 => complex.c3} (93%) rename lib/std/math/{math_easings.c3 => easing.c3} (100%) rename lib/std/math/{math_matrix.c3 => matrix.c3} (100%) rename lib/std/math/{math_quaternion.c3 => quaternion.c3} (100%) rename lib/std/math/runtime/{math_i128.c3 => i128.c3} (97%) delete mode 100644 lib/std/net/http.c3 create mode 100644 lib/std/os/freebsd/general.c3 create mode 100644 lib/std/os/macos/general.c3 create mode 100644 lib/std/os/netbsd/general.c3 create mode 100644 lib/std/os/openbsd/general.c3 create mode 100644 lib/std/os/posix/clock.c3 create mode 100644 lib/std/os/posix/net.c3 create mode 100644 lib/std/os/win32/clock.c3 delete mode 100644 lib/std/text/i18n.c3 diff --git a/lib/std/atomic.c3 b/lib/std/atomic.c3 index 50931711b..3e5748e47 100644 --- a/lib/std/atomic.c3 +++ b/lib/std/atomic.c3 @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Eduardo José Gómez Hernández. All rights reserved. +// Copyright (c) 2023-2025 Eduardo José Gómez Hernández. All rights reserved. // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::atomic::types{Type}; diff --git a/lib/std/core/os/wasm_memory.c3 b/lib/std/core/os/wasm/wasm_memory.c3 similarity index 100% rename from lib/std/core/os/wasm_memory.c3 rename to lib/std/core/os/wasm/wasm_memory.c3 diff --git a/lib/std/math/math_complex.c3 b/lib/std/math/complex.c3 similarity index 93% rename from lib/std/math/math_complex.c3 rename to lib/std/math/complex.c3 index aad3dfd2d..de09d7752 100644 --- a/lib/std/math/math_complex.c3 +++ b/lib/std/math/complex.c3 @@ -32,9 +32,11 @@ const Complex IDENTITY = { 1, 0 }; const Complex IMAGINARY = { 0, 1 }; macro Complex Complex.add(self, Complex b) @operator(+) => { .v = self.v + b.v }; +macro Complex Complex.add_this(&self, Complex b) @operator(+=) => { .v = self.v += b.v }; macro Complex Complex.add_real(self, Real r) @operator_s(+) => { .v = self.v + (Real[<2>]) { r, 0 } }; macro Complex Complex.add_each(self, Real b) => { .v = self.v + b }; macro Complex Complex.sub(self, Complex b) @operator(-) => { .v = self.v - b.v }; +macro Complex Complex.sub_this(&self, Complex b) @operator(-=) => { .v = self.v -= b.v }; macro Complex Complex.sub_real(self, Real r) @operator(-) => { .v = self.v - (Real[<2>]) { r, 0 } }; macro Complex Complex.sub_real_inverse(self, Real r) @operator_r(-) => { .v = (Real[<2>]) { r, 0 } - self.v }; macro Complex Complex.sub_each(self, Real b) => { .v = self.v - b }; diff --git a/lib/std/math/math_easings.c3 b/lib/std/math/easing.c3 similarity index 100% rename from lib/std/math/math_easings.c3 rename to lib/std/math/easing.c3 diff --git a/lib/std/math/math_matrix.c3 b/lib/std/math/matrix.c3 similarity index 100% rename from lib/std/math/math_matrix.c3 rename to lib/std/math/matrix.c3 diff --git a/lib/std/math/math_quaternion.c3 b/lib/std/math/quaternion.c3 similarity index 100% rename from lib/std/math/math_quaternion.c3 rename to lib/std/math/quaternion.c3 diff --git a/lib/std/math/runtime/math_i128.c3 b/lib/std/math/runtime/i128.c3 similarity index 97% rename from lib/std/math/runtime/math_i128.c3 rename to lib/std/math/runtime/i128.c3 index 5b510ae41..3086b69ba 100644 --- a/lib/std/math/runtime/math_i128.c3 +++ b/lib/std/math/runtime/i128.c3 @@ -1,4 +1,4 @@ -module std::math; +module std::math::math_rt; fn int128 __divti3(int128 a, int128 b) @extern("__divti3") @weak @nostrip { @@ -312,21 +312,21 @@ macro float_from_i128($Type, a) @private $switch $Type: $case double: $Rep = ulong; - const MANT_DIG = DOUBLE_MANT_DIG; + const MANT_DIG = math::DOUBLE_MANT_DIG; const SIGNIFICANT_BITS = 52; const EXP_BIAS = 1023; const MANTISSA_MASK = 0xFFFFF_FFFF_FFFFu64; const SIGN_BIT = 1u64 << 63; $case float: $Rep = uint; - const MANT_DIG = FLOAT_MANT_DIG; + const MANT_DIG = math::FLOAT_MANT_DIG; const EXP_BIAS = 127; const SIGNIFICANT_BITS = 23; const MANTISSA_MASK = 0x7F_FFFFu32; const SIGN_BIT = 1u32 << 31; $case float16: $Rep = ushort; - const MANT_DIG = HALF_MANT_DIG; + const MANT_DIG = math::HALF_MANT_DIG; $case float128: $Rep = uint128; const MANT_DIG = QUAD_MANT_DIG; @@ -371,22 +371,22 @@ macro float_from_u128($Type, a) @private $switch $Type: $case double: $Rep = ulong; - const MANT_DIG = DOUBLE_MANT_DIG; + const MANT_DIG = math::DOUBLE_MANT_DIG; const SIGNIFICANT_BITS = 52; const EXP_BIAS = 1023; const MANTISSA_MASK = 0xFFFFF_FFFF_FFFFu64; $case float: $Rep = uint; - const MANT_DIG = FLOAT_MANT_DIG; + const MANT_DIG = math::FLOAT_MANT_DIG; const EXP_BIAS = 127; const SIGNIFICANT_BITS = 23; const MANTISSA_MASK = 0x7F_FFFFu32; $case float16: $Rep = ushort; - const MANT_DIG = HALF_MANT_DIG; + const MANT_DIG = math::HALF_MANT_DIG; $case float128: $Rep = uint128; - const MANT_DIG = QUAD_MANT_DIG; + const MANT_DIG = math::QUAD_MANT_DIG; $endswitch if (a == 0) return ($Type)0; int sd = 128 - (int)$$clz(a); // digits diff --git a/lib/std/math/runtime/math_supplemental.c3 b/lib/std/math/runtime/math_supplemental.c3 index a7f246974..4093256fe 100644 --- a/lib/std/math/runtime/math_supplemental.c3 +++ b/lib/std/math/runtime/math_supplemental.c3 @@ -1,15 +1,15 @@ -module std::math; +module std::math::math_rt; fn float __roundevenf(float f) @extern("roundevenf") @weak @nostrip { // Slow implementation - return round(f / 2) * 2; + return math::round(f / 2) * 2; } fn double __roundeven(double d) @extern("roundeven") @weak @nostrip { // Slow implementation - return round(d / 2) * 2; + return math::round(d / 2) * 2; } fn double __powidf2(double a, int b) @extern("__powidf2") @weak @nostrip diff --git a/lib/std/net/http.c3 b/lib/std/net/http.c3 deleted file mode 100644 index 5e90a16bc..000000000 --- a/lib/std/net/http.c3 +++ /dev/null @@ -1,406 +0,0 @@ -module std::net::http; -/* -enum HttpStatus -{ - PENDING, - COMPLETED, - FAILED -} - -struct Http -{ - HttpStatus status; - int status_code; - String reason; - String content_type; - String response_data; -} - -fn Http* http_get(String url, Allocator using = allocator::temp()) -{ - return null; -} - -fn Http* http_post(String url, Allocator using = allocator::temp()) -{ - return null; -} - -fn void Http.destroy(Http* this) -{ -} - -fn HttpStatus Http.process(Http* this) -{ - unreachable(); -} - -// Common across implementations - -struct HttpInternal @private -{ - inline Http http; - Allocator allocator; - int connect_pending; - int request_sent; - char[256] address; - char[256] request_header; - char* request_header_large; - String request_data; - char[1024] reason_phrase; - char[256] content_type; - - usz data_size; - usz data_capacity; - void* data; -} - -fn String? parse_url(String url, String* port, String* resource) @private -{ - if (url[:7] != "http://") return NetError.INVALID_URL?; - url = url[7..]; - - usz end_index = url.index_of(":") ?? url.index_of("/") ?? url.len; - String address = url[:end_index]; - String end_part = url[end_index..]; - if (!end_part.len) - { - *port = "80"; - *resource = {}; - return address; - } - switch (end_part[0]) - { - case ':': - end_index = end_part.index_of("/") ?? end_part.len; - end_part[:end_index].to_uint() ?? NetError.INVALID_URL?!; - *port = end_part[:end_index]; - *resource = url[end_index..]; - case '/': - *port = "80"; - *resource = end_part; - default: - unreachable(); - } - return address; -} - -fn Socket? http_internal_connect(String address, uint port) @private -{ - return tcp::connect_async(address, port)!; -} - -fn HttpInternal* http_internal_create(usz request_data_size, Allocator allocator) @private -{ - HttpInternal* internal = allocator.alloc(HttpInternal.sizeof + request_data_size)!!; - internal.status = PENDING; - internal.status_code = 0; - internal.response_data = {}; - internal.allocator = allocator; - internal.connect_pending = 1; - internal.request_sent = 0; -// internal.reason = ""; -// internal.content_type = ""; - internal.data_size = 0; - internal.data_capacity = 64 * 1024; - internal.data = allocator.alloc(internal.data_capacity)!!; - internal.request_data = {}; - return internal; -} - -fn Http*? http_get(String url, Allocator allocator = allocator::temp()) -{ -$if env::WIN32: - int[1024] wsa_data; - if (_wsa_startup(1, &wsa_data) != 0) return NetError.GENERAL_ERROR?; -$endif - uint port; - String resource; - String address = parse_url(url, &port, &resource)?; - Socket socket = tcp::connect(address, port)?; - HttpInternal* internal = http_internal_create(0, allocator); - internal.socket = socket; - - char* request_header; - usz request_header_len = 64 + resource.len + address.len + port.len; - if (request_header_len < sizeof(internal.request_header)) - { - internal.request_header_large = null; - request_header = internal.request_header; - } - else - { - internal.request_header_large = (char*)allocator.malloc(request_header_len + 1); - request_header = internal.request_header_large; - } - int default_http_port = port == "80"; - sprintf( request_header, "GET %s HTTP/1.0\r\nHost: %s%s%s\r\n\r\n", resource, address, default_http_port ? "" : ":", default_http_port ? "" : port ); - - return internal; -} - -fn Http*? http_post(String url, Allocator allocator = allocator::temp()) -{ -$if env::OS_TYPE == OsType::WIN32: - int[1024] wsa_data; - if (_wsa_startup(1, &wsa_data) != 0) return NetError.GENERAL_ERROR?; -$endif - String port; - String resource; - String address = parse_url(url, &port, &resource)?; - Socket socket = http_internal_connect(address, port)?; - HttpInternal* internal = http_internal_create(0, allocator); - internal.socket = socket; - - char* request_header; - uz request_header_len = 64 + resource.len + address.len + port.len; - if (request_header_len < sizeof(internal.request_header)) - { - internal.request_header_large = null; - request_header = internal.request_header; - } - else - { - internal.request_header_large = (char*)allocator.malloc(request_header_len + 1); - request_header = internal.request_header_large; - } - int default_http_port = port == "80"; - sprintf( request_header, "POST %s HTTP/1.0\r\nHost: %s%s%s\r\nContent-Length: %d\r\n\r\n", resource, address, default_http_port ? "" : ":", default_http_port ? "" : port, - (int) size ); - - internal->request_data_size = size; - internal->request_data = ( internal + 1 ); - memcpy( internal->request_data, data, size ); - - return internal; -} - -fn HttpStatus Http.process(Http* http) -{ - HttpInternal* internal = (HttpInternal*)http; - if (http.status == HttpStatus.FAILED) return http.status; - if (internal.connect_pending) - { - fd_set sockets_to_check; - FD_ZERO(&sockets_to_check); - FD_SET( internal->socket, &sockets_to_check ); - struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; - // check if socket is ready for send - if( select( (int)( internal->socket + 1 ), NULL, &sockets_to_check, NULL, &timeout ) == 1 ) - { - int opt = -1; - socklen_t len = sizeof( opt ); - if( getsockopt( internal->socket, SOL_SOCKET, SO_ERROR, (char*)( &opt ), &len) >= 0 && opt == 0 ) - { - internal->connect_pending = 0; // if it is, we're connected - } - } - } - if (internal.connect_pending) retur http.status; - if (!internal.request_sent) - { - char* request_header = internal->request_header_large ? - internal.request_header_large : internal.request_header; - if (send(internal.socket, request_header, (int) strlen( request_header ), 0) == -1) - { - return http.status = FAILED; - } - if (internal.request_data_size) - { - int res = send(internal.socket, (char const*)internal->request_data, (int) internal->request_data_size, 0 ); - if (res == -1) - { - http.status = HTTP_STATUS_FAILED; - return http.status; - } - } - internal.request_sent = 1; - return http.status; - } - // check if socket is ready for recv - fd_set sockets_to_check; - FD_ZERO( &sockets_to_check ); - #pragma warning( push ) - #pragma warning( disable: 4548 ) // expression before comma has no effect; expected expression with side-effect - FD_SET( internal->socket, &sockets_to_check ); - #pragma warning( pop ) - struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; -} -http_status_t http_process( http_t* http ) - { - - - while( select( (int)( internal->socket + 1 ), &sockets_to_check, NULL, NULL, &timeout ) == 1 ) - { - char buffer[ 4096 ]; - int size = recv( internal->socket, buffer, sizeof( buffer ), 0 ); - if( size == -1 ) - { - http->status = HTTP_STATUS_FAILED; - return http->status; - } - else if( size > 0 ) - { - size_t min_size = internal->data_size + size + 1; - if( internal->data_capacity < min_size ) - { - internal->data_capacity *= 2; - if( internal->data_capacity < min_size ) internal->data_capacity = min_size; - void* new_data = HTTP_MALLOC( memctx, internal->data_capacity ); - memcpy( new_data, internal->data, internal->data_size ); - HTTP_FREE( memctx, internal->data ); - internal->data = new_data; - } - memcpy( (void*)( ( (uintptr_t) internal->data ) + internal->data_size ), buffer, (size_t) size ); - internal->data_size += size; - } - else if( size == 0 ) - { - char const* status_line = (char const*) internal->data; - - int header_size = 0; - char const* header_end = strstr( status_line, "\r\n\r\n" ); - if( header_end ) - { - header_end += 4; - header_size = (int)( header_end - status_line ); - } - else - { - http->status = HTTP_STATUS_FAILED; - return http->status; - } - - // skip http version - status_line = strchr( status_line, ' ' ); - if( !status_line ) - { - http->status = HTTP_STATUS_FAILED; - return http->status; - } - ++status_line; - - // extract status code - char status_code[ 16 ]; - char const* status_code_end = strchr( status_line, ' ' ); - if( !status_code_end ) - { - http->status = HTTP_STATUS_FAILED; - return http->status; - } - memcpy( status_code, status_line, (size_t)( status_code_end - status_line ) ); - status_code[ status_code_end - status_line ] = 0; - status_line = status_code_end + 1; - http->status_code = atoi( status_code ); - - // extract reason phrase - char const* reason_phrase_end = strstr( status_line, "\r\n" ); - if( !reason_phrase_end ) - { - http->status = HTTP_STATUS_FAILED; - return http->status; - } - size_t reason_phrase_len = (size_t)( reason_phrase_end - status_line ); - if( reason_phrase_len >= sizeof( internal->reason_phrase ) ) - reason_phrase_len = sizeof( internal->reason_phrase ) - 1; - memcpy( internal->reason_phrase, status_line, reason_phrase_len ); - internal->reason_phrase[ reason_phrase_len ] = 0; - status_line = reason_phrase_end + 1; - - // extract content type - char const* content_type_start = strstr( status_line, "Content-Type: " ); - if( content_type_start ) - { - content_type_start += strlen( "Content-Type: " ); - char const* content_type_end = strstr( content_type_start, "\r\n" ); - if( content_type_end ) - { - size_t content_type_len = (size_t)( content_type_end - content_type_start ); - if( content_type_len >= sizeof( internal->content_type ) ) - content_type_len = sizeof( internal->content_type ) - 1; - memcpy( internal->content_type, content_type_start, content_type_len ); - internal->content_type[ content_type_len ] = 0; - } - } - - http->status = http->status_code < 300 ? HTTP_STATUS_COMPLETED : HTTP_STATUS_FAILED; - http->response_data = (void*)( ( (uintptr_t) internal->data ) + header_size ); - http->response_size = internal->data_size - header_size; - - // add an extra zero after the received data, but don't modify the size, so ascii results can be used as - // a zero terminated string. the size returned will be the string without this extra zero terminator. - ( (char*)http->response_data )[ http->response_size ] = 0; - return http->status; - } - } - - return http->status; - } - - -void http_release( http_t* http ) - { - http_internal_t* internal = (http_internal_t*) http; - #ifdef _WIN32 - closesocket( internal->socket ); - #else - close( internal->socket ); - #endif - - if( internal->request_header_large) HTTP_FREE( memctx, internal->request_header_large ); - HTTP_FREE( memctx, internal->data ); - HTTP_FREE( memctx, internal ); - #ifdef _WIN32 - WSACleanup(); - #endif - } - - -#endif /* HTTP_IMPLEMENTATION */ - -/* -revision history: - 1.0 first released version -*/ - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses - you may choose the one you like. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2016 Mattias Gustavsson -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/*/ \ No newline at end of file diff --git a/lib/std/net/os/win32.c3 b/lib/std/net/os/win32.c3 index 90c4459de..c44942eaf 100644 --- a/lib/std/net/os/win32.c3 +++ b/lib/std/net/os/win32.c3 @@ -88,7 +88,7 @@ fn fault convert_error(WSAError error) fn fault socket_error() { - return convert_error(win32_WSAGetLastError()); + return convert_error(win32::wsaGetLastError()); } const CUShort POLLIN = win32::POLLIN; diff --git a/lib/std/net/socket.c3 b/lib/std/net/socket.c3 index 455a1dc2b..0398eb6a5 100644 --- a/lib/std/net/socket.c3 +++ b/lib/std/net/socket.c3 @@ -69,7 +69,7 @@ fn ulong? poll_ms(Poll[] polls, long timeout_ms) { if (timeout_ms > CInt.max) timeout_ms = CInt.max; $if env::WIN32: - CInt result = win32_WSAPoll((Win32_LPWSAPOLLFD)polls.ptr, (Win32_ULONG)polls.len, (CInt)timeout_ms); + CInt result = win32::wsaPoll((Win32_LPWSAPOLLFD)polls.ptr, (Win32_ULONG)polls.len, (CInt)timeout_ms); $else CInt result = os::poll((Posix_pollfd*)polls.ptr, (Posix_nfds_t)polls.len, (CInt)timeout_ms); $endif diff --git a/lib/std/net/socket_private.c3 b/lib/std/net/socket_private.c3 index 5f7656a1d..21e92d696 100644 --- a/lib/std/net/socket_private.c3 +++ b/lib/std/net/socket_private.c3 @@ -23,7 +23,7 @@ fn bool last_error_is_delayed_connect() { $switch: $case env::WIN32: - switch (win32_WSAGetLastError()) + switch (win32::wsaGetLastError()) { case wsa::EWOULDBLOCK: case wsa::EINPROGRESS: return true; diff --git a/lib/std/os/freebsd/general.c3 b/lib/std/os/freebsd/general.c3 new file mode 100644 index 000000000..94e058751 --- /dev/null +++ b/lib/std/os/freebsd/general.c3 @@ -0,0 +1,2 @@ +module std::os::freebsd @if(env::FREEBSD); + diff --git a/lib/std/os/macos/darwin.c3 b/lib/std/os/macos/darwin.c3 index 3c136662f..af87101c6 100644 --- a/lib/std/os/macos/darwin.c3 +++ b/lib/std/os/macos/darwin.c3 @@ -67,6 +67,17 @@ struct Darwin_segment_command_64 uint flags; /* flags */ } +struct Darwin_mach_timebase_info +{ + uint numer; + uint denom; +} + +alias Darwin_mach_timebase_info_t = Darwin_mach_timebase_info; +alias Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info; + +extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase); +extern fn ulong mach_absolute_time(); fn String? executable_path(Allocator allocator) { @@ -155,3 +166,4 @@ fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace) }; return list; } + diff --git a/lib/std/os/macos/general.c3 b/lib/std/os/macos/general.c3 new file mode 100644 index 000000000..d4c95a6ef --- /dev/null +++ b/lib/std/os/macos/general.c3 @@ -0,0 +1,2 @@ +module std::os::darwin @if(env::DARWIN); + diff --git a/lib/std/os/netbsd/general.c3 b/lib/std/os/netbsd/general.c3 new file mode 100644 index 000000000..d63c936b6 --- /dev/null +++ b/lib/std/os/netbsd/general.c3 @@ -0,0 +1 @@ +module std::os::netbsd @if(env::NETBSD); diff --git a/lib/std/os/openbsd/general.c3 b/lib/std/os/openbsd/general.c3 new file mode 100644 index 000000000..34e7112f6 --- /dev/null +++ b/lib/std/os/openbsd/general.c3 @@ -0,0 +1,2 @@ +module std::os::openbsd @if(env::OPENBSD); + diff --git a/lib/std/os/posix/clock.c3 b/lib/std/os/posix/clock.c3 new file mode 100644 index 000000000..07e736dca --- /dev/null +++ b/lib/std/os/posix/clock.c3 @@ -0,0 +1,68 @@ +module std::os::posix @if(env::POSIX); +import libc; + +extern fn CInt clock_gettime(int type, TimeSpec *time); + +module std::os::posix @if(env::OPENBSD); +const CLOCK_REALTIME = 0; +const CLOCK_PROCESS_CPUTIME_ID = 2; +const CLOCK_MONOTONIC = 3; +const CLOCK_THREAD_CPUTIME_ID = 4; +const CLOCK_UPTIME = 5; +const CLOCK_BOOTTIME = 6; + +module std::os::posix @if(env::FREEBSD); +const CLOCK_REALTIME = 0; +const CLOCK_VIRTUAL = 1; +const CLOCK_PROF = 2; +const CLOCK_MONOTONIC = 4; +const CLOCK_UPTIME = 5; +const CLOCK_UPTIME_PRECISE = 7; +const CLOCK_UPTIME_FAST = 8; +const CLOCK_REALTIME_PRECISE = 9; +const CLOCK_REALTIME_FAST = 10; +const CLOCK_MONOTONIC_PRECISE = 11; +const CLOCK_MONOTONIC_FAST = 12; +const CLOCK_SECOND = 13; +const CLOCK_THREAD_CPUTIME_ID = 14; +const CLOCK_PROCESS_CPUTIME_ID = 15; +const CLOCK_BOOTTIME = CLOCK_UPTIME; +const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST; +const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST; + +module std::os::posix @if(env::NETBSD); +const CLOCK_REALTIME = 0; +const CLOCK_VIRTUAL = 1; +const CLOCK_PROF = 2; +const CLOCK_MONOTONIC = 3; +const CLOCK_THREAD_CPUTIME_ID = 0x20000000; +const CLOCK_PROCESS_CPUTIME_ID = 0x40000000; + +module std::os::posix @if(env::WASI); +// Not implemented +const CLOCK_REALTIME = 0; +const CLOCK_MONOTONIC = 0; + +module std::os::posix @if(env::DARWIN); +const CLOCK_REALTIME = 0; +const CLOCK_MONOTONIC = 6; +const CLOCK_MONOTONIC_RAW = 4; +const CLOCK_MONOTONIC_RAW_APPROX = 5; +const CLOCK_UPTIME_RAW = 8; +const CLOCK_UPTIME_RAW_APPROX = 9; +const CLOCK_PROCESS_CPUTIME_ID = 12; +const CLOCK_THREAD_CPUTIME_ID = 16; + +module std::os::posix @if(env::LINUX || env::ANDROID); +const CLOCK_REALTIME = 0; +const CLOCK_MONOTONIC = 1; +const CLOCK_PROCESS_CPUTIME_ID = 2; +const CLOCK_THREAD_CPUTIME_ID = 3; +const CLOCK_MONOTONIC_RAW = 4; +const CLOCK_REALTIME_COARSE = 5; +const CLOCK_MONOTONIC_COARSE = 6; +const CLOCK_BOOTTIME = 7; +const CLOCK_REALTIME_ALARM = 8; +const CLOCK_BOOTTIME_ALARM = 9; +const CLOCK_TAI = 11; + diff --git a/lib/std/os/posix/general.c3 b/lib/std/os/posix/general.c3 index 19f38e399..8a83951c3 100644 --- a/lib/std/os/posix/general.c3 +++ b/lib/std/os/posix/general.c3 @@ -1,4 +1,3 @@ -module std::os::posix; +module std::os::posix @if(env::POSIX); extern ZString* environ; - diff --git a/lib/std/os/posix/net.c3 b/lib/std/os/posix/net.c3 new file mode 100644 index 000000000..d0bfa2ac5 --- /dev/null +++ b/lib/std/os/posix/net.c3 @@ -0,0 +1 @@ +module std::os::posix @if(env::POSIX); \ No newline at end of file diff --git a/lib/std/os/win32/clock.c3 b/lib/std/os/win32/clock.c3 new file mode 100644 index 000000000..808358f79 --- /dev/null +++ b/lib/std/os/win32/clock.c3 @@ -0,0 +1,6 @@ +module std::os::win32 @if(env::WIN32); +import std::math; + +extern fn void getSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime"); +extern fn Win32_BOOL queryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency"); +extern fn Win32_BOOL queryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter"); diff --git a/lib/std/os/win32/files.c3 b/lib/std/os/win32/files.c3 index 345b9f856..78985a488 100644 --- a/lib/std/os/win32/files.c3 +++ b/lib/std/os/win32/files.c3 @@ -1,5 +1,6 @@ module std::os::win32 @if(env::WIN32); import libc; + enum Win32_GET_FILEEX_INFO_LEVELS { STANDARD, diff --git a/lib/std/os/win32/wsa.c3 b/lib/std/os/win32/wsa.c3 index 843074bb4..b4362cd2a 100644 --- a/lib/std/os/win32/wsa.c3 +++ b/lib/std/os/win32/wsa.c3 @@ -122,11 +122,11 @@ const SD_RECEIVE = 0x00; const SD_SEND = 0x01; const SD_BOTH = 0x02; -extern fn CInt win32_WSAPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @extern("WSAPoll") @builtin; -extern fn WSAError win32_WSAGetLastError() @extern("WSAGetLastError") @builtin; -extern fn void win32_WSASetLastError(WSAError error) @extern("WSASetLastError") @builtin; -extern fn CInt win32_WSAStartup(Win32_WORD, void*) @extern("WSAStartup") @builtin; -extern fn CInt win32_WSACleanup() @extern("WSACleanup") @builtin; +extern fn CInt wsaPoll(Win32_LPWSAPOLLFD fdArray, Win32_ULONG fds, Win32_INT timeout) @extern("WSAPoll"); +extern fn WSAError wsaGetLastError() @extern("WSAGetLastError"); +extern fn void wsaSetLastError(WSAError error) @extern("WSASetLastError"); +extern fn CInt wsaStartup(Win32_WORD, void*) @extern("WSAStartup"); +extern fn CInt wsaCleanup() @extern("WSACleanup"); const int FIONBIO = -2147195266; const int FIONREAD = 1074030207; @@ -230,3 +230,4 @@ const WSAError QOS_EPSFILTERSPEC = 11028; const WSAError QOS_ESDMODEOBJ = 11029; const WSAError QOS_ESHAPERATEOBJ = 11030; const WSAError QOS_RESERVED_PETYPE = 11031; + diff --git a/lib/std/text/i18n.c3 b/lib/std/text/i18n.c3 deleted file mode 100644 index 6acc33318..000000000 --- a/lib/std/text/i18n.c3 +++ /dev/null @@ -1,17 +0,0 @@ -/*module std::text::i18n; -import std::collections::map; -import std::hash::fnv32a; -typedef Language = char[]; - -const Language EN = "en"; - -alias TranslationMap = HashMap{String, String}; -fn uint Language.hash(self) => fnv32a::encode((char[])self); -HashMap{Language, TranslationMap*} language_map @private; -TranslationMap? current_map; - -macro String @localized(String string) @builtin -{ - return current_map[string] ?? string; -} - diff --git a/lib/std/time/os/time_darwin.c3 b/lib/std/time/os/time_darwin.c3 index a359b3eee..d3bc86fd0 100644 --- a/lib/std/time/os/time_darwin.c3 +++ b/lib/std/time/os/time_darwin.c3 @@ -1,23 +1,12 @@ module std::time::os @if(env::DARWIN); - -struct Darwin_mach_timebase_info -{ - uint numer; - uint denom; -} - -alias Darwin_mach_timebase_info_t = Darwin_mach_timebase_info; -alias Darwin_mach_timebase_info_data_t = Darwin_mach_timebase_info; - -extern fn void mach_timebase_info(Darwin_mach_timebase_info_data_t* timebase); -extern fn ulong mach_absolute_time(); +import std::os::darwin; fn Clock native_clock() { static Darwin_mach_timebase_info_data_t timebase; if (!timebase.denom) { - mach_timebase_info(&timebase); + darwin::mach_timebase_info(&timebase); } - return (Clock)(mach_absolute_time() * timebase.numer / timebase.denom); + return (Clock)(darwin::mach_absolute_time() * timebase.numer / timebase.denom); } diff --git a/lib/std/time/os/time_posix.c3 b/lib/std/time/os/time_posix.c3 index 46b369225..b9c76fde5 100644 --- a/lib/std/time/os/time_posix.c3 +++ b/lib/std/time/os/time_posix.c3 @@ -1,82 +1,17 @@ module std::time::os @if(env::POSIX); -import libc; - -extern fn CInt clock_gettime(int type, TimeSpec *time); +import libc, std::os::posix; fn Time native_timestamp() { TimeSpec ts; - clock_gettime(CLOCK_REALTIME, &ts); + posix::clock_gettime(posix::CLOCK_REALTIME, &ts); return (Time)(ts.s * 1_000_000i64 + ts.ns / 1_000i64); } fn Clock native_clock() @if(!env::DARWIN) { TimeSpec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); + posix::clock_gettime(posix::CLOCK_MONOTONIC, &ts); return (Clock)((ulong)ts.s * 1_000_000_000u64 + (ulong)ts.ns); } -module std::time::os @if(env::OPENBSD); -const CLOCK_REALTIME = 0; -const CLOCK_PROCESS_CPUTIME_ID = 2; -const CLOCK_MONOTONIC = 3; -const CLOCK_THREAD_CPUTIME_ID = 4; -const CLOCK_UPTIME = 5; -const CLOCK_BOOTTIME = 6; - -module std::time::os @if(env::FREEBSD); -const CLOCK_REALTIME = 0; -const CLOCK_VIRTUAL = 1; -const CLOCK_PROF = 2; -const CLOCK_MONOTONIC = 4; -const CLOCK_UPTIME = 5; -const CLOCK_UPTIME_PRECISE = 7; -const CLOCK_UPTIME_FAST = 8; -const CLOCK_REALTIME_PRECISE = 9; -const CLOCK_REALTIME_FAST = 10; -const CLOCK_MONOTONIC_PRECISE = 11; -const CLOCK_MONOTONIC_FAST = 12; -const CLOCK_SECOND = 13; -const CLOCK_THREAD_CPUTIME_ID = 14; -const CLOCK_PROCESS_CPUTIME_ID = 15; -const CLOCK_BOOTTIME = CLOCK_UPTIME; -const CLOCK_REALTIME_COARSE = CLOCK_REALTIME_FAST; -const CLOCK_MONOTONIC_COARSE = CLOCK_MONOTONIC_FAST; - -module std::time::os @if(env::NETBSD); -const CLOCK_REALTIME = 0; -const CLOCK_VIRTUAL = 1; -const CLOCK_PROF = 2; -const CLOCK_MONOTONIC = 3; -const CLOCK_THREAD_CPUTIME_ID = 0x20000000; -const CLOCK_PROCESS_CPUTIME_ID = 0x40000000; - -module std::time::os @if(env::WASI); -// Not implemented -const CLOCK_REALTIME = 0; -const CLOCK_MONOTONIC = 0; - -module std::time::os @if(env::DARWIN); -const CLOCK_REALTIME = 0; -const CLOCK_MONOTONIC = 6; -const CLOCK_MONOTONIC_RAW = 4; -const CLOCK_MONOTONIC_RAW_APPROX = 5; -const CLOCK_UPTIME_RAW = 8; -const CLOCK_UPTIME_RAW_APPROX = 9; -const CLOCK_PROCESS_CPUTIME_ID = 12; -const CLOCK_THREAD_CPUTIME_ID = 16; - -module std::time::os @if(env::LINUX || env::ANDROID); -const CLOCK_REALTIME = 0; -const CLOCK_MONOTONIC = 1; -const CLOCK_PROCESS_CPUTIME_ID = 2; -const CLOCK_THREAD_CPUTIME_ID = 3; -const CLOCK_MONOTONIC_RAW = 4; -const CLOCK_REALTIME_COARSE = 5; -const CLOCK_MONOTONIC_COARSE = 6; -const CLOCK_BOOTTIME = 7; -const CLOCK_REALTIME_ALARM = 8; -const CLOCK_BOOTTIME_ALARM = 9; -const CLOCK_TAI = 11; - diff --git a/lib/std/time/os/time_win32.c3 b/lib/std/time/os/time_win32.c3 index 998d9dcdb..872c97785 100644 --- a/lib/std/time/os/time_win32.c3 +++ b/lib/std/time/os/time_win32.c3 @@ -2,14 +2,9 @@ module std::time::os @if(env::WIN32); import std::os::win32; import std::math; -extern fn void win32_GetSystemTimeAsFileTime(Win32_FILETIME* time) @extern("GetSystemTimeAsFileTime"); -extern fn Win32_BOOL win32_QueryPerformanceFrequency(Win32_LARGE_INTEGER* lpFrequency) @extern("QueryPerformanceFrequency"); -extern fn Win32_BOOL win32_QueryPerformanceCounter(Win32_LARGE_INTEGER* lpPerformanceCount) @extern("QueryPerformanceCounter"); - const ulong WINDOWS_TICK_US @local = 10; const ulong WIN_TO_UNIX_EPOCH_US @local = 116444736000000000u64 / WINDOWS_TICK_US; - fn Clock native_clock() { static Win32_LARGE_INTEGER freq; @@ -17,17 +12,17 @@ fn Clock native_clock() ulong mult = 0; if (!freq.quadPart) { - if (!win32_QueryPerformanceFrequency(&freq)) return 0; + if (!win32::queryPerformanceFrequency(&freq)) return 0; } Win32_LARGE_INTEGER counter @noinit; - if (!win32_QueryPerformanceCounter(&counter)) return 0; + if (!win32::queryPerformanceCounter(&counter)) return 0; return (Clock)counter.quadPart.muldiv(1_000_000_000, freq.quadPart); } fn Time native_timestamp() { Win32_FILETIME ft @noinit; - win32_GetSystemTimeAsFileTime(&ft); + win32::getSystemTimeAsFileTime(&ft); ulong result = (ulong)ft.dwHighDateTime << 32 | ft.dwLowDateTime; return (Time)(result / WINDOWS_TICK_US - WIN_TO_UNIX_EPOCH_US); } \ No newline at end of file diff --git a/releasenotes.md b/releasenotes.md index 2889259e9..4a1b71c07 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -11,7 +11,8 @@ - Add `@operator_r` and `@operator_s` attributes. - More stdlib tests: `sincos`, `ArenaAllocator`, `Slice2d`. - Make aliases able to use `@deprecated`. - +- Refactored stdlib file organization. + ### Fixes - Trying to cast an enum to int and back caused the compiler to crash. - Incorrect rounding at compile time going from double to int. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 6f5a5a2d7..50d5d36f2 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -6241,11 +6241,11 @@ INLINE bool sema_rewrite_op_assign(SemaContext *context, Expr *expr, Expr *left, // Simple case: f += a => f = f + a if (left->expr_kind == EXPR_IDENTIFIER) { + Expr *lvalue = expr_copy(left); + Expr *rvalue = expr_copy(left); expr->expr_kind = EXPR_BINARY; left->expr_kind = EXPR_BINARY; - Expr *lvalue = expr_copy(left); - Expr *rvalue = expr_copy(right); - left->binary_expr = (ExprBinary) { .left = exprid(rvalue), .right = exprid(right), new_op }; + left->binary_expr = (ExprBinary) { .left = exprid(rvalue), .right = exprid(right), .operator = new_op }; expr->binary_expr = (ExprBinary) { .left = exprid(lvalue), .right = exprid(left), .operator = BINARYOP_ASSIGN, .grouped = false }; expr->resolve_status = RESOLVE_NOT_DONE; left->resolve_status = RESOLVE_NOT_DONE; @@ -6422,6 +6422,7 @@ static bool sema_expr_analyse_op_assign(SemaContext *context, Expr *expr, Expr * [BINARYOP_SUB] = OVERLOAD_MINUS, [BINARYOP_DIV] = OVERLOAD_DIVIDE, [BINARYOP_MOD] = OVERLOAD_REMINDER, + [BINARYOP_MULT] = OVERLOAD_MULTIPLY, [BINARYOP_BIT_XOR] = OVERLOAD_XOR, [BINARYOP_BIT_OR] = OVERLOAD_OR, [BINARYOP_BIT_AND] = OVERLOAD_AND, diff --git a/test/unit/stdlib/math/math_complex.c3 b/test/unit/stdlib/math/math_complex.c3 index 5d5d7b41f..d32671359 100644 --- a/test/unit/stdlib/math/math_complex.c3 +++ b/test/unit/stdlib/math/math_complex.c3 @@ -16,8 +16,8 @@ fn void complex_add() Complex b = { 1, 2 }; assert(a + b == (Complex){ 4, 6 }); assert(a.add_each(1).equals({4, 5})); - //a += b; - //assert(a == (Complex){ 4, 6 }); + a += b; + assert(a == (Complex){ 4, 6 }); } fn void complex_sub() @@ -26,14 +26,16 @@ fn void complex_sub() Complex b = { 1, 2 }; assert(a - b == (Complex){ 2, 2 }); assert(a.sub_each(1).equals({2, 3})); - //a -= b; - //assert(a == (Complex){ 2, 2 }); + a -= b; + assert(a == (Complex){ 2, 2 }); } fn void complex_scale() { Complex a = {2, 1}; assert(a * 2 == (Complex) {4, 2}); + a *= 2; + assert(a == (Complex) {4, 2}); } fn void complex_conjugate() @@ -53,7 +55,7 @@ fn void complex_div() Complex a = {2, 5}; Complex b = {4, -1}; assert(a / b == (Complex) {3.0/17.0, 22.0/17.0}); - //a /= b; - //assert(a == (Complex) {3.0/17.0, 22.0/17.0}); + a /= b; + assert(a == (Complex) {3.0/17.0, 22.0/17.0}); }