<andrewrk>
this is the big goal here: integrate std.os.write with async io mode
<fengb>
I can't because the outstream crashes on a segfault :P
<andrewrk>
yeah, alright let me prioritize those async related bugs you reported recently
<fengb>
I need to reduce this last one. Maybe I can find a workaround
<fengb>
But it’s a doozy because out stream goes everywhere. Pretty sure switching debug.warn over is causing some problems
<andrewrk>
inspecting the crash with gdb can often lead to shortcuts in figuring out how to reduce
<andrewrk>
basically you go up the stack until you see any IrInstruction and use the dump() method to have it printt the source location
<andrewrk>
fengb, oh yeah, even making the callback comptime is still a problem, because format() becomes an async function, and then you still have to solve the recursion problem
doublex has quit [Ping timeout: 265 seconds]
<daurnimator>
hmmm why didn't I have these issues in my stream branch?
<fengb>
It seems to be able to analyze everything
<andrewrk>
oh, it's the missing spill, right? the llvm error message with "dominate" ?
<fengb>
It’s missing a spill in the optional if block but that was an easy workaround
<fengb>
andrewrk: format is *always* async and the only recursion point is struct / union analysis, which has a max depth. I haven't been able to get custom formatters working yet due to the posted bug, but I don't see why it wouldn't "just work"
<fengb>
Unless this bug is me completely mangling the semantics, which is quite possible >_>
<daurnimator>
fengb: why always? e.g. bufPrint shouldn't be async...
<fengb>
The internals are async due to generators. Nobody should notice it’s async
<andrewrk>
oh wow fengb I think your bug might actually be solved in the branch I was planning on working on today anyway
<andrewrk>
has to do with solving the inconsistency of how result locations work with comptime stuff vs runtime stuff
<fengb>
Ah okay cool
<fengb>
We need a cloning machine to have you work on PRs and actual tasks
<andrewrk>
yeah, or, you know, a hiring budget
plumm has quit [Quit: Lost terminal]
<via>
andrewrk: in C at least the use of volatile for that use case would make sense
<via>
would be appropriate rather. that is a use case outside of mmio
<via>
in this case both volatile and atomic are valid, but they mean different things. the volatile is relevent for the fact that the memory location can be changed behind the compiler's back, the atomic because it can race with the isr -- though for this use case a u32 would be an atomic load/store no matter what
<via>
not sure if zig's volatile 100% matches C
<andrewrk>
via, atomic and not volatile is correct here in both zig and c
<andrewrk>
even if arm 32 has atomic u32 loads/stores, atomic operations tell the optimizer that there is more than 1 thread observing the memory (interrups count)
<via>
i can envision situations where the atomicity of a load store between threads is not actually needed
<via>
but volatile explicitly in c at least is to instruct the compiler to not assume no changes between memory accesses of the same location
<via>
with what you're describing, why would there be any need for volatile? if atomic tells the compiler also that it can't hold onto loads and stores
<via>
e.g. why would mmio also not just count as another "thread"
<daurnimator>
via: a volatile will *always* be done
<daurnimator>
via: an atomic might be eliminated
<daurnimator>
via: e.g. `const a: volatile *u8 = getsomeptr(); var b = a.*; b = a.*;` will always do two loads.
<via>
i can't speak to c11's atomic types, i don't know them very well, but yes that is my understanding of the purpose of volatile
<daurnimator>
vs `const a: *u8 = getsomeptr(); var b = @atomicLoad(a, .Monotonic); b = @atomicLoad(u8, a, .Monotonic); b = @atomicLoad(u8, a, .Monotonic);` the compile is allowed to skip the first one
<daurnimator>
oops I pasted twice. but you get the point
<via>
i was unaware the atomics could be optimized that way, but especially if thats true i feel like thats reinforcing what i'm saying
<via>
e.g. spinning on reading a memory location that may be changed by an isr
<daurnimator>
"why would there be any need for volatile?" -> because the read might have side effects.
<daurnimator>
volatile means "I want this read to happen the exact number of times I write in the code (but the compiler is allowed to move them around)". atomic is "if you do this load/store, it must happen before/after other such annotated loads/stores"
<via>
are you disagreeing with what andrewrk said? it sounds like you're more or less saying what i was
<via>
i was under the impression volatile was specifically a compiler hint to not optimize loads stores. i was unaware atomic had ordering gaurantees so much as just gauranteeing the write or read happened without overlapping with something else reading/writing to the same location -- e.g. no partial read/write
<daurnimator>
ooo interesting: the "run this code" button above the snippet. We should do that with zig's docs and godbolt
<via>
my googling seems to indicate that even c11's atomic_ types allow a compiler to optimize away subsequent loads, and volatile would still be needed for this case
<andrewrk>
fengb, it tells me that the code got past analysis, something went wrong making LLVM IR instructions, and that a struct field pointer thing generated a wrong llvm type
<andrewrk>
you can get the source location if you go up the stack to #5 and look at instruction.base.dump()
<fengb>
Updated with some more info. Pretty neat
<daurnimator>
`zig run` appears to make files in ~/.cache/zig/stage1 ?
curtisf has quit [Remote host closed the connection]
adamkowalski has joined #zig
adamkowalski has quit [Remote host closed the connection]
ur5us has quit [Ping timeout: 260 seconds]
<daurnimator>
I sort of want separate to have a single-char-delimiter-taking version so that we can return sentinel terminated slices.
doublex_ has quit [Ping timeout: 260 seconds]
<fengb>
I think I need an actual Linux dev box. Celeron / Atom isn't quite good enough :P
dddddd has quit [Ping timeout: 268 seconds]
ltriant has quit [Quit: leaving]
marmotini_ has joined #zig
marmotini_ has quit [Remote host closed the connection]
Astronothing has joined #zig
SimonNa has quit [Remote host closed the connection]
<daurnimator>
fengb: why aren't you running linux as your main machine? :)
spenced has joined #zig
<fengb>
`loop.init()` this is causing _start to be async when I flip os.write to be async :(
spenced has quit [Client Quit]
<fengb>
lol it's easier for me to compile on the mac and copy it over. I love how great Zig's cross platform support
ur5us has joined #zig
_Vi has joined #zig
<andrewrk>
fengb, you gotta figure out where you can make a seam
_Vi has quit [Ping timeout: 260 seconds]
<wilsonk>
daurnimator: wow, thanks for that gdb-dashboard recommendation. Love it!
Astronothing has quit [Read error: Connection reset by peer]
doublex has quit [Remote host closed the connection]
doublex has joined #zig
<bgiannan>
daurnimator, do you know how to disable by defaultl some of the panels of gdb-dashboard? i waste time everytime doing `dashboard assembly`, `dashboard register`etc. to disable those i don't use
spenced has joined #zig
spenced has quit [Client Quit]
spenced has joined #zig
spenced has quit [Client Quit]
ur5us has quit [Ping timeout: 260 seconds]
nimar has quit [Ping timeout: 265 seconds]
marmotini_ has joined #zig
marmotini_ has quit [Remote host closed the connection]
<SyrupThinker>
bgiannan: Append the commands to .gdbinit
<bgiannan>
SyrupThinker, thx
marmotini_ has joined #zig
_Vi has joined #zig
schme245 has joined #zig
marmotini_ has quit [Remote host closed the connection]
dddddd has joined #zig
frmdstryr has quit [Quit: Konversation terminated!]
doublex has quit [Ping timeout: 260 seconds]
marmotini_ has joined #zig
doublex has joined #zig
doublex_ has joined #zig
doublex_ has quit [Read error: Connection reset by peer]
<phillyiscool>
So always pass a pointer when you want to modify a struct in a function
phillyiscool has quit [Remote host closed the connection]
<Snektron>
yes
return0e has joined #zig
return0e has quit [Remote host closed the connection]
marmotini_ has quit [Remote host closed the connection]
<fengb>
Shoot, the last unexplained crash is probably result location
<fengb>
Maybe it'll be resolved by the cleanup?
gonzus has joined #zig
<gonzus>
During Advent of Code, I found myself several times missing a good way to write a while loop where the controlling variable is scoped to the loop only.
<gonzus>
I would write something like: `var j: usize = 0; while (j < top) : (j += 1) { ... }`
<gonzus>
But that means that `j` is available to the code after the loop.
<gonzus>
Is there a better idiom for this?
<mikdusan>
just make a sub-scope ?
<gonzus>
Yes, that works, but it looks really ugly... :-)
<gonzus>
I guess I just wish I could declare that variable inside the `while ()` part. Too much C influence, maybe?
<gonzus>
I mean, that `while` loop has almost everything from a C `for` loop.
<mikdusan>
it's interesting you bring that up. I was just looking at c++17 or 20, and what it does for that. so `for` and `if` allow init-statements. but `while` does not and the general opinions are "well just use for"
<mikdusan>
and if you sit down and think about it, that's a lot of garble,
<gonzus>
Right. This is of course a matter of aesthetics. I am so used to writing `for (int j = 0; j < top; ++j) {...}` that its semantics are absolutely obvious to me. And because I love lexical scoping, RAII, and so forth, I find myself missing that idiom.
<gonzus>
hryx checking that link...
<gonzus>
hryx: interesting read. There is a subtlety to the variable in a C for loop, which doesn't affect C that much but is visible in languages that do support closures.
<gonzus>
Since I already brought up one thing I found myself missing, I will mention another: easier way to express literals (for example, for initializing variables).
dimenus|work has joined #zig
dimenus is now known as Guest65855
Guest65855 has quit [Killed (tolkien.freenode.net (Nickname regained by services))]
dimenus|work is now known as dimenus
<fengb>
I like Go's strategy of only using for loops
<gonzus>
At some point I wanted to have a `HashMap(A, HashMap(B, usize))` and it was a pain to initialize it.
<gonzus>
fengb: I don't know Go well enough. Can you declare variables in Go's `for` statement?
<hryx>
gonzus: Go supports the C-style for loops you want
<gonzus>
I have been doing lots of Perl and JS development lately, and I guess I am spoiled by how easily you can initialize hashes of arrays of hashes of...
<fengb>
No, but it handles iterating by ranges pretty elegantly. It's the same philosophy as "one loop" but using for loops instead of while loops
<fengb>
gonzus: yes but it's supposed to hurt in Zig, because it doesn't map to machine code well :P
<fengb>
Oh oops, I actually forgot the manual loop existed. Okay I'm not a fan anymore >_>
<fengb>
It seems they simply merged 3 different semantics into the for loop
<fengb>
I thought it was more elegant lol
dimenus has quit [Quit: Leaving]
<hryx>
I think the thinking was "this is elegant because we only have this one keyword to remember"
<hryx>
but all those semantics are smooshed in there
<gonzus>
I would still love to be able to do `var data = { "foo": [ 1, 2, 3], "bar": [4, 5], "baz": [6] };`, though.
<fengb>
I've been using for := range forever so I guess I just assumed that was the only option
<gonzus>
With a subset of JSON-like syntax, where each element has a consistent type that could be inferred by the compiler.
<fengb>
You can use anon structs: `.{ .foo = .{ 1, 2, 3 }`
<fengb>
It's not runtime iterable so it probably doesn't solve your problem
<gonzus>
Ah, right. Those are kind of new, correct?
<gonzus>
I have seen more recent code calling `std.debug.warn()` that uses those.
<fengb>
Yeah. Using a struct as a hashmap isn't semantically correct though
<fengb>
That's one thing Javascript did really poorly: mixing records and collections :/
<fengb>
I have to relearn that they're different whenever I switch to a different language >_>
<gonzus>
Agreed. I'm actually thinking more of what Perl does, but with JS syntax (because it looks closer to JSON, which is better known).
Astronothing has joined #zig
Astronothing has quit [Client Quit]
<BaroqueLarouche>
ohhh only 14 pull request, getting near 0!
<fengb>
All of them have been reviewed too so it's effectively 0!
return0e has joined #zig
return0e has quit [Remote host closed the connection]
return0e has joined #zig
Astronothing has joined #zig
doublex has joined #zig
doublex_ has quit [Ping timeout: 260 seconds]
gonzus has quit [Ping timeout: 260 seconds]
schme245 has quit [Remote host closed the connection]
frmdstryr has joined #zig
<fengb>
Hmm, I'm starting to encounter cases where I have to rebuild zig to run std lib tests
<mikdusan>
that doesn't sound right
<fengb>
Some of std lib is being linked into the binary
<fengb>
Or maybe it's the other way around -- my failures in std lib is prevent the build?
Snetry has quit [Ping timeout: 265 seconds]
<mikdusan>
try running tests with `zig0` instead -> `zig0 test lib/std/std.zig`
<Snektron>
<hryx "gonzus: I recently came across a"> This problem is not so bad in languages with explicit typing
<Snektron>
or without reference semantics of basic types
Snetry has joined #zig
<Snektron>
for example, in c++ i could choose between the two with either `[=i] { return i; }` and `[i] { return i; }`
<fengb>
Oh that thing. Go's biggest footgun :P
waleee-cl has joined #zig
marmotini_ has joined #zig
marmotini_ has quit [Ping timeout: 240 seconds]
schme245 has joined #zig
doublex has quit [Ping timeout: 260 seconds]
leeward has joined #zig
schme245 has quit [Remote host closed the connection]
_Vi has quit [Ping timeout: 252 seconds]
SimonNa has joined #zig
doublex has joined #zig
Astronothing has quit [Ping timeout: 265 seconds]
return0e has quit [Remote host closed the connection]
<leeward>
I know why this is failing to compile (4114), but does anyone see any errors in the code? I'm getting a segfault on line 12 if I fix the print calls. https://godbolt.org/z/gJNK4v
<mikdusan>
change to `var logger = ...`
schme245 has joined #zig
<mikdusan>
and change to `const allocator = &logger.allocator;`
<andrewrk>
one reason that while doesn't have its own syntax for declaring a variable is to teach the programmer that it's ok to make sub-scopes
<andrewrk>
people avoid these for some reason, but they are generally good
traviss has quit [Ping timeout: 260 seconds]
return0e has joined #zig
return0e has quit [Remote host closed the connection]
<leeward>
mikdusan: Now I hit os.zig:499 - "EBADF => unreachable, // Always a race condition."
<bheads>
for some reason sub-scopes just look wrong
<mikdusan>
leeward: yeah I only corrected those 2 lines. It looks like locals `stderr` needs a similar fix
<andrewrk>
bheads, this can be unlearned
<bheads>
the only thing I miss is simpler syntax for looping over static ranges
<bheads>
was wondering if that could do solved with slice ranges for(.{1..10}) |x| { ...
<leeward>
Is the plan to do this with generators?
<bheads>
seems like major over kill
<fengb>
You can do `for([_]void{{}} ** n) |_, i|`. Probably not recommended :P
<leeward>
mikdusan: I'm not sure what you mean.
<leeward>
Are you saying `std.io.getStdErr().outStream().stream` should be const?
<mikdusan>
leeward, `getStdErr().outStream()` thinking in C++/Java terms, returns an _implementation_ of `io.OutStream` interface
<fengb>
andrewrk: was fiddling with async os.write last night, all of _start.zig needs some form of wrapping since debug.* all become async due to os.write
<mikdusan>
so first throw that into a local
<mikdusan>
then grab `&stderr_impl.stream` which gives a _pointer_ to the interface
<andrewrk>
fengb, for debug info, we know that we open the files in blocking mode - even when std.io.is_async is true. so we can use `noasync` function calls for debug info stuff
<andrewrk>
this creates a "seam" between blocking and async, and stops the spread of async
<fengb>
Hmm, I can try that
<fengb>
But it calls os.write, which I thought would always be async when io.is_async is true
<andrewrk>
os.write will be generated as an async function, yes
<fengb>
All the debug functions are indirectly dependent on it
<andrewrk>
`noasync` calls an async function, asserting that it does not actually suspend
<andrewrk>
what's interesting about noasync is it allows a blocking function to call an async function
<leeward>
mikdusan: It works! Now to understand why...
<andrewrk>
...as long as the assertion is correct that in this particular case (e.g. fd is in blocking mode), the async function does not actually take advantage of its async-ness and suspend
<fengb>
Aha
<mikdusan>
leeward: do you use C++?
<andrewrk>
I believe there is safety for it even
<leeward>
I've bumped into this before, with allocators. Why can't I get `.stream` from the `getStdErr().outStream()` directly?
<fengb>
I'm actually really happy with how this is turning out. The fact that format() is internally async does not matter to the rest of std
<leeward>
mikdusan: Not when I can avoid it. I haven't professionally for about 10 years.
<fengb>
I know that was the intent... but I really didn't expect it to work so seamlessly
<andrewrk>
seamlessly except for the 3 compiler crashing bugs you filed 🙃
<fengb>
Architecturally it's sound
<fengb>
Unless those bugs are actually exposing bad semantics... which is possible
<mikdusan>
leeward: the first correction I provided was analogous to in C++, one cannot copy-by-value (dereference) a pointer to an object, and this is what `var allocator = logger.allocator` is effectively doing.
<fengb>
I expected to go and hunt down random bugs when I started stitching back std, but everything just passes! (or crashes)
<andrewrk>
fengb, yes I think we've managed to keep the number of footguns down to a low number
<andrewrk>
still not as low as I'd like yet
<mikdusan>
leeward: and actually the `var stderr = std.io.getStdErr().outStream().stream;` is doing the same thing, trying to copy an interface as opposed to just getting a pointer to it
<andrewrk>
speaking of footguns ^
<leeward>
mikdusan: Ah, ok. On the subject of footguns, is this the kind of thing the compiler could detect?
<bheads>
could the struct be marked as uncopyable
<mikdusan>
leeward: yes this is a long known issue(s) and there have been some substantial ideas floated to solve
<andrewrk>
oh, that's in generated zig code. I see the problem now
<via>
yeah, i ran into this over the weekend with the libopencm3 headers -- an internal struct for usb definitions, and i had to pass a pointer to it
<via>
worked around it by defining an external symbol of the same name to a u32
<andrewrk>
I think we can remove that compile error for extern variables. It exists because zig doesn't know how big the type is. but zig doesn't have to if it's defined externally
<andrewrk>
so zig needs to be improved to allow this
<via>
ok. i can make an issue this evening
<andrewrk>
thanks!
<via>
but it might just be seeing if its marked extern and not erroring in a spot?
<via>
as the fix
<andrewrk>
yes I think it would be that simple
<andrewrk>
would need to probably add another check though, if you tried to get the size of it
<TheLemonMan>
andrewrk, addressof of a weak var returns a ?*T instead of *T
<TheLemonMan>
maybe that's... weird? maybe @externWeak is fine and we're just overcomplicating everything?
<andrewrk>
what I like about the builtin fn call is that it's simple syntactically, it is powerful in a way that we have a precedent for (with @export comptime string as symbol name), and the return type is always ?*T
<andrewrk>
I would probably want to avoid `weak` as the keyword since it could easily clobber a userland identifier, and the idea of a var which almost always gives *T now giving ?*T when the keyword is present, is OK, but could be a little surprising. let me consider it for a minute
<andrewrk>
I do think a builtin would be easier for someone reading code to discover what it does than a keyword that changes the type that & gives. you see `externweak var foo: c_int;`, and the reader might guess wrong about the type of &foo. but with a builtin, I don't think anyone would guess wrong. they would either look it up or guess correctly
<andrewrk>
fengb, I don't see any design decisions here that disagree with zig yet
<andrewrk>
I think making an IDE early on was a smart move
doublex has quit [Ping timeout: 260 seconds]
<andrewrk>
damn, already an IDE and non-llvm fast debugging backend
<andrewrk>
this is really impressive
<fengb>
I don't like how syntactically it's close to C/C++/Java/C# :P
<fengb>
After using Swift, Go, and Zig, it feels backwards to put types on the left lol
<mq32>
fengb: i'm a fan of the C# syntax
<mq32>
it has some things, but in general it's pretty clean
ur5us has quit [Ping timeout: 260 seconds]
<andrewrk>
it's time for zig to have ide support and fast debug mode compilation. I'm tired of living in the stone ages
<companion_cube>
so, a LSP server?
<andrewrk>
fengb, let's do this. I'm going to focus on unblocking your format() stuff so we can move on to async std lib. then it's full steam ahead on self hosted
doublex has joined #zig
<hryx>
awwwww yeah!
<andrewrk>
zig's compiler server protocol will be more powerful than LSP, which will allow an LSP adapter proxy
doublex_ has joined #zig
<andrewrk>
zig's compiler server protocol will be whatever is appropriate and most efficient for zig
<companion_cube>
why not start with LSP? best bang for your buck, by far, imho. Works out of the box on all editors…
ur5us has joined #zig
<companion_cube>
(note that LSP is somewhat extensible, too)
<companion_cube>
and I think it's the simplest thing for a start; just implement the basic protocol + diagnostics, all the other features are opt-in
<BaroqueLarouche>
so Beef is basically a native C# with no exceptions
<mq32>
I have to take a closure look at Beef and how it differs from Vala
<mq32>
which is a C# clone with refcounting based on the GObject system
<companion_cube>
😱
<daurnimator>
andrewrk: what does "have IDE support" mean/imply for you?
* daurnimator
has seen people use standard debugger integrations in their IDEs with zig and it seemed to look cool
ltriant has joined #zig
<BaroqueLarouche>
daurnimator: VS code support is good, but it would be better if the debugger understand Zig complex types like array, slices and tupls
<BaroqueLarouche>
can't wait for a proper LSP integrated with the VS Code extension
<mq32>
BaroqueLarouche, there was already a zig autocompleter by someone, i used it until it broke with a zig update
<mq32>
was really great to have even basic autocompletion working
<BaroqueLarouche>
nice
<BaroqueLarouche>
but the logically way is to wait for the self-hosted compiler
<mq32>
yeah, the autocompletion needs a lot of info from the compiler
<daurnimator>
mq32: I use tabnine which works okay with zig
<mq32>
<= hates any "autotyping" that isn't following 100% forseeable rules
<daurnimator>
why?
<daurnimator>
ah okay
<daurnimator>
it often guesses what I'm about to type
<mq32>
i don't like completion that changes order
<mq32>
because it slows down my workflow
<companion_cube>
for me, auto completion is also useful to validate that I'm typing stuff that makes sense (like, identifiers in scope)
<companion_cube>
AI stuff would definitely not be good at tha
<mq32>
and something that "learns" (even for basic statistics) does that
<companion_cube>
t
<companion_cube>
heuristic stuff, I should say :-°
<mq32>
yeah
<mq32>
the most autocompleters assume that you write code top-to-bottom
<mq32>
as in "line 1 to n"
<mq32>
that's why i disable pretty much all of the "we complete the word if you press space" stuff, i want to explicitly confirm that i want that completion
<via>
i have a zig program running on an stm32f4 target successfully creating a usb cdc acm device and sending hello world strings ove rit
<TheLemonMan>
that's cool
<TheLemonMan>
"usb cdc acm" heh that gives me horrible flashbacks
<mq32>
via: nice!
<via>
the packed structs are still issues, i hacked around it, but i'm working on that. figuring out which struct wasn't being packed right is nice though
<via>
andrewrk: where is the right place to put tests to test struct packing? the stuff in stage1 doesn't apply does it?
TheLemonMan has quit [Quit: "It's now safe to turn off your computer."]
<daurnimator>
companion_cube: correct identifers etc is taken care of by my linter.
<companion_cube>
that comes far too late, imho
<companion_cube>
I want feedback as I'm writing the identifier, not when I save
<daurnimator>
companion_cube: my linter runs as I type
<companion_cube>
then what's the difference between that and completion? sounds like it could directly help you complete :p
<daurnimator>
companion_cube: note that I'm not always typing valid identifiers, e.g. I might write a function that takes an allocator, but I haven't aliased std.mem.allocator yet: tabnine still suggests it
<daurnimator>
companion_cube: FWIW I `zig fmt` on save.
<companion_cube>
I'm more thinking about other languages, but sure
<companion_cube>
I mean, the way I use completion)
<companion_cube>
java IDEs would suggest you std.mem.allocator with proper completion, and add the import :)
<companion_cube>
(import or alias)
<fengb>
I type everything perfectly the first time
<fengb>
If I don't, the compiler deletes my code
waleee-cl has quit [Quit: Connection closed for inactivity]
<fengb>
"Besides, there's no such thing as a truly infinite loop. Eventually our sun will go supernova, at which point the offending code will be removed."
<lupine>
and voyager will still be phoning home
<fengb>
Is there a need to copy lib/ into build/?
<daurnimator>
fengb: no. there's a cmake option to skip it