Dynamic protocols.

This commit is contained in:
Christoffer Lerno
2023-10-04 23:10:59 +02:00
committed by Christoffer Lerno
parent 4cc30c0d33
commit 49c4595457
106 changed files with 2372 additions and 2011 deletions

View File

@@ -13,7 +13,7 @@ fn void EnumMap.init(&self, ValueType init_value)
}
}
fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic
fn usz! EnumMap.to_format(&self, Formatter* formatter) : Printable
{
usz n = formatter.print("{ ")!;
foreach (i, &value : self.values)
@@ -25,7 +25,7 @@ fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic
return n;
}
fn String EnumMap.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String EnumMap.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return string::printf("%s", *self);
}

View File

@@ -125,7 +125,7 @@ fn EnumSet EnumSet.xor_of(&self, EnumSet s)
$endif
}
fn usz! EnumSet.to_format(&set, Formatter* formatter) @dynamic
fn usz! EnumSet.to_format(&set, Formatter* formatter) : Printable
{
usz n = formatter.print("[")!;
bool found;
@@ -140,7 +140,7 @@ fn usz! EnumSet.to_format(&set, Formatter* formatter) @dynamic
return n;
}
fn String EnumSet.to_string(&set, Allocator* using = mem::heap()) @dynamic
fn String EnumSet.to_string(&set, Allocator* using = mem::heap()) : Printable
{
return string::printf("%s", *set);
}

View File

@@ -6,7 +6,7 @@ import std::io;
import std::math;
def ElementPredicate = fn bool(Type *type);
def ElementTest = fn bool(Type *type, any context);
def ElementTest = fn bool(Type *type, any* context);
const ELEMENT_IS_EQUATABLE = types::is_equatable_type(Type);
const ELEMENT_IS_POINTER = Type.kindof == POINTER;
@@ -42,7 +42,7 @@ fn void List.tinit(&self, usz initial_capacity = 16)
self.init(initial_capacity, mem::temp()) @inline;
}
fn usz! List.to_format(&self, Formatter* formatter) @dynamic
fn usz! List.to_format(&self, Formatter* formatter) : Printable
{
switch (self.size)
{
@@ -62,7 +62,7 @@ fn usz! List.to_format(&self, Formatter* formatter) @dynamic
}
}
fn String List.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String List.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return string::printf("%s", *self);
}
@@ -286,12 +286,12 @@ macro usz List._remove_if(&self, ElementPredicate filter, bool $invert) @local
return size - self.size;
}
fn usz List.remove_using_test(&self, ElementTest filter, any context)
fn usz List.remove_using_test(&self, ElementTest filter, any* context)
{
return self._remove_using_test(filter, false, context);
}
fn usz List.retain_using_test(&self, ElementTest filter, any context)
fn usz List.retain_using_test(&self, ElementTest filter, any* context)
{
return self._remove_using_test(filter, true, context);
}

View File

@@ -27,7 +27,7 @@ struct Object
}
fn usz! Object.to_format(&self, Formatter* formatter) @dynamic
fn usz! Object.to_format(&self, Formatter* formatter) : Printable
{
switch (self.type)
{

View File

@@ -133,12 +133,12 @@ fn Type PrivatePriorityQueue.peek_at(&self, usz index) @operator([])
return self.heap[index];
}
fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter) @dynamic
fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter) : Printable
{
return self.heap.to_format(formatter);
}
fn String PrivatePriorityQueue.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String PrivatePriorityQueue.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return self.heap.to_string(using);
}

View File

@@ -29,12 +29,12 @@ fn Type Range.get(&self, usz index) @operator([])
return self.start + (Type)index;
}
fn String Range.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String Range.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return string::printf("[%s..%s]", self.start, self.end);
}
fn usz! Range.to_format(&self, Formatter* formatter) @dynamic
fn usz! Range.to_format(&self, Formatter* formatter) : Printable
{
return formatter.printf("[%s..%s]", self.start, self.end)!;
}
@@ -56,12 +56,12 @@ fn bool ExclusiveRange.contains(&self, Type value) @inline
return value >= self.start && value < self.end;
}
fn usz! ExclusiveRange.to_format(&self, Formatter* formatter) @dynamic
fn usz! ExclusiveRange.to_format(&self, Formatter* formatter) : Printable
{
return formatter.printf("[%s..<%s]", self.start, self.end)!;
}
fn String ExclusiveRange.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String ExclusiveRange.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return string::printf("[%s..<%s]", self.start, self.end);
}

View File

@@ -62,7 +62,7 @@ macro void @swap(&a, &b) @builtin
* @ensure @typeis(return, $Type*)
* @return! CastResult.TYPE_MISMATCH
**/
macro anycast(any v, $Type) @builtin
macro anycast(any* v, $Type) @builtin
{
if (v.type != $Type.typeid) return CastResult.TYPE_MISMATCH?;
return ($Type*)v.ptr;
@@ -190,6 +190,21 @@ macro void unsupported(String string = "Unsupported function invoked") @builtin
$$unreachable();
}
macro any_make(void* ptr, typeid type) @builtin
{
return $$any_make(ptr, type);
}
macro any.retype_to(&self, typeid type)
{
return $$any_make(self.ptr, type);
}
macro any.as_inner(&self)
{
return $$any_make(self.ptr, self.type.inner);
}
/**
* @param expr "the expression to cast"
* @param $Type "the type to cast to"

View File

@@ -11,7 +11,7 @@ fault ConversionResult
/**
* @require $Type.kindof.is_int() || $Type.kindof == TypeKind.ENUM "Argument was not an integer"
**/
macro any_to_int(any v, $Type)
macro any_to_int(any* v, $Type)
{
typeid any_type = v.type;
TypeKind kind = any_type.kindof;

View File

@@ -4,8 +4,11 @@ import libc;
const int PRINTF_NTOA_BUFFER_SIZE = 256;
fn String any.to_string(void* value, Allocator *using) @interface;
fn usz! any.to_format(void* value, Formatter* formatter) @interface;
protocol Printable
{
fn String to_string(&self, Allocator *using);
fn usz! to_format(&self, Formatter* formatter);
}
fault PrintFault
{
@@ -69,7 +72,7 @@ fn usz! Formatter.out(&self, char c) @private
return 1;
}
macro usz! Formatter.print_with_function(&self, any arg)
fn usz! Formatter.print_with_function(&self, Printable* arg)
{
if (&arg.to_format)
{
@@ -104,7 +107,7 @@ macro usz! Formatter.print_with_function(&self, any arg)
}
fn usz! Formatter.out_str(&self, any arg) @private
fn usz! Formatter.out_str(&self, any* arg) @private
{
switch (arg.type.kindof)
{
@@ -116,7 +119,7 @@ fn usz! Formatter.out_str(&self, any arg) @private
case FAULT:
return self.out_substr((*(anyfault*)arg.ptr).nameof);
case ANY:
return self.out_str(*(any*)arg);
return self.out_str(*(any**)arg);
case OPTIONAL:
unreachable();
case SIGNED_INT:
@@ -146,14 +149,16 @@ fn usz! Formatter.out_str(&self, any arg) @private
return self.out_substr(*(bool*)arg.ptr ? "true" : "false");
default:
}
usz! n = self.print_with_function(arg);
usz! n = self.print_with_function((Printable*)arg);
if (catch err = n)
{
case SearchResult.MISSING:
break;
default:
return err?;
} else {
}
else
{
return n;
}
switch (arg.type.kindof)
@@ -179,7 +184,7 @@ fn usz! Formatter.out_str(&self, any arg) @private
{
return self.out_substr(((DString*)arg).str_view());
}
return self.out_str(any { arg.ptr, arg.type.inner });
return self.out_str(arg.as_inner());
case POINTER:
PrintFlags flags = self.flags;
uint width = self.width;
@@ -211,7 +216,7 @@ fn usz! Formatter.out_str(&self, any arg) @private
for (usz i = 0; i < alen; i++)
{
if (i != 0) len += self.out_substr(", ")!;
len += self.out_str(any { ptr, inner })!;
len += self.out_str(any_make(ptr, inner))!;
ptr += size;
}
len += self.out(']')!;
@@ -236,7 +241,7 @@ fn usz! Formatter.out_str(&self, any arg) @private
for (usz i = 0; i < vlen; i++)
{
if (i != 0) len += self.out_substr(", ")!;
len += self.out_str(any { ptr, inner })!;
len += self.out_str(any_make(ptr, inner))!;
ptr += size;
}
len += self.out_substr(">]")!;
@@ -267,7 +272,7 @@ fn usz! Formatter.out_str(&self, any arg) @private
for (usz i = 0; i < slen; i++)
{
if (i != 0) len += self.out_substr(", ")!;
len += self.out_str(any { ptr, inner })!;
len += self.out_str(any_make(ptr, inner))!;
ptr += size;
}
len += self.out(']')!;
@@ -286,7 +291,7 @@ fn void! out_null_fn(void* data @unused, char c @unused) @private
fn usz! Formatter.vprintf(&self, String format, any[] anys)
fn usz! Formatter.vprintf(&self, String format, any*[] anys)
{
if (!self.out_fn)
{
@@ -353,7 +358,7 @@ fn usz! Formatter.vprintf(&self, String format, any[] anys)
// evaluate specifier
uint base = 0;
if (variant_index >= anys.len) return PrintFault.MISSING_ARG?;
any current = anys[variant_index++];
any* current = anys[variant_index++];
switch (c)
{
case 'd':

View File

@@ -9,7 +9,7 @@ fn usz! Formatter.adjust(&self, usz len) @local
return self.pad(' ', self.width, len);
}
fn uint128! int_from_any(any arg, bool *is_neg) @private
fn uint128! int_from_any(any* arg, bool *is_neg) @private
{
*is_neg = false;
if (arg.type.kindof == TypeKind.POINTER)
@@ -18,7 +18,7 @@ fn uint128! int_from_any(any arg, bool *is_neg) @private
}
if (arg.type.kindof == TypeKind.DISTINCT)
{
return int_from_any(any { arg.ptr, arg.type.inner }, is_neg);
return int_from_any(arg.as_inner(), is_neg);
}
switch (arg)
{
@@ -60,7 +60,7 @@ fn uint128! int_from_any(any arg, bool *is_neg) @private
}
}
fn FloatType! float_from_any(any arg) @private
fn FloatType! float_from_any(any* arg) @private
{
$if env::F128_SUPPORT:
if (arg.type == float128.typeid) return (FloatType)*((float128*)arg.ptr);
@@ -70,7 +70,7 @@ fn FloatType! float_from_any(any arg) @private
$endif
if (arg.type.kindof == TypeKind.DISTINCT)
{
return float_from_any(any { arg.ptr, arg.type.inner });
return float_from_any(arg.as_inner());
}
switch (arg)
{
@@ -585,14 +585,14 @@ fn usz! Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba
}
fn usz! Formatter.ntoa_any(&self, any arg, uint base) @private
fn usz! Formatter.ntoa_any(&self, any* arg, uint base) @private
{
bool is_neg;
uint128 val = int_from_any(arg, &is_neg)!!;
return self.ntoa(val, is_neg, base) @inline;
}
fn usz! Formatter.out_char(&self, any arg) @private
fn usz! Formatter.out_char(&self, any* arg) @private
{
usz len = 1;
uint l = 1;
@@ -646,21 +646,21 @@ fn void! printf_advance_format(usz format_len, usz *index_ptr) @inline @private
if (val >= format_len) return FormattingFault.UNTERMINATED_FORMAT?;
}
fn any! next_any(any* args_ptr, usz args_len, usz* arg_index_ptr) @inline @private
fn any*! next_any(any** args_ptr, usz args_len, usz* arg_index_ptr) @inline @private
{
if (*arg_index_ptr >= args_len) return FormattingFault.MISSING_ARG?;
return args_ptr[(*arg_index_ptr)++];
}
fn int! printf_parse_format_field(
any* args_ptr, usz args_len, usz* args_index_ptr,
any** args_ptr, usz args_len, usz* args_index_ptr,
char* format_ptr, usz format_len, usz* index_ptr) @inline @private
{
char c = format_ptr[*index_ptr];
if (c.is_digit()) return simple_atoi(format_ptr, format_len, index_ptr);
if (c != '*') return 0;
printf_advance_format(format_len, index_ptr)!;
any val = next_any(args_ptr, args_len, args_index_ptr)!;
any* val = next_any(args_ptr, args_len, args_index_ptr)!;
if (!val.type.kindof.is_int()) return FormattingFault.INVALID_WIDTH_ARG?;
uint! intval = types::any_to_int(val, int);
return intval ?? FormattingFault.INVALID_WIDTH_ARG?;

View File

@@ -449,12 +449,12 @@ fn void Path.free(self)
}
fn usz! Path.to_format(&self, Formatter* formatter) @dynamic
fn usz! Path.to_format(&self, Formatter* formatter) : Printable
{
return formatter.print(self.str_view());
}
fn String Path.to_string(&self, Allocator* using = mem::heap()) @dynamic
fn String Path.to_string(&self, Allocator* using = mem::heap()) : Printable
{
return self.str_view().copy(using);
}

View File

@@ -84,7 +84,7 @@ fn usz! Stream.available(&self) @inline
return IoError.NOT_SEEKABLE?;
}
fn usz! Stream.read_any(&self, any ref)
fn usz! Stream.read_any(&self, any* ref)
{
return self.read_all(ref.ptr[:ref.type.sizeof]);
}
@@ -94,7 +94,7 @@ fn usz! Stream.read_any(&self, any ref)
* @require ref.ptr != null
* @ensure return == ref.type.sizeof
*/
fn usz! Stream.write_any(&self, any ref)
fn usz! Stream.write_any(&self, any* ref)
{
return self.write_all(ref.ptr[:ref.type.sizeof]);
}

View File

@@ -45,7 +45,7 @@ struct InetAddress
}
fn usz! InetAddress.to_format(InetAddress* addr, Formatter* formatter) @dynamic
fn usz! InetAddress.to_format(InetAddress* addr, Formatter* formatter) : Printable
{
if (addr.is_ipv6)
{
@@ -56,7 +56,7 @@ fn usz! InetAddress.to_format(InetAddress* addr, Formatter* formatter) @dynamic
return formatter.printf("%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!;
}
fn String InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap()) @dynamic
fn String InetAddress.to_string(InetAddress* addr, Allocator* using = mem::heap()) : Printable
{
if (addr.is_ipv6)
{

View File

@@ -16,7 +16,7 @@ struct Posix_pollfd
def Posix_nfds_t = CUInt;
extern fn CInt connect(NativeSocket socket, SockAddrPtr address, Socklen_t address_len);
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol protocol) @extern("socket");
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol ip_protocol) @extern("socket");
extern fn int fcntl(NativeSocket socket, int cmd, ...) @extern("fcntl");
extern fn CInt bind(NativeSocket socket, SockAddrPtr address, Socklen_t address_len) @extern("bind");
extern fn CInt listen(NativeSocket socket, CInt backlog) @extern("listen");

View File

@@ -17,7 +17,7 @@ def NativeSocket = distinct uptr;
extern fn CInt ioctlsocket(NativeSocket, CLong cmd, CULong *argp);
extern fn WSAError closesocket(NativeSocket);
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol protocol);
extern fn NativeSocket socket(AIFamily af, AISockType type, AIProtocol ip_protocol);
extern fn int connect(NativeSocket, SockAddrPtr address, Socklen_t address_len);
extern fn int bind(NativeSocket, SockAddrPtr address, Socklen_t address_len);
extern fn int listen(NativeSocket, int backlog);

View File

@@ -5,9 +5,9 @@ import libc;
def TcpSocket = distinct inline Socket;
def TcpServerSocket = distinct inline Socket;
fn TcpSocket! connect(String host, uint port, Duration timeout = 0, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
fn TcpSocket! connect(String host, uint port, Duration timeout = 0, SocketOption... options, IpProtocol ip_protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_STREAM)!;
AddrInfo* ai = net::addrinfo(host, port, ip_protocol.ai_family, os::SOCK_STREAM)!;
defer os::freeaddrinfo(ai);
if (timeout > 0)
{
@@ -16,9 +16,9 @@ fn TcpSocket! connect(String host, uint port, Duration timeout = 0, SocketOption
return connect_to(ai, ...options);
}
fn TcpSocket! connect_async(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
fn TcpSocket! connect_async(String host, uint port, SocketOption... options, IpProtocol ip_protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_STREAM)!;
AddrInfo* ai = net::addrinfo(host, port, ip_protocol.ai_family, os::SOCK_STREAM)!;
defer os::freeaddrinfo(ai);
return connect_async_to(ai, ...options);
}
@@ -33,9 +33,9 @@ fn TcpSocket! connect_async_to(AddrInfo* ai, SocketOption... options)
return (TcpSocket)net::connect_async_from_addrinfo(ai, options);
}
fn TcpServerSocket! listen(String host, uint port, uint backlog, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
fn TcpServerSocket! listen(String host, uint port, uint backlog, SocketOption... options, IpProtocol ip_protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_STREAM)!;
AddrInfo* ai = net::addrinfo(host, port, ip_protocol.ai_family, os::SOCK_STREAM)!;
defer os::freeaddrinfo(ai);
return listen_to(ai, backlog, ...options);
}

View File

@@ -3,9 +3,9 @@ import std::net @public;
def UdpSocket = distinct inline Socket;
fn UdpSocket! connect(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
fn UdpSocket! connect(String host, uint port, SocketOption... options, IpProtocol ip_protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_DGRAM)!;
AddrInfo* ai = net::addrinfo(host, port, ip_protocol.ai_family, os::SOCK_DGRAM)!;
defer os::freeaddrinfo(ai);
return connect_to(ai, ...options);
}
@@ -15,9 +15,9 @@ fn UdpSocket! connect_to(AddrInfo* ai, SocketOption... options)
return (UdpSocket)net::connect_from_addrinfo(ai, options);
}
fn UdpSocket! connect_async(String host, uint port, SocketOption... options, IpProtocol protocol = UNSPECIFIED)
fn UdpSocket! connect_async(String host, uint port, SocketOption... options, IpProtocol ip_protocol = UNSPECIFIED)
{
AddrInfo* ai = net::addrinfo(host, port, protocol.ai_family, os::SOCK_DGRAM)!;
AddrInfo* ai = net::addrinfo(host, port, ip_protocol.ai_family, os::SOCK_DGRAM)!;
defer os::freeaddrinfo(ai);
return connect_async_to(ai, ...options);
}

View File

@@ -30,7 +30,7 @@ fn bool Backtrace.is_unknown(&self)
return !self.object_file.len;
}
fn usz! Backtrace.to_format(&self, Formatter* formatter) @dynamic
fn usz! Backtrace.to_format(&self, Formatter* formatter) : Printable
{
if (self.has_file())
{

View File

@@ -1,9 +1,9 @@
module std::time;
def Time = distinct long @inline;
def Duration = distinct long @inline;
def Clock = distinct ulong @inline;
def NanoDuration = distinct long @inline;
def Time = distinct long;
def Duration = distinct long;
def Clock = distinct ulong;
def NanoDuration = distinct long;
const Duration MS = 1_000;
const Duration SEC = 1_000_000;
@@ -97,7 +97,7 @@ fn Duration NanoDuration.to_duration(nd) => (Duration)nd / 1_000;
fn NanoDuration Duration.to_nano(td) => (NanoDuration)td * 1_000;
fn long Duration.to_ms(td) => (long)td / 1_000;
fn usz! NanoDuration.to_format(&self, Formatter* formatter) @dynamic
fn usz! NanoDuration.to_format(&self, Formatter* formatter) : Printable
{
NanoDuration nd = *self;
if (nd == 0)