ChanServ changed the topic of #zig to: zig programming language | https://ziglang.org | be excellent to each other | channel logs: https://irclog.whitequark.org/zig/
ltriant has quit [Ping timeout: 246 seconds]
iamthad has quit [Quit: ZNC - https://znc.in]
torque has quit [Ping timeout: 252 seconds]
iamthad has joined #zig
torque has joined #zig
ltriant has joined #zig
ltriant has quit [Ping timeout: 248 seconds]
ltriant has joined #zig
ltriant has quit [Ping timeout: 272 seconds]
ltriant has joined #zig
fgenesis has joined #zig
Ichorio has quit [Ping timeout: 264 seconds]
marijnfs has joined #zig
marijnfs__ has quit [Ping timeout: 268 seconds]
ltriant has quit [Ping timeout: 248 seconds]
<daurnimator> andrewrk: thanks for the async examples
_whitelogger has joined #zig
<andrewrk> daurnimator, progress is going well. I have the behavior tests passing the whole time in the rewrite-coroutines branch
* andrewrk back in a bit
<daurnimator> andrewrk: huzzah
<daurnimator> andrewrk: I've had a few questions here in the channel over last few days. Could you answer a few of them?
ltriant has joined #zig
ltriant has quit [Ping timeout: 245 seconds]
kristoff_it has joined #zig
kristoff_it has quit [Ping timeout: 268 seconds]
ltriant has joined #zig
andrewrk has quit [Ping timeout: 248 seconds]
andrewrk has joined #zig
dimenus has quit [Ping timeout: 245 seconds]
laaron has joined #zig
dewf has joined #zig
laaron has quit [Remote host closed the connection]
laaron has joined #zig
dewf has quit [Quit: Leaving]
<andrewrk> daurnimator, can you repeat the questions or post them to the mailing list?
<daurnimator> andrewrk: sure. will reask one at a time now
<daurnimator> andrewrk: 1. `pub fn @"bool"() bool {` fails due to shadowing. is it intentional you can never have a method named the same as a builtin type?
<andrewrk> yes it's intentional - otherwise `bool` in the scope would be ambiguous
<andrewrk> I guess that's a way that keywords are actually more convenient than builtin types
<daurnimator> andrewrk: I feel like I should be able to do it, but maybe only access via explicit `@This().bool`
<andrewrk> I believe there is a relevant issue open for this
<daurnimator> oh?
<daurnimator> 2. something like `fn foo(anything: var) { std.debug.warn("{}", @typeName(@typeOf(anything)));` fails with `error: parameter of type 'type' requires comptime` when I try and pass a type in --> but I don't want to make the parameter comptime. Is there something planned that might help here?
<andrewrk> interesting. I think we can relax that
<andrewrk> proposal welcome for that
<daurnimator> okay, will create one.
<daurnimator> (scroll down to bottom file first)
<daurnimator> Created #2940 for question 2. above.
<daurnimator> Also in 3. note that the bug report URL in clang is missing :P
<andrewrk> daurnimator, you crashed clang, so the next steps are to repro in the llvm9 branch and then if it's still crashing, make an upstream bug report
darithorn has quit [Quit: Leaving]
<daurnimator> How should I obtain/test with llvm 9?
<andrewrk> and then use the llvm9 branch of zig
<daurnimator> 4. Is allowing `@field` as an lvalue intentional? I was surprised that it worked... but happy :) Maybe it deserves a mention in the docs?
<andrewrk> oh and you want -DZIG_FORCE_EXTERNAL_LLD for the llvm9 branch (for now)
<andrewrk> yes it is intentional
<andrewrk> I think the docs have it correct: "Preforms[sic] field access equivalent to lhs.field_name, except instead of the field "field_name", it accesses the field named by the string value of field_name. "
<andrewrk> lhs.field_name works as an lvalue
<andrewrk> an example would be an improvement
<daurnimator> I read "access" to imply *reading* rather than allowing writing
<andrewrk> I see
<andrewrk> "access" does mean both though
<andrewrk> regardless, adding an example will be an improvement
<daurnimator> k. created an issue to track
<andrewrk> thx
<andrewrk> I think we're going to realize our async/await dream
<andrewrk> it's gonna work
<daurnimator> andrewrk: great :)
<andrewrk> zig functions work at compile time, at runtime, blocking, event-based, single-threaded, multithreaded
<daurnimator> I'm eager to start on networking abstractions once its done.
<andrewrk> it's a language for writing actually reusable code
<daurnimator> andrewrk: to clarify your async examples: `async foo()` that returns a Frame right? it doesn't actually begin executing the function?
<andrewrk> it does both
<andrewrk> if it didn't actually begin executing the function it would be a generator
<andrewrk> async foo() means "do this now. but I don't need the result yet."
<andrewrk> and it's valid for all functions, even normal blocking ones
<daurnimator> andrewrk: idea. what if `async foo` was the frame. and calling a frame `()` resumed it?
<andrewrk> start with the use case. what are you trying to solve?
<daurnimator> often when writing "async" code you don't want to actually start the operation "now": you just want it to be "done" by the time wait() returns.
<andrewrk> well how's it going to get done if it doesn't start?
<daurnimator> --> immediately starting the function means that you end up doing a context switch and thrash your cpu cache
<andrewrk> what do you mean context switch?
<daurnimator> andrewrk: in this example: a call to a non-trival function
<andrewrk> you can start it whenever you want
<daurnimator> andrewrk: is "starting" different to "resuming" at all?
<andrewrk> the only difference is setting resume_index to 0
<daurnimator> hrm. I might need to understand more
<andrewrk> were you able to grok the LLVM IR?
<daurnimator> I didn't really look at it too hard. I mainly looked at the zig code
<andrewrk> it's pretty readable in this branch, unlike master
<andrewrk> I can explain any of those instructions
<daurnimator> andrewrk: in that gist, you have an explicit `async`: how does that tie in with 1778?
<andrewrk> related to those questions are a couple screen shots: https://twitter.com/andy_kelley/status/1153808423068135425
<andrewrk> in this simple example `entry` is the c calling convention entry point into the object. so it can't be async. that's the function where you would, for example, create an event loop
<andrewrk> the `async` in the entry function makes it able to call an async function, because it does not represent a suspend point
<daurnimator> andrewrk: is there any plan for an @isAsync() builtin?
<andrewrk> async is used to express concurrency
<andrewrk> that's a similar question to @isComptime()
<andrewrk> it would be strongly discouraged, if it existed
<andrewrk> "is it async?" and "is it comptime?" are the wrong questions to be asking
<daurnimator> okay. I see in your #1778 post you used `if (std.event.loop.instance) |event_loop| {` -> so it would be based on a global rather than inferred from context. makes sense I think.
<andrewrk> right. the whole idea here is that packages are agnostic, and the main application gets to make a choice
<andrewrk> which is why async is allowed on any function, and is used to express concurrency
<andrewrk> but it can always be folded into single-threaded blocking
<andrewrk> look at that beautiful list of "Depends on:" issues in 1778 that are all done now
<gonz_> Timewise, how far off are we from having the new async stuff in master?
<daurnimator> andrewrk: turn it into a checklist ;)
<andrewrk> gonz_, hard to predict but I'll be happy if it's in master branch by sept 1
<daurnimator> o.o that far away?
<gonz_> I wouldn't have worded it precisely like that, but I feel the same. Mostly because I feel like zig will basically be exactly for what I do all day every day suddenly.
<andrewrk> we'll see. progress has been rapid so far, maybe it will magically continue like that
<gonz_> Do it at the pace you can or slightly less, IMO
<gonz_> Don't burn out :/
<andrewrk> I know how to take care of myself :)
<andrewrk> this weekend I'm actually traveling for an arcade game tournament
<daurnimator> andrewrk: `async<std.heap.direct_allocator>` <-- does this make the allocator interface part of the language?
<andrewrk> daurnimator, you're looking at the master branch example which is provided for comparison
<daurnimator> ah okay
<andrewrk> one of the benefits of the coroutine rewrite is that the allocator interface stops being part of the language
<daurnimator> right. I see the `async<result2>` example instead.
<andrewrk> yeah and even that's not going in the first design iteration
<andrewrk> there will be no more <> to async for now
<daurnimator> andrewrk: going back to my earlier idea: what if calling a frame "resumed" it?
ltriant has quit [Remote host closed the connection]
<andrewrk> what problem are you solving?
ltriant has joined #zig
<daurnimator> so rather than `async<result2>`, it was just: `result2()`
<daurnimator> minimisation of concepts while providing powerful foundations.
ltriant has quit [Quit: leaving]
<gonz_> daurnimator: What was the thing you were looking to use as a base for the future networking stuff?
<daurnimator> gonz_: on which target?
<gonz_> Windows
<daurnimator> gonz_: on windows it'll be overlapped IO for most things, and talk directly to AFD for TCP/UDP things.
<gonz_> AFD, right
<daurnimator> andrewrk: thanks for the answers :) go get yourself some sleep!
<daurnimator> gonz_: If you're interested in implementing any of it please do! I don't use windows myself so I'm not going to get to it any time soon
<daurnimator> companion_cube: in reply to something you said ages ago... but zig pieces in the kernel isn't as far fetched as you may think
<gonz_> daurnimator: I'll at least look into some of it. I do use Windows but it's been ages since I did any socket stuff for Windows.
<daurnimator> gonz_: I'd start by just porting this example to zig: https://gist.github.com/daurnimator/63d2970aedc952f0beb3
<gonz_> Thanks, this will be good to have.
<daurnimator> gonz_: you should be able to make a zig PR of various windows pieces required to implement that
<gonz_> I'm currently working on a few win32 things so it's a good companion project, probably
* daurnimator looks at the zig issues page and realises that he filed more than half of them
<daurnimator> hryx: do you think you'll implement #1717 ?
<companion_cube> daurnimator: well it all depends on whether Linus would spit on zig, wouldn't it?
<daurnimator> companion_cube: I got kees and willy intrigued.... If we had a stability guarantee and non-reliant on LLVM I think I could get things over the line given the right project
<companion_cube> yeah, the llvm dep is probably the biggest thing. Anyway that'd be nice
<daurnimator> companion_cube: I was messing around with https://gist.github.com/daurnimator/6518ece625b9c5f143ac51274b9dacfe the other month
<daurnimator> a couple of the issues found during that experiment have been fixed now; so I should give things another go...
<daurnimator> If anyone is going to LPC in september it would be a great topic to bring up.....
kristoff_it has joined #zig
samtebbs has joined #zig
sammich has quit [Read error: Connection reset by peer]
sammich has joined #zig
mattisme has quit [Write error: Connection reset by peer]
fengb has quit [Ping timeout: 240 seconds]
ffddr has quit [Ping timeout: 240 seconds]
geemili has quit [Ping timeout: 276 seconds]
mattmurr has quit [Ping timeout: 264 seconds]
emekankurumeh[m] has quit [Ping timeout: 264 seconds]
BitPuffin has quit [Ping timeout: 276 seconds]
SimonNa has quit [Ping timeout: 248 seconds]
SimonNa has joined #zig
SimonNa has quit [Read error: Connection timed out]
SimonNa has joined #zig
SimonNa has quit [Client Quit]
eagle2com has joined #zig
BitPuffin has joined #zig
wootehfoot has joined #zig
mattisme has joined #zig
fengb has joined #zig
dimenus has joined #zig
dimenus has quit [Ping timeout: 245 seconds]
ffddr has joined #zig
wootehfoot has quit [Read error: Connection reset by peer]
<fengb> Oh wow function expressions!
<mq32> fengb: ?
<companion_cube> nice
<companion_cube> in the `sort` example it feels like the function should be comptime
<mq32> fengb: ah i thought there would be something new on the thread. i'm kinda stalking it since i've commented
<fengb> Yeah I just noticed it was accepted. Got too excited >_>
<fengb> And... I guess I'll punt on my emulator's CPU until that blah
<fengb> Oh I never thought about comptime function dispatch
<fengb> willamcol3's proposal is giving me flashbacks of Ruby :P
<companion_cube> it's like rust's distinction between `fn foo<F:Fn(A)->B>(f: F) …` and `fn foo(f: &dyn Fn(A)->B) …`
<companion_cube> first is specialized, second is dynamic dispatch
<companion_cube> (which allows closures, not just functions)
<companion_cube> but passing comptime functions would allow closures too, I think
<fengb> Yeah, I think it makes sense if comptime could be enabled by default since a lot of usecases are comptime known
<fengb> Although having the compiler automatically deciding could be confusing
<companion_cube> yeah…
<fengb> Also curious how that'd work. Wouldn't each comptime callback require its own instance of the function?
<companion_cube> every call to `sort` with a distinct function would be specialized, yes
<companion_cube> (same as each combination of types for containers)
<fengb> I suppose that's no different from std.debug.warn technically translating to a bunch of different functions underneath the covers
<companion_cube> reminds me of a talk of Stroustrup about performance where he talks about qsort being slower than C++ because of that
<companion_cube> (much harder to inline in the C version)
curtisf has joined #zig
<fengb> companion_cube: sticking "comptime" onto the callback argument already does this
<fengb> Also took me way too long to write a sort function
curtisf has quit [Ping timeout: 260 seconds]
<daurnimator> samtebbs: re: 'extern' that actually relates to a different issue I encountered in the linux kernel module experiement
<daurnimator> `export const _1 linksection(".modinfo") = MODULE_LICENSE("MIT");` <-- there was no way to add something to a link section without giving it a name.
<daurnimator> samtebbs: oh wait. I confused extern vs export
<samtebbs> daurnimator: I think I did as well, bit perhaps the point still stands... :p
<samtebbs> but*
<daurnimator> `extern` is a calling convention. `export` is a shortcut for `@export(, .GlobalLinkage)`
<daurnimator> uh `.Strong`
<samtebbs> Is extern also not a hint to the compiler that this symbol isn't defined in the analysed source, but in another object file that will be linked in
<samtebbs> So therefore a name is required as otherwise you wouldn't know what symbol to get from that other object file at link time
eagle2com has quit [Ping timeout: 248 seconds]
SquantMuts has quit [Quit: leaving]
<daurnimator> oh I forgot about that meaning
<daurnimator> wow `extern` is really overloaded in meanings isn't it
<samtebbs> Yeah :D
<mq32> fengb: that comptime function parameter is quite awesome
<fengb> comptime is just one of those things that works so well, I question my sanity
<mq32> yeah, that's true
<daurnimator> I still want someone to write a PEG library that works at comptime too
<mq32> you mean a parser generator?
laaron has quit [Remote host closed the connection]
<daurnimator> yess
rappet has quit [Quit: -]
<mq32> hah, would be neat
<mq32> reminds me of the CTRE library for C++
<mq32> that would create compile time regular expressions
<mq32> which means the compiler would *compile* the actual pattern matcher instead of creating a VM for it
<fengb> Well... templates are turing complete so
<mq32> yeah
<mq32> but something like
<mq32> if(CTRE("$x").match(str)) { } would compile to an "if(str[0] == 'x') { }"
halosghost has joined #zig
<fengb> The video where Andrew discussed C++ compile time stuff made me feel sick
<mq32> yeah, it kinda sucks on *all* levels
<daurnimator> mq32: sort of... I was just thinking that you could essentially step the VM along as far as you can until you hit a runtime input
<fengb> I mean... that syntax looks decent lol
<daurnimator> fengb: for syntax I was thinking of copying lpeg.... as much as you can without operator overloading: for the base layer you get a sort of ugly: `PEG.FollowedBy(PEG.P("foo"), PEG.P("bar"))`... but because it works at comptime, you can implement pseudo-regexes on top
<daurnimator> fengb: http://www.inf.puc-rio.br/~roberto/lpeg/re.html <-- implementation of a PEG that generates a PEG.... who's input looks like a regular expression
<fengb> You seem to want to port over all of Lua :P
<daurnimator> fengb: just the good bits
<mq32> do you know the RPAtk C library?
<samtebbs> Is a PEG similar to a parser combinator?
<daurnimator> on the topic of PEGs, guido wrote a blog post today about potentially changing python's lexer+parser to a PEG... https://medium.com/@gvanrossum_83706/peg-parsers-7ed72462f97c
dec05eba has joined #zig
<fgenesis> oh, medium.com gives a 500 right now
<halosghost> feature, not a bug
<dec05eba> I tried using a peg parser before for writing a programming language, but i switched to a regular recursive descent parser as it was easier to read (as code flow)
<halosghost> PEGs are really pleasant
<daurnimator> halosghost: compared to the alternatives... usually yes.
<dec05eba> i also dislike generated code in general. It makes it harder to debug
dec05eba has quit [Remote host closed the connection]
rappet has joined #zig
<fengb> dec05eba: I agree in general, but comptime isn't the same as traditionally generated code
<gonz_> Has anyone used rouge (ruby library: https://github.com/rouge-ruby/rouge) ? I just found out that dev.to uses it for all their syntax highlighting and I want to start a #zig tag there, but I'm not so hot on delving into this Ruby library.
Akuli has joined #zig
<gonz_> Though some of their existing lexers aren't as crazy as I would've thought
darithorn has joined #zig
dimenus has joined #zig
tane has joined #zig
<tane> howdy
knebulae has quit [Read error: Connection reset by peer]
SquantMuts has joined #zig
<dimenus> 00007FF77F5AE71D movaps xmm0,xmmword ptr [rsp+8Ch]
<dimenus> :(
vexu has joined #zig
<dimenus> is there a way to specify the alignment of an array?
<dimenus> assigning to vectors is segfaulting because the memory address is not 16 byte aligned
<mikdusan> yup i have patch
<mikdusan> just testing
avoidr has joined #zig
<dimenus> mikdusan: were you working on this already?
<mikdusan> no i saw your issue and it's the inverse direction of a previous fix i did (vector -> array copy) so i figured it was straight fwd
<dimenus> very cool, thank you sir
<scientes> also bool vectors are 1 bit width and bool arrays are 1 byte width
<scientes> and they don't convert right
<dimenus> mikdusan: that PR fixed my issue
<mikdusan> 👍
vexu has quit [Quit: WeeChat 2.5]
emekankurumeh[m] has joined #zig
knebulae has joined #zig
ky0ko has joined #zig
<mikdusan> scientes: is this correct? `@sizeOf(@Vector(4,u1))` == 4
<scientes> i
<scientes> i'm not sure
<scientes> comptime works
<scientes> it just fails on run-time
<scientes> and i wasn't even using @sizeOf
<scientes> i just noticed that mem.eql() doesn't work
<mq32> scientes, sounds like padding is applied and only the lowest bit is used
<scientes> the vector puts all the bits right next to each other
<scientes> so the conversion is wrong
<scientes> vector->array
<mikdusan> if vector packs bits, i would think first step is to fix @sizeOf
<dimenus> why even have a vector of bools? seems like it causes more confusion
<dimenus> since they don't align with what bools are in non-vectors
<fengb> There's no packed array atm
<scientes> dimenus, comparisons return vectors of bools
<dimenus> ah
<scientes> comparisons of vectors
<fengb> https://github.com/ziglang/zig/pull/2422 we added this in userland but not at a language level
<scientes> actually the conversion needs to use extractelement
<scientes> cause its definitely packed on x86, which has special mask registers
<scientes> but its just sext 8 16 32 or 64 on ppc for example
<scientes> anyways, i will have to look at that code
Tetralux_ is now known as Tetralux
<Tetralux> Q: Is there a way to refer to an extern fn by a different name than the one you're linking with?
<Tetralux> (.. Without using a `const otherName = foreign_fn_name;`
<dimenus> why without?
<Tetralux> You might have an entire API with very generic names that you don't want polluting your file's namespace.
<Tetralux> I'm guessing you cannot do this.
<Tetralux> For instance, WINAPI's `socket` fn.
<fengb> They need to resolve at link time so there's not much you can do to work around it
<fengb> I suppose you can toss the references into a different file and manually wire in that way
Akuli has quit [Quit: Leaving]
halosghost has quit [Quit: WeeChat 2.5]
<Tetralux> Essentially, I want to be able to tell Zig to link with a name that isn't what I'm calling the fn.
<Tetralux> Like `extern "libsomething" .linkname(my_extern_fn) fn MyExternFn(...);`
<Tetralux> I could then call it with `my_extern_fn(...)`
<Tetralux> Or no
<Tetralux> Other way around
<Tetralux> I could then call it as `MyExternFn(...)`
<Tetralux> But it would be linked as `my_extern_fn`.
<Tetralux> And my_extern_fn would not be an identifier in the file scope.
<andrewrk> Tetralux, extern function prototypes might move to builtin function calls with #1717
<andrewrk> something like: const foo = @extern("libname", "linkname", fn_prototype);
<mikdusan> Tetralux: is the desire to have a completely diff name, or simply to put it in a namespace to avoid pollution?
<Tetralux> Both for the same reason: I want it to be clear that I'm calling into a DLL and not the code in the file's scope.
<Tetralux> And if the DLL has very generic names, I have to rename it or namespace it.
<Tetralux> I'm guessing the latter would be idiomatically done by putting `struct { ... }` around it?
<mikdusan> maybe i misunderstand but how about `const Box = struct { extern "c" fn printf() void; };` and then `Box.printf();` is namespaced.
<Tetralux> That's one valid choice, sure.
<fengb> andrewrk: that looks really slick
<Tetralux> Also, andrewrk, regarding `@extern` - having to provide the link name if you don't want it to be different seems unfortunate.
<Tetralux> Otherwise, LGTM.
<Tetralux> I'm guessing the CC would be part of the prototype?
<andrewrk> I'm expecting nearly every extern function to be renamed due to namespacing
<Tetralux> If you do the struct namespacing thing, then you'd have no need to though.
<Tetralux> In which case I'd be cutnpasting.
wilsonk_ has quit [Ping timeout: 245 seconds]
<Tetralux> Q: Should you be able to do `return switch (self) .V1 => .V2` where self is and enum and the return type is an enum?
<Tetralux> (.. assume curly brackets around `.V1 => .V2`.)
wilsonk_ has joined #zig
<bwb_> andrewrk: zig progaganda on my heavy rustlang twitter
<bwb_> smh
kristoff_it has quit [Ping timeout: 248 seconds]
<Tetralux> `zig run test.zig -target x86_64-windows` breaks Zig.
<Tetralux> It breaks while attempting to print a stack trace.
<dimenus> on master?
<Tetralux> Yeah
<hryx> daurnimator: I personally enjoy working on things that affect the syntax, so I would enjoy working on #1717. I'm not dead set on being the one to do it though, and would probably need to step up my understanding of the IR transformations
<hryx> cool to see all this discussion about what to do about extern in relation to fn expressions
<hryx> bummed that I've been too busy to work on zig this week. Lookin' forward to a little weekend hacking
<Tetralux> dimenus: zig0 doesn't segfault, but instead just prints out that posix spawn failed.
<Tetralux> But zig is generated my `make install`, so that's what I'm using.
<Tetralux> I would imagine that attempting to `zig run` an executable that's non-native isn't supposed to work is it. xD
<Tetralux> That does raise an interesting question:
<Tetralux> Is it possible to _debug_ a program on a non-native system?
<Tetralux> e.g: use `-target x86_64-windows`; able to run `gdb program.exe -ex run` on a linux x86_64 machine.
<Tetralux> Or something along those lines, rather.
<Tetralux> This is the crash btw: zig/src-self-hosted/stage1.zig:37:5: 0x7cc679 in stage2_panic (userland)
<Tetralux> @panic(ptr[0..len]);
Ichorio has joined #zig
tane has quit [Quit: Leaving]
<scientes> Tetralux, you can run it with wine
<scientes> inc. winedbg --gdb
<scientes> that is the only way to use valgrind with windows applications
<Tetralux> RIGHT
<Tetralux> Never tried to debug an app with Wine before.
<Tetralux> Huh..
<Tetralux> Interesting.
<fgenesis> 23:17 < scientes> that is the only way to use valgrind with windows applications
<fgenesis> so how would you call this then?
<fgenesis> winedbg --valgrind ./thing.exe ?
<scientes> i don't know look at the valgrind documentation
<scientes> i think you just do valgrind wine foo.exe
<fgenesis> ohman this is great
<scientes> or you can remove the "wine" if you have binfmt set up
<scientes> becauase the kernel recognizes the exe and calls the wine interpreter
dimenus has quit [Ping timeout: 268 seconds]
tgschultz has quit [Ping timeout: 264 seconds]
tgschultz has joined #zig
MajorLag has joined #zig
tgschultz has quit [Ping timeout: 245 seconds]
MajorLag has quit [Ping timeout: 272 seconds]
darithorn has quit [Quit: Leaving]
kristoff_it has joined #zig
<scientes> umm trying to get a lock on stderr means that zig sometimes just hangs
kristoff_it has quit [Ping timeout: 245 seconds]
<scientes> oh its not, srrry i confused fd 3 and 2
Ichorio_ has joined #zig
ntgg has joined #zig
Ichorio has quit [Ping timeout: 264 seconds]
Ichorio_ has quit [Ping timeout: 264 seconds]