<pixelherodev>
If I wanted to try writing a program that takes Zig IR and produces arbitrary output, is that feasible? Or would it be better to take the LLVM IR and process that instead?
<andrewrk>
not stable at all, and that's not feasible. we don't have a binary or textual format for it
<traviss>
good news. vscode is showing error squiggles now after zig fmt on save. did something change? i upgraded vscode yesterday on debian.
<traviss>
looks like some recent commits about a week ago. thanks emekoi and tiehuis. nice work guys!
<pixelherodev>
andrewrk, alright thanks
<pixelherodev>
With `--emit llvm-ir --release-fast`, is the generated IR optimized, or is that overridden by emitting IR?
<andrewrk>
yes the generated ir is optimized in this case
<pixelherodev>
Perfect - working on a translater to a custom ISA :)
epsyloN- has joined #zig
<pixelherodev>
Not writing an official LLVM backend, because I'll probably have an easier time parsing the IR directly :P
diltsman has joined #zig
<andrewrk>
I'll hopefully have a better solution to offer you for this use case in the future, but that's bit far away
epsyloN- has quit [Remote host closed the connection]
<diltsman>
Why does it give an error when I assign this function "stdcallcc fn WndProc(……)" to a member of type "pub const WNDPROC = stdcallcc fn (……)"? It says "expected type 'extern fn([*c].cimport:1:11.struct_HWND__, c_uint, c_ulonglong, c_longlong) c_longlong', found 'stdcallcc fn([*c].cimport:1:11.struct_HWng) c_longlong'"
<daurnimator>
diltsman: missing 'extern'?
<diltsman>
Does it need extern and stdcallcc? I seem to remember that having an error too.
<diltsman>
Using only extern compiled, but the functionality seemed to me like something wasn't working right.
kapil_ has joined #zig
<daurnimator>
diltsman: where is your WNDPROC definition coming from?
<diltsman>
daurnimator const c = @cImport({
<diltsman>
@cInclude("Windows.h");
<diltsman>
});
<andrewrk>
diltsman, those definitions don't match at all, they don't even have the same number of args
<diltsman>
Copy paste error...I will recompile once I finish unzipping the latest Zig.
mahmudov has quit [Remote host closed the connection]
diltsman has joined #zig
<diltsman>
I don't know if this went through before I got disconnected: The error is expected type 'extern fn([*c].cimport:1:11.struct_HWND__, c_uint, c_ulonglong, c_longlong) c_longlong', found 'stdcallcc fn([*c].cimport:1:11.struct_HWND__, c_uint, c_ulonglong, c_longlong) c_longlong'
<diltsman>
I am assigning the function to this member: lpfnWndProc: ?WNDPROC,
<diltsman>
I would almost guess that the conversion to a function pointer strips the stdcallcc qualifier...
adamkowalski has quit [Quit: Lost terminal]
qbradley has quit [Remote host closed the connection]
traviss has quit [Ping timeout: 250 seconds]
frmdstryr has quit [Ping timeout: 265 seconds]
mahmudov has joined #zig
<pixelherodev>
There a readUntilDelimiter that takes multiple delimiters?
<pixelherodev>
e.g. strtok in C with strtok(str, "\n "); will delimit by both spaces and newlines
<fengb>
I’m getting a segfault when trying to create an array larger than ~4MB. Is this due to the fixed stack size?
leeward has quit [Quit: *Poof*]
diltsman has quit [Ping timeout: 260 seconds]
<pixelherodev>
If I finish this LLVM IR parser, should I submit it to the standard library?
qbradley42 has quit [Remote host closed the connection]
<daurnimator>
pixelherodev: hmmm. what users can you forsee?
* pixelherodev
shrugs
<pixelherodev>
There's a Zig parser already
<pixelherodev>
That's what made me think of it
<daurnimator>
we have the zig parser because `zig fmt` is implemented in zig
<daurnimator>
also because it's a requirement for self-hosted
<pixelherodev>
It might be useful for custom backends for self-hosted, but I'm going to not worry about that anytime soon
<daurnimator>
pixelherodev: if its something you see as generally useful; or as a requirement for zig 1.0 (self-hosted + package manager + any other tooling in the zig executable) then it should be in the standard library
qbradley has joined #zig
<fengb>
Bumping the stack didn't resolve it :(
<pixelherodev>
fengb, heap allocate?
<fengb>
Why didn't I think of that?
<fengb>
lol
<fengb>
Oh it must be because I'm trying to return megabytes
ManDeJan has quit [Ping timeout: 250 seconds]
<fengb>
Okay it's working. Thanks
<pixelherodev>
np
<fengb>
I blew out the heap at 10GB lol
<pixelherodev>
annnnnd I ran into #3028. *Yay*.
<pixelherodev>
s/8/9
qbradley has quit [Ping timeout: 260 seconds]
ManDeJan has joined #zig
traviss has joined #zig
daex has quit [Ping timeout: 240 seconds]
casaca has quit [Ping timeout: 265 seconds]
daex has joined #zig
ManDeJan has quit [Ping timeout: 276 seconds]
<pixelherodev>
There a workaround for "Assertion failed at /home/noam/Documents/Development/Builds/zig/src/codegen.cpp:5274 in ir_render_slice. This is a bug in the Zig compiler."?
<pixelherodev>
Context: the existence of `std.ArrayList([]const u8).init(allocator)` causes that to show up
<pixelherodev>
... or not. Argh.
<daurnimator>
pixelherodev: often those sort of errors are encountered when something is already wrong
<pixelherodev>
It occurs when trying to instantiate `const AttributeGroup = struct { id: usize, attributes: std.ArrayList([]const u8) };`
<pixelherodev>
Huh. ... is there any reason slicing a slice would throw that?
ky0ko has quit [Ping timeout: 240 seconds]
<pixelherodev>
Oh riiiight, it was an implcit casting thing
<pixelherodev>
Should have been a compiler error but yeah that was a code issue
<pixelherodev>
Thanks!
riba has joined #zig
riba has quit [Ping timeout: 240 seconds]
ManDeJan has joined #zig
johnLate has quit [Ping timeout: 240 seconds]
ManDeJan has quit [Ping timeout: 265 seconds]
<mq32>
andrewrk: would async/await be the right thing to schedule stuff in game logic? i would like to write my game code linear, even though it would require "background tasks" like rendering
<mq32>
so my idea right now is something like
<mq32>
var userResponse = await ui.showMessageBox("Please click yes or no!");
johnLate has joined #zig
<Pistahh>
mq32: I just played with async/await a couple of days ago, based on that I think your idea can work. Obviously a lot depends on the rest of your stuff
<mq32>
yeah i know
<mq32>
my idea is that the game logic yields to the framework and will be resumed as soon as the framework finished the action
<mq32>
so like
<mq32>
await movePlayer(.up);
<mq32>
and this will resume after the player has moved a tile
<mq32>
i still struggle with what "await" actually does
<mq32>
i have understood suspend and resume, but the async/await is still a mystery to mee
<Pistahh>
it may or may not make it easier to understand if in your mind you replace "frame" with "coroutine"
<Pistahh>
i.e. foo = async something() makes a coroutine that can be referred to as "foo"
<Pistahh>
this "coroutine" may suspend itself (waiting for something else to produce the data it needs, and that producer can use suspend to "wake it up"
<Pistahh>
sorry, the producer can use "resume" to "wake it up"
<Pistahh>
then this coroutine can return some walue, and "await foo" receives that result
<Pistahh>
value.. bah, it is morning and I haven't reached the 3rd coffee yet
<mq32>
hehe
<mq32>
yeah, thats all "kinda" clear to me
<mq32>
but i think i need a flow chart or something :D
<Pistahh>
ugh, given the nature of the issue - things getting suspended/resumed, I can't imagine how to represent it on a flow chart in a meaningful way :D
<Pistahh>
for me a flowchart would just make it worse :)
<mq32>
hehe
<mq32>
maybe not flowchart, but sequence diagram
<mq32>
because afaik await is also a suspend point
<mq32>
was a fun project, and probably the thing with the biggest data sets i've worked with
<Pistahh>
mq32: yes, await essentially suspends the calling frame, and it is resumed when the await-ed function returns
<mq32>
but where? :D
<mq32>
that's my problem right now
<mq32>
is that stored in the frame of the awaited function?
Yardanico has joined #zig
<Pistahh>
I don't know how zig actually does it; if I needed to implement it the code for await-ing a function generated by the compiler would get the frame for the actual function (@frame), put it on the stack of the called function, and make the called function use that when returning to resume the calling function
<mq32>
hmm
<mq32>
i have to play around with async/await a bit to get a grasp on what happens when
<mq32>
btw, on the discussion of safe recursion from yesterday:
<mq32>
it would be possible to create a "StackFrameAllocator" that does continuous memory allocation and thus, create a reasonable stack memory layout working together with CPU architectures *and* limiting recursion depth
<daurnimator>
mq32: it should be the opposite: async/await are easy, suspend/resume are tricky :)
<mq32>
usage: yes
<mq32>
understanding: no
<mq32>
:D
<mq32>
suspend/resume are quite clear to me what they do and how i would implement that in assembler
marmotini_ has quit [Read error: Connection reset by peer]
Wallbraker has joined #zig
marmotini_ has joined #zig
marmotini_ has quit [Remote host closed the connection]
dimenus has joined #zig
paulriddle has joined #zig
<paulriddle>
Hello everyone. I know Zig can cross-compile C code. However I'm not sure to what extend I can control the whole process. It has default set of options for compilation and I'm not sure how I can overwrite them. So I figured it's simpler to cross-compile with Clang. I've seen how it can be done, but it used some parts from already cross-compiled GCC toolchain. I'm wondering if it's possible to avoid
<paulriddle>
relying on GCC and use whatever comes with Zig instead?
<pixelherodev>
It is
<pixelherodev>
Most clang options can be passed directly to zig
<pixelherodev>
s/most/most relevant
<paulriddle>
I've seen some questionable stuff in the logs. For example I cross-compiled for MIPS with musl, and have seen musl being complied without stack protector. What if I want musl with stack protector?
<paulriddle>
But it's good to know that I can pass options to clang.
<paulriddle>
There has been project called The Clang Universal Driver. It seems to be dead. Doesn't Zig essentially implement it?
<paulriddle>
What's the difference between libgcc and glibc?
<mq32>
glibc is a C library
<paulriddle>
I know that. But so is libgcc,
<mq32>
libgcc is a supplement library that provides implementation for instructions that do not exist on target HW
<mq32>
so for example 64 bit multiplication
<paulriddle>
For clang compiler-rt is the same as libgcc for GCC?
<mq32>
yeah
<paulriddle>
When cross-compiling C with Zig, does it compile compiler-rt for the target platform?
<mq32>
it should
<paulriddle>
I cannot pass -O0 to clang via zig, I give `zig build-exe --c-source hello.c --library c --verbose-cc -O0 -target aarch64v8-linux-gnu` it says Invalid argument
<mq32>
maybe you can use "zig cc"
<mq32>
that's just "clang"
<mq32>
it emits an object file you can use for linking with zig build-exe later
paulriddle has quit [Quit: leaving]
waleee-cl has joined #zig
gonzus has joined #zig
<gonzus>
I know how to create a HashMap with `var map = std.AutoHashMap(i32, void).init(std.heap.direct_allocator);` -- but how do you declare a variable in a struct to hold that map? What type should it have?
<fengb>
The type should be std.AutoHashMap(i32, void)
<Pistahh>
andrewrk: when using "suspend" what is the purpose of its code block "parameter"? When is it executed? How is it different than just simply execute it before the suspend statement?
<gonzus>
@feng
<gonzus>
fengb: thanks, that works.
mahmudov has quit [Remote host closed the connection]
<Snektron>
mq32: cool
<Snektron>
What kind of visualization method does voxie use?
<mq32>
i have implemented three styles
<mq32>
(btw, it uses OpenCL)
<mq32>
first style is marching cubes + OpenGL
<mq32>
second style is "solid surface detection" with raymarching
<Snektron>
My project was also for CT data really, but the illustris volumes proved quite nice for it too
<mq32>
and the third style was raymarching with addition
<Snektron>
Ah
<Snektron>
Mine uses full on ray tracing
<mq32>
what does "raytracing" mean in this context?
<mq32>
i remember myself of a octree traversal i implemented in OpenCL
<mq32>
traversal without the requirement of a stack
<mq32>
was kinda neat
<mq32>
but would require too much additional memory for voxel grids
<Snektron>
mq32, the integration you used doesn't quite produce the correct colors
<Snektron>
Its good enough
<Snektron>
Stack isnt really the end of the world
<mq32>
hehe
<mq32>
yeah it isn't "correct" but!
<Snektron>
For bvh you can just set a pointer to the parent though
<mq32>
we have postprocessing for that
<Snektron>
For octrees also
<Snektron>
But
<mq32>
the 3D part is just for "getting a first view"
<mq32>
for real inspection, you have a 2D slicing tool with finegranular settings
<Snektron>
You can deduplicate the octree to make the volume a lot more compact
<mq32>
that's a neat technique
<mq32>
i got to go
<mq32>
laters
<andrewrk>
Pistahh, it has to do with multi threading. the suspend state is set upon entry to the block, so the function is considered to be suspended already, during the execution of the suspend block. this is useful if you need to for example spawn a thread that will resume the function - if it wasn't already suspended you'd have a race condition
<Pistahh>
andrewrk: makes sense, thx
<andrewrk>
async/await are the higher level APIs, a bit harder to get wrong
<andrewrk>
suspend/resume are lower level, useful tools when writing the "guts" of your application
casaca has joined #zig
<gonzus>
If I create a struct with an init method that allocates memory, I guess I cannot just put a `defer` in the init method to clean it up, because that defer will be called when exiting the init method, right?
<gonzus>
If this is correct, can you use a defer at all to manage the memory here?
Akuli has joined #zig
<dingenskirchen>
yeah you'll need to provide a free/deinit method for your struct gonzus
<dingenskirchen>
but users can `defer` that immediately after calling init
<gonzus>
Ah, I see. So you transfer the `defer` call to where you are initting your larger structure? Ok.
frmdstryr has joined #zig
noonien has joined #zig
reductum has joined #zig
<mq32>
gonzus: there is also errdefer for when something gets wrong
<fengb>
Why would release-small be 10x faster than release-fast?
<gonzus>
mq32: yeah, I am aware. Thanks!
<mq32>
fengb: cache
<mq32>
and "order of modules"
<fengb>
But... 10x
<mq32>
there's a talk from this cppcon on "global optimizations" where some where just "swap those two modules in the build order"
<mq32>
yes
<mq32>
imagine you have a function on the hot path
<mq32>
close to your currnet function
<mq32>
or far away
<mq32>
caches will mess up or not
<fengb>
I'm benchmarking
<mq32>
perf should measure that
<fengb>
So this should be the only hotpath
<mq32>
(cache misses and so on)
<fengb>
And the difference is only 1.5k
<fengb>
Bleh, I spent all night implementing a bit twiddling algorithm, and the 10 minute iterative version is better :(
<mq32>
that's usually the case :D
<andrewrk>
fengb, maybe you can rescue the project by introducing vectors
<fengb>
wasm doesn't have simd yet
<andrewrk>
oh. hmm I wonder if this is would theoretically be better with a different interpreter / jitter
<andrewrk>
hard to measure perf with non-machine-code
<fengb>
I haven't noticed this in real world applications so not sure what's going on
kapil_ has quit [Quit: Connection closed for inactivity]
FireFox317 has joined #zig
<andrewrk>
fengb, I'm a little bit surprised that this is turning out to be so involved - I would have expected a page allocator to be pretty minimal
<fengb>
I'm making it harder than it is :P
<fengb>
I want to make sure iterating through 65536 bits wouldn't be terrible
<andrewrk>
you could have another integer whose bits map to multiple of the 65536 bits, telling whether there are any 0 bits
<andrewrk>
e.g. a u8 where each bit represents 8192 bits
<fengb>
Yep that's the thing I just did in 10 minutes >_>
<andrewrk>
nice :D
<fengb>
I spent all last night doing the bit twiddling magic only to discover this is just faster for most cases
<fengb>
So it's my fault for not exploring that first
<andrewrk>
this is O(log32(N)), pretty efficient
<FireFox317>
andrewrk: weren't you saying that you were going to stream after the AoC of yesterday? I didn't saw anything on YT :)
<andrewrk>
FireFox317, yeah, I'll do it today!
<andrewrk>
last night I prepared the codebase
<FireFox317>
oooh nice, looking forward to it :) doing AoC day 3 now
gonzus has quit [Remote host closed the connection]
<andrewrk>
argh, not being able to mix release llvm + debug zig on windows is really annoying
<andrewrk>
it's such a strange limitation of msvc
<Prf_Jakob>
andrewrk: Linking against LLVM statically?
<andrewrk>
I've tried both ways. If you don't give the same Debug/Release configuration parameter to LLVM as you give to Zig, then MSVC spits out linking errors
lunamn has joined #zig
<lupine>
awesome, I managed to crash teh compiler :D
<Prf_Jakob>
andrewrk: Yes because MSVC selects different compiler-, C- and C++-runtimes depending Debug/Release and Single- or Multi-Threading.
<lupine>
but more immediately, I'm trying to use https://ziglang.org/documentation/master/std/#std;mem.SplitIterator.next but struggling to work out how to pass a `const []u8` to a function that takes a `u8`
<frmdstryr>
lupine, make a copy
<andrewrk>
lupine, consider the situation intuitively. why is your slice const? why does the function need a mutable slice?
<lupine>
well, I just changed the function to pub fn parse(in: []const u8) and that worked
<lupine>
back to the compiler crash :D
<andrewrk>
Prf_Jakob, I understand why it's happening. But it's a problematic limitation that does not exist on other platforms
<frmdstryr>
Can I call a function using a compile time string? like @call(T, "someFn") ?
<lupine>
ah, down to a missing try, I'll see i can get a repro together. the naive attempt correctly fails
jmiven has quit [Quit: bye]
jmiven has joined #zig
<frmdstryr>
I'm trying to do if (hasFn("someFn")) @field(T, "someFn")() but it doesn't allow me :)
wilsonk has quit [Ping timeout: 276 seconds]
wilsonk has joined #zig
mahmudov has joined #zig
deesix has joined #zig
protty has joined #zig
<tgschultz>
frmdstryr, what isn't working?
<tgschultz>
because in the code you've given, std.meta.trait.hasFn returns a function and you need to do this: if(hasFn("someFn")(T))
<frmdstryr>
Yeah that's what I had
<tgschultz>
is there an error reported?
<frmdstryr>
Yea it says T has no field someFn
qbradley has joined #zig
<protty>
is someFn a T struct field (`someFn: fn() void,`) or a function inside the T struct (`fn someFn() void {}`)?
<tgschultz>
weird. I can confirm something odd here with a quick godbolt session. Let me see if I can track down more because hasFn seems to be broken.
<tgschultz>
In the meantime, you can use @hasDecl("")
<tgschultz>
@hasDecl(T, "someFn")
<tgschultz>
oh, nevermind, my issue was user error.
<tgschultz>
hasFn should work as long as T has an fn decl called "someFn"
<andrewrk>
tgschultz, how you doing btw? what zig issue(s) are most of interest to you these days?
<andrewrk>
still the vtable / interface thing?
<tgschultz>
andrewrk, I've been busy outside the zig world for a while now and haven't had time to dive back in. The interface thing is still of interest to me since I think it is important to get right for a lot of reasons.
<andrewrk>
good to know
plumm has joined #zig
<plumm>
are there any special commands for building on mac os? im getting linker errors, specifically dyld_stub_binder. I've set the macos min version, linked c and set the target to gnu
<tgschultz>
frmdstryr there is some confusion here caused by the use of the term "field" to refer to both declarations and instance fields. #1439 has more information.
Akuli has quit [Quit: Leaving]
<tgschultz>
andrewrk, since that issue was closed I'm wondering if the last bit about "field" being renamed or split got lost from the todo list.
<andrewrk>
tgschultz, I think that did get lost
<tgschultz>
Shall I open a proposal to add it, jsut so we can keep track of it?
ur5us has joined #zig
wilsonk has quit [Ping timeout: 265 seconds]
<tgschultz>
I went ahead and did that
<frmdstryr>
Has there been any benchmarks done on zig's streams?
<andrewrk>
frmdstryr, yeah, llvm has a hard time optimizing them
wilsonk has joined #zig
<frmdstryr>
My hello world http server is doing 300 req/s
<plumm>
v_v
<companion_cube>
that's not just llvm then :)
<andrewrk>
plumm, people are thankful for your godbolt pull request
<frmdstryr>
If I try to use a large fixed buffer I get "allocation failed" when trying to build
<andrewrk>
frmdstryr, what allocator are you using?
<frmdstryr>
The direct allocator which I'm guessing why it's so slow
<andrewrk>
that's mmap() for every call, and munmap() for every free
<frmdstryr>
Trying to use a FixedBufferAllocator but it wont let me use more than like 10k?
<andrewrk>
what are you initializing the buffer with?
<andrewrk>
and where are you putting it?
<frmdstryr>
var buf: [250 * 1024 * 1024]u8 = undefined;
<frmdstryr>
Also zig is using 22GB of Ram
<frmdstryr>
so that's probably it
<andrewrk>
that's a bug, it should definitely figure out not to expand that undef array
<companion_cube>
frmdstryr: are you following any existing codebase for your httpd?
<frmdstryr>
It's loosely based on tornadoweb
<companion_cube>
the C part? hmmmm no idea what that looks like ^^
<plumm>
frmdstryr: why not use an arena?
<frmdstryr>
Ok using a fixed buffer it got up to 1329 req/s
FireFox317 has quit [Remote host closed the connection]
FireFox317 has joined #zig
wootehfoot has quit [Read error: Connection reset by peer]
urluck has quit [Remote host closed the connection]
<frmdstryr>
Does zig have any profiling features (other than using a timer)?
<andrewrk>
no but profiling tooling that works on native binaries works on zig
urluck has joined #zig
FireFox317 has quit [Ping timeout: 265 seconds]
<andrewrk>
I'm planning to stream on zasm in about 30 minutes
<companion_cube>
the stdlib docs are a bit sparse on streams, there's just these `var` types :/
<frmdstryr>
Pushed the code here https://github.com/frmdstryr/zhp maybe someone can find some stupid things I'm doing that's slowing it down
<andrewrk>
which release mode did you choose to test?
<frmdstryr>
Just using zig build run debug?
<andrewrk>
yes the default build mode is debug
<andrewrk>
it looks like you have 1 arena allocator for the entire process. that's not quite what you want, I think. you probably want 1 arena per request
<andrewrk>
and rather than freeing the arena, you probably want to reset it, and return it to a pool
<andrewrk>
also the comment on line 1 of main.zig looks outdated :)
<frmdstryr>
Ha, yes, it is far from that now
<andrewrk>
another thing to keep in mind is that zig std lib integration with evented I/O is not complete. many things that are planned to be async, will instead still block
<andrewrk>
for example, std.os.read is integrated with evented I/O, but std.os.write is not. this compromises the entire thing
<protty>
It also looks like Application.start() runs each http handler synchronously (each incoming connection cant be accepted until the current one is finished processing and disconnects)
<andrewrk>
but it's really useful to have projects like this, so we can see if they improve from making these modifications to the std lib
<andrewrk>
yes I haven't found the place where it accepts a request yet, but I would expect to see an async there, something like: `async handleRequest();`
<frmdstryr>
its in Application.connectionMade
<frmdstryr>
Sorry Application.start
<frmdstryr>
If I run wrk with a single thread and 1 connections it's about 1k req/s
<frmdstryr>
with a single thread and 128 connections its around 1.7k req/s
<frmdstryr>
I'm never calling "await" anywhere in start so I'm not really sure how it works at all
waleee-cl has quit [Quit: Connection closed for inactivity]
<andrewrk>
if you've used go before, you can think of an async function call similar to a go function call
<andrewrk>
go doesn't allow collecting the return value; you have to use channels for that. but zig lets you `await` the result to obtain the return value of the function
<frmdstryr>
So in the loop in start it should be "async self.connectionMade(" ?
<protty>
andrewrk: would it be possible for `resume` to return an option type of the async functions result (similar to rust's `std::Future::poll()`) to know when the async function completed?
<andrewrk>
protty, currently, `resume` asserts that the function is suspended. that would be a departure from the current semantics
<andrewrk>
there's a problem with the option type thing, because it would potentially race with the function completing and having its frame freed. the `resume` could be a use-after-free
<andrewrk>
you should be able to orchestrate this manually though - with a flag that is a local variable in the function, which the suspend block makes accessible to the code that wants to resume
<andrewrk>
I'm about to start streaming
<protty>
what about if the function changes its status atomically: resume would do `casStrong(.Suspended, .Running)`, suspension could do `assert(Xchg(.Suspended) == .Running)`
<protty>
alrighty, see you there o/
<daurnimator>
frmdstryr: also have an arena per-connection
doublex_ has quit [Ping timeout: 245 seconds]
ltriant has joined #zig
protty has quit [Remote host closed the connection]
lunamn has quit [Ping timeout: 265 seconds]
lunamn has joined #zig
qbradley has quit [Remote host closed the connection]