ChanServ changed the topic of #zig to: zig programming language | | be excellent to each other | channel logs:
jjido has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<andrewrk> does anyone know where the triangle vertices are specified in this code?
<andrewrk> I should probably go read the tutorial
<andrewrk> afk, back in an hour or two
<shritesh> andrewrk: I got C hello world to compile to wasm32-wasi using zig CLI, linking to (a “cloud” fork of musl and other libs) and running inside
<shritesh> Rust directly vendors in wasi-sysroot which seems to be the only (and reference) WASI implementation. We can probably do the same.
<shritesh> I have started making Zig userland aware of WASI and will try to get things up and running.
mnoronha has joined #zig
<shritesh> Nvm all that complexity. WASI, turns out, has a clean API that we can implement zig's stdlib on
mnoronha has quit [Quit: The Lounge -]
<andrewrk> shritesh, excellent. this is analogous to libSystem on macos or the freebsd libc
<andrewrk> now I'm thinking about a userland implementation of a wasi interpreter
<shritesh> That'd be even cooler.
<andrewrk> it would be pretty straightforward with @import("std")
<andrewrk> then `zig test -target wasm32-wasi` would work
<andrewrk> I really don't think it would be that much code
<shritesh> Does that mean we can have a WASI interpreter in std?
<shritesh> If that's the case, wasi could be an easy choice for embedding in games / such in Zig
<andrewrk> I think that would be pretty reasonable
<andrewrk> it's planned to audit the std lib before 1.0.0 and decide what to keep and what to put in a separate package
<andrewrk> until then, let's go for it
<shritesh> This is exciting.
<andrewrk> what's especially cool is that it can be implemented in userland, but we can still ship it before we have self-hosted zig
<andrewrk> the same way we do zig fmt
<andrewrk> plus with the fact that it was implemented in userland wouldn't even have the overhead cost of child process execution
<shritesh> I want to work on this :D
<andrewrk> :D
<shritesh> ...and I think interpreter be compiled as an OS to bare metal in freestanding mode, right?
<shritesh> *can be
<andrewrk> how I was imagining it would work is that it would 1. parse the wasm 2. do the instructions 3. call out to the standard library for the system stuff
<andrewrk> for it to work in freestanding you would want to use the same code for (1) and (2) but not (3)
<andrewrk> so I think if you wanted it in freestanding, we would just expose the parser and maybe the memory/instructions handling as some kind of API
<andrewrk> and then a higher level api that freestanding would opt out of, that would handle the wasi "syscalls"
<shritesh> Makes sense
<andrewrk> same with a game engine, it would want to be in charge of (3)
<shritesh> Let's make this happen. I'll probably be able to implement WASI compiling and a basic stdlib over the weekend.
<shritesh> *get WASI compiling
<andrewrk> I'm excited
<shritesh> Same. This is not the kind of thing I usually get to work on, so that'll make it even more fun.
<gamester> andrewrk: in the shader
very-mediocre has joined #zig
very-mediocre has quit [Ping timeout: 256 seconds]
wilsonk has quit [Ping timeout: 264 seconds]
wilsonk has joined #zig
jjido has joined #zig
hio has joined #zig
ManDeJan has joined #zig
<ManDeJan> What is the best way to debug an 'index out of bounds' error? My code works in fast and small builds but crashes in safe mode
dewf has joined #zig
<andrewrk> ManDeJan, how about debug mode? you should get a stack trace. or you can use a debugger
<ManDeJan> is using -Drelease-safe not doing debug mode?
<ManDeJan> Well not using any release modes gives a stacktrace, but its just printing a bunch of question marks
<ManDeJan> Like this: ???:?:?: 0x7f55b0481223 in ??? (???)
jjido has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<ManDeJan> andrewrk, gdb only has this to say: 0x000000000021e3ec in (self=0x7fffffffd238)
<ManDeJan> at /usr/lib/zig/std/debug.zig:254
<ManDeJan> 254 const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
<ManDeJan> A segfault
daurnimator has joined #zig
<andrewrk> you can look up the stack in gdb, even if it segfaults when printing the stack trace. keep going up the stack until you see where the index out of bounds occurred
<ManDeJan> Ah thank you! :)
l1x has quit [Read error: Connection reset by peer]
walac has quit [Ping timeout: 264 seconds]
l1x has joined #zig
walac has joined #zig
<ManDeJan> This is what I'm working on btw: , maybe a good candidate for
<daurnimator> struct layout isn't specified is it
<andrewrk> not unless you use packed or extern
scientes has quit [Ping timeout: 268 seconds]
marmotini_ has joined #zig
fsateler_ has joined #zig
fsateler has quit [Ping timeout: 246 seconds]
marmotini has joined #zig
marmotini_ has quit [Ping timeout: 264 seconds]
marmotini_ has joined #zig
marmotini has quit [Ping timeout: 246 seconds]
jjido has joined #zig
greglefox has joined #zig
<greglefox> Hello everyone. First massive congrats for 0.4, impressive changeslog.
<greglefox> I have some nooby questions regarding the language design, I am not sure this is the right place
<greglefox> Still will try, hope I don'y bother
<greglefox> 1) why using '{' '}' for the init of struct, and not parenthesis ? var x=MyStruct(.x=45) instead of var x=MyStruct{.x=45} ?
<greglefox> 2) why using .x instead of x to refer the field x in a struct ? var x=MyStruct(x=45)
<greglefox> (I guess: only to clarify the scope of x within the initialization call?)
marmotini has joined #zig
<greglefox> 3) why struct does not guarantee field order if not packed (documentation says: struct field order is determined by the compiler for optimal performance, any example) ? var myVector = Vec3(1.0, -0.3, 4.5) vs myVector = Vec3{.x=1.0, .y=-0.3, .z=4.5}
marmotini_ has quit [Ping timeout: 264 seconds]
<daurnimator> interesting.... seems like I need to use `var a = &myarraylist;` or else I can append to it and not modify the original!
<daurnimator> I was lucky in that some unrelated testing caught it
gunnarahlberg has joined #zig
<gunnarahlberg> hi! I'm trying to understand how to debug a problem.
marmotini_ has joined #zig
<gunnarahlberg> argh... I'm not able to reproduce the problem from this laptop, need to reiterate. I'll be back
marmotini has quit [Ping timeout: 250 seconds]
<gamester> daurnimator: How else would it work? You wouldn't be able to do "auto a = myarraylist" in C++ either, though a copy of the actual array would be made. In C# you could never have a "myarraylist" in the first place, you'd have to 'new' it and get a reference to it (&myarraylist).
<daurnimator> gamester: well in my mind I thought I'd get a copy of the whole arraylist including items; or a pointer. turns out that wasn't the case. was an easy to mistake to make IMO. with nothing to warn me otherwise
<gamester> it's easy to make accidental copies of things in Zig yes, but you should never expect to get deep copies since the language doesn't do that for you :)
<gamester> arraylist is just a struct, something like {ptr, length, capacity}
<daurnimator> gamester: yep.
<daurnimator> gamester: problem is essentially unexpected/unwanted copies.
<gamester> yeah, I agree with that
<gamester> having said that, in a systems programming language not being able to make a copy of a struct without "cloning" it is very limiting, so I like the freedom but it takes some getting used to
gunnarahlberg has quit [Ping timeout: 256 seconds]
<greglefox> No chance...
greglefox has quit [Quit: The Lounge -]
greglefox has joined #zig
greglefox has left #zig [#zig]
jjido has quit [Quit: Connection closed for inactivity]
<daurnimator> Sent in my http header work as #2263
dewf has quit [Quit: Leaving]
scientes has joined #zig
tiehuis has joined #zig
<tiehuis> greglefox: regarding 1 and 2, probably because this is similar to what C does for struct initialization
<tiehuis> and using parentheses for a struct initialiation overloads this with function call syntax
<tiehuis> although while it may be technically viable (since forcing field definitions would probably make it unambiguous) there is the general trend of adhering to common expectation in zig where possible
<tiehuis> would have to ask andrewrk on the specific reasoning though
<tiehuis> oh and for 3, if you want guaranteed field order i think that's possible by doing `const Foo = extern struct { ... }`
<tiehuis> this uses the system C abi which preserves field order
tiehuis has quit [Client Quit]
ManDeJan has quit [Ping timeout: 252 seconds]
marmotini has joined #zig
marmotini_ has quit [Ping timeout: 252 seconds]
very-mediocre has joined #zig
marmotini_ has joined #zig
marmotini has quit [Ping timeout: 252 seconds]
ManDeJan has joined #zig
very-mediocre has quit [Ping timeout: 256 seconds]
very-mediocre has joined #zig
very-mediocre has quit [Remote host closed the connection]
very-mediocre has joined #zig
very-mediocre has quit [Quit: The Lounge -]
very-mediocre has joined #zig
<hryx> I'm having trouble with an inferred error set: `function foo is not fully analyzed yet` -
<hryx> I broadly understand the error in concept, but I'm not sure why I'm only getting it there, and not in many of the other parseXxx functions
very-mediocre has quit [Remote host closed the connection]
very-mediocre has joined #zig
hg has joined #zig
gunnarahlberg has joined #zig
Zaab1t has joined #zig
return0e has joined #zig
return0e_ has quit [Ping timeout: 244 seconds]
very-mediocre has quit [Remote host closed the connection]
very-mediocre has joined #zig
<ManDeJan> What is the Zig alternative for making a variable a reference in C++?
marmotini_ has quit [Remote host closed the connection]
<gamester> a pointer
very-mediocre has quit [Remote host closed the connection]
<ManDeJan> Yes, but that means taking the address of a parameter explicitly at the call site, I was wondering if it was possible to do that implicitly as you do in C++ with a reference
<gamester> ManDeJan: oh, well anything you don't intend to modify in a function should be passed in by value, zig takes care of passing it in efficiently
<ManDeJan> gamester, I want to modify it
<ManDeJan> But I personally don't like the look of a '&' in front of every parameter at the callsite
<shritesh> Zig requires you to be explicit about that by specifying that the function takes in a non-const pointer if it is to be modified.
<ManDeJan> Understandable
jjido has joined #zig
<ManDeJan> How do I take a functionpointer of a generic function?
Sahnvour has joined #zig
gamester has left #zig ["Leaving"]
<mikdusan> ManDeJan: all I can think of is to place it in a struct.
jjido_ has joined #zig
meheleventyone has joined #zig
<ManDeJan> mikdusan, thanks for the suggestion!
<Sahnvour> ManDeJan great to see you implemented wyhash in zig, I was thinking of doing it
<ManDeJan> Thank you :)
<andrewrk> hryx, I think there's an open issue for this, but inferred error sets don't work with recursion
<andrewrk> the workaround is to give an explicit error set for the function that has the compile error in it
<ManDeJan> I don't know how to add proper tests but I'm pretty sure it is 100% of the time generating the same hashes as the C++ implemenation
meheleventyone has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<Sahnvour> well for starters you could add a `test "wyhash" { ... }` block and check that the provided test vectors on the homepage give correct result
<ManDeJan> I did that manually and that works, but I know that is not very scientific :)
<ManDeJan> I'd like the tests to be in a separate directory and include the original wyhash header in zig and compare against that
<ManDeJan> But I was getting errors when trying to include wyhash.h so I gave up trying that
<Sahnvour> fair enough
wootehfoot has joined #zig
<ManDeJan> I'd also like to benchmark the speed against the C++ and Rust implementations as well
<hryx> andrewrk: thanks, I'll employ that error set workaround tonight and continue
<Sahnvour> ManDeJan let me know if you have progress on this, I'm interested too
<andrewrk> ManDeJan, one thing to keep in mind with performance comparisons is that zig turns on -march=native when building for the native target. that's not on by default for C/C++, and I'm not sure whether rust does it
Akuli has joined #zig
<ManDeJan> andrewrk, thanks, I'll keep that in mind :)
<andrewrk> of course if you use zig to build C/C++ code, it will use the "zig defaults" for c code, which includes -march=native for the native target
<hryx> Interesting comment from the person who maintains the smhasher repository:
<hryx> xxh3 "is now the recommended hash for file or db digests"
<hryx> isn't file digests the use case which inspired the initiative for a new hashing implementation?
<andrewrk> ManDeJan, also I'm working on moving translate-c to userland, which I think will make it more attractive for contributors. improving translate-c would make the "getting errors when trying to include wyhash.h" solved and make everything Just Work
<hryx> (@ ManDeJan and Sahnvour re: xxh3 in my previous message -- just curious)
<ManDeJan> andrewrk, nice!
<ManDeJan> hryx, I have not thoroughly looked at xxh3, from what i've seen it looks impressively fast, but also more complicated than wyhash
<hryx> I see, that's an important consideration
<ManDeJan> I think it's impressive how fast wyhash performs taking into consideration how generic its code is compared to the hand tuned intrinsic xxh3 uses
<ManDeJan> It would be cool to see how Zigs vector type compares to platform specific vectorization
<andrewrk> definitely. let me know if one of the checkboxes on #903 is blocking that research
<andrewrk> it also occurred to me that we can use a userland implementation of a hash function instead of src/blake2b.c
<andrewrk> stage1 is going to become a hybrid of C++ and Zig
<hryx> That's pretty neat :>
<ManDeJan> Neat :)
<shritesh> andrewrk, how do I access arch specific builtins like `__builtin_wasm_memory_grow`?
<andrewrk> shritesh, hmm. is there a way to do it in clang?
<andrewrk> if so we can look at the LLVM IR
<andrewrk> or in rust
<shritesh> Yes, that's a clang-specific function available to all C code.
<andrewrk> it looks like a regular old external symbol
<shritesh> Hmm. Lemme try that
<andrewrk> so you could do: extern "wasi" fn __builtin_wasm_memory_size(...);
<shritesh> it should generate `call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %{{.*}})`
<andrewrk> (not actual elipsis, I just don't know what the fn prototype is)
<andrewrk> ahh
<andrewrk> that's weird, I don't see it in the language reference
<andrewrk> is this documented somewhere?
jjido_ has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<andrewrk> I mean the @llvm.wasm.memory.grow
<andrewrk> I'm going to ask in #llvm on OFTC
<andrewrk> I think it's probably a regular old external function
Zaab1t has quit [Quit: bye bye friends]
<shritesh> If you click on build there and look at line six in main.wasm, it's converted to a current_memory instruction
<andrewrk> shritesh, what is this studio building with? when I use clang 8 to build test.c with `-nostdlib -S -emit-llvm test.c -target wasm32-freestanding` I get "error: use of unknown builtin '__builtin_wasm_current_memory'"
<andrewrk> shritesh, aha, I think the @llvm.wasm.* functions are simply undocumented. I see them when I grep the LLVM codebase
<shritesh> Is there a way to access these from userspace? (also, I have been playing with CUDA and will need these)
<andrewrk> no, we would have to expose them as zig builtin functions
<shritesh> Ah.
<andrewrk> I think that's not so bad, there are only a handful right?
<shritesh> Yeah
<shritesh> Is there a way to do this like inline assembly?
<shritesh> Another use case: CUDA kernels:
<andrewrk> inline assembly would work if LLVM implemented wasm assembly syntax in the target
<andrewrk> I'm not sure whether or not that is the case
jjido_ has joined #zig
<andrewrk> hmmm. I think it's best to go about this the proper way, without introducing an explicit dependency of the Zig programming language on LLVM. So far there is no such dependency
<andrewrk> e.g. I don't want to have a builtin that is defined to be a string that lowers to whatever that means to LLVM
<andrewrk> I'm ok with having a lot of zig builtins though, to expose all this stuff. I'm open to making it easier to add zig builtins to the compiler (it's currently a chunk of boilerplate to do so)
jjido_ has quit [Remote host closed the connection]
<shritesh> Cool. Will be something that needs to be imported?
<andrewrk> from zig userland perspective it will look like one of these:
<shritesh> That'd be a lot of functions. Can it be namespaced? Like @wasm.currentMemory() or something?
<strmpnk> How is that better than @wasmCurrentMemory?
<shritesh> namespaces are nice :)
<andrewrk> mmm that looks better at first glance, but it introduces complexity to the language
<andrewrk> consider if you never learned zig and you had to guess what it did, @wasmCurrentMemory() vs @wasm.currentMemory()
<andrewrk> the former leaves less to the imagination
<strmpnk> A prefix with a dot looks nice visually but mechanically, I think it’s misleading without the rest of struct features.
<shritesh> agreed
<shritesh> I'd expect much of these to be hidden behind stdlib anyway
<andrewrk> right
<strmpnk> I’ve never tried it but are builtins allowed to be aliased or just invoked?
<andrewrk> the former. a "builtin function call" is the syntax
<strmpnk> In that case, perhaps namespacing makes more sense. And the @ syntax would be property access of a prelude module.
<bheads_____> could userland code generate zig ir for things like this?
<andrewrk> I don't understand your question bheads_____
<bheads_____> well I guess I dont know how the builtins work in zig IR to llvm ir
<ManDeJan> I made some functional programming things work at compile time :D
<hg> it's super cool that godbolt supports zig
<hg> ManDeJan: looks awesome
<ManDeJan> hg, thankyou, I'm also very happy with godbolt supporting zig, and godbolt in general
<hg> indeed
<hg> ManDeJan: have you seen the project to do something similar but on a local machine?
<hg> I can dig it up if not
<hg> ^ for whomever may be interested
<hg> particularly cool because it supports a bunch of dynamic languages as well (e.g., python and php)
bheads_____ has quit [Read error: Connection reset by peer]
<hg> I have no idea if zig works with it; but hypothetically, you can add custom compilers
<hg> so I suspect it could be added
<ManDeJan> hg, Looks very fancy
bheads_____ has joined #zig
<hg> yet another reason I should probably take another look at emacs
<hg> I just struggle to bring myself too (I've been in the vi* camp for so long now…)
<bheads_____> huh... compiling zig just locked up debian.... and I had to reboot
<strmpnk> bheads_____: memory limited maybe?
<bheads_____> maybe, I do code in java all day....
<hg> yep, it supports zig
<bheads_____> anyways what I was very poorly trying to express was what if the was a way in user land to express IR directly, like you can asm
<bheads_____> so things like wasm could have user land extensions
<strmpnk> I suppose IR embedding could be done but wouldn't that increase coupling with both LLVM and a particular version of LLVM (their IR isn't super stable AFAICT)?
<hg> strmpnk: definitely not stable
<bheads_____> sure, but asm blocks have the same problem
<hg> well
<strmpnk> CPU architectures seem far more stable though and wouldn't lock down the backend.
<hg> less so since asm for a target is less changing
<hg> 🤷
<bheads_____> is LLVM change in minor release or just major?
<strmpnk> I'm not necessarily against it but it seems intrinsics are a better middle ground.
<bheads_____> I was thinking of a way to get to intrinsics without having them to exists in the compiler already
<bheads_____> could be a good way to pipeline what is useful into the compiler
<strmpnk> True. Some front-ends try to "detect" patterns and replace them with intrinsics.
<strmpnk> Like memcpy.
<bheads_____> it also seems odd to add a ton of wasm target builtins to the compiler
<bheads_____> or cuda
<bheads_____> and if llbm ir not stable enought then the it could be the zig ir (zig has its own ir... or did I just dream that)
<bheads_____> llvm^ ***
<strmpnk> Yeah. I kind of want to try my hand at a naive dynasm backend but I honestly don't have time and could probably do something useful like building more libraries.
<andrewrk> I'm pretty confident about not coupling the zig language to LLVM. The only thing blocking a custom backend is effort
<bheads_____> sure, but I doubt wasm or cuda would be targets for a long time
<bheads_____> just a thought =)
<shritesh> Why'd you think so?
<bheads_____> building a backend to support just x86 x86_64 sse and familly is a big project on its own
<bheads_____> plus arm and ppc
<bheads_____> that builtin list is going to keep growing ...
<andrewrk> it might make more sense to introduce the concept of wasm assembly / cuda assembly, if it doesn't already. assembly is how the zig language lets you do target-specific stuff
<andrewrk> the list of assembly instructions per target is long. the list of zig builtin functions has none so far that are target-specific
<bheads_____> and this would be a target built in @wasmCurrentMemory()
<bheads_____> so I guess if wasm had asm then my suggest is moot
<andrewrk> right. maybe it should be `asm ("(current_memory)" : (-> usize)`
<shritesh> I have a diff of +33 to add @wasmCurrentMemory() usize
<shritesh> C++ is painful
<shritesh> I think I should look into the asm route.
Akuli has quit [Quit: Leaving]
<andrewrk> it's quite possible that LLVM has assembly support for wasm
<shritesh> I'll see what clang -S outputs
<strmpnk> Inline .wat expressions would be interesting for wasm. I'm not sure how easy it would be with LLVM's implementation though. You'd probably have to create function wrapper for each sequence.
<andrewrk> <dschuff> in theory inline asm should work but it's not well-tested at all
<andrewrk> discussion over in #llvm on OFTC
<shritesh> I don't think LLVM knows about WAT at all
<strmpnk> Right, it'd be a module for the wasm linking process.
<andrewrk> shritesh, one thing we can explore, is detecting certain patterns of inline assembly and translating them to llvm intrinsics
<andrewrk> so that would avoid adding extra builtins to zig, but would still benefit from using the LLVM intrinsics in the backend
<andrewrk> I think that's a pretty good compromise
<andrewrk> so in pass2 of Zig IR for inline assembly, we look for "(current_memory)" with result type `usize`, and emit a special zig ir instruction which is the wasm32_current_memory intrinsic, which turns into the LLVM intrinsic
<andrewrk> I think that should work for grow_memory too
<andrewrk> and all the cuda stuff
<shritesh> That does require a list of mappings known to the compiler, right?
<andrewrk> yes
<shritesh> That'd work
<andrewrk> that should be less boilerplate than adding everything as a separate zig builtin function
<shritesh> For sure
<andrewrk> does the pass1, pass2 of zig IR make sense? I can explain that
<andrewrk> the ir_gen_* functions which deal with IrBuilder are "pass 1". these don't have type information available but they flatten out the AST into Zig IR.
<andrewrk> the ir_analyze_* functions which deal with IrAnalyze are "pass 2". these have full type information, and are responsible to do comptime evaluation and populate the ConstExprValue, or emit a runtime Zig IR instruction
<shritesh> Hmmm
<andrewrk> finally in codegen.cpp, the ir_render_* functions look at those Zig IR instructions and emit LLVM IR instructions
<andrewrk> you would detect the patterns in ir_analyze_* ("pass 2") and emit a new kind of instruction that in codegen.cpp turns into an llvm intrinsic. Up to you whether you make 1 new IrInstruction for this, or one corresponding to each LLVM intrinsic
hg has quit [Quit: WeeChat 2.4]
<shritesh> Gotcha. I'll look into it
<andrewrk> I could also solve this problem for you to unblock you, but I wouldn't get to it before this weekend
<shritesh> It's okay. I will try to figure it out.
<Sahnvour> hryx lately many hash functions started to take advantage of new instruction sets (AES especially) on x86 to have better throughput
<Sahnvour> but this is best taken advantage of for "large" payloads
<Sahnvour> because these instructions work on 256 or 512 bits at a time
<hryx> I see. In this case, this is mainly for the benefit of ticket #2244 right?
<Sahnvour> hashing files for identification is a good use case, in particular when you control the hardware you run on, to be sure they are accessible
<Sahnvour> I think #224 will resolve to one or two things:
<Sahnvour> either wyhash is shown to also be very very fast for small payloads (ie. u32 or u64 as hashmap keys for example) and it can be the default hash function, regardless of the data size
<Sahnvour> or there are better options and the hash to use would depend on the size of the data
<hryx> hey andrewrk, quick question about this recursive parser rewrite. I find myself adding a lot of new errors like "Expected parameter list, found {}", which you can see here:
<hryx> but I noticed that for existing stage1 and stage2 the pattern seems to be to tell the user what _token_ was expected, not what node/type/expression was expected
<hryx> Should I be following that pattern still? Does "expected token X" make more sense to the user than what I've added?
<andrewrk> hryx, I think you can do what feels simpler and then as a future design iteration we can reevaluate what kind of error messages work better / integrate better with IDEs
<andrewrk> does that sound reasonable?
<hryx> sure does, thanks
<hryx> the "expected node" approach is more intuitive to me right now, can reevaluate later
<andrewrk> sounds good to me
<hryx> gonna get a big chomp done on the branch this weekend
<andrewrk> excellent
nullher0es has quit [Remote host closed the connection]
ManDeJan has quit [Ping timeout: 255 seconds]
Summertime has quit [Quit: Sunsetting.]
Summertime has joined #zig
wootehfoot has quit [Read error: Connection reset by peer]
Sahnvour has quit [Quit: Leaving]