IRC channel logs

2023-02-12.log

back to list of logs

<daviid>old: what i was refering to, in guix, is define-c-struct ... which is here - https://git.savannah.gnu.org/cgit/guix.git/tree/guix/build/syscalls.scm#n376
<daviid>i'd like to see this in core guile ...
<civodul>agreed, it'd be nicer than make-c-struct
<daviid>civodul: perfect, let's do it then! g-golf (has to) extensively use make-c-struct parse-c-struct, i think the guix approach would be very beneficial, including performance wise ...
<old>daviid: The idea is to be able to access member without having to compute offsets. You define the struct once and that is it
<old>And ofc without any copy. You access the underlying bytevector thanks to bytevector-slice
<daviid>old: right, that is what define-c-struct does in guix, and that is what we all need in guile ...
<mwette>also needed (or maybe desired) is a procedure to convert c-struct to list of ffi types, for passing to C functions which have struct args
<old>I would need to see an example usage of define-c-struct in guix to understand what it can do
<daviid>old: see in the same file, below ... /guix/build/syscalls.scm:(define-c-struct ifaddrs ;<ifaddrs.h> ... and many more
<daviid>old: https://git.savannah.gnu.org/cgit/guix.git/tree/guix/build/syscalls.scm#n889
<old>yes I can see
<old>I don't see compose data structure though. Does it support that?
<old>Say you define <foo> then <bar> has a member <foo> in it?
<daviid>old: but SDL_Rect are not composed either - this said, in C, would that not be a field is pointer to another C struct? then define-c-struct would still work on the 'nested' C struct ... maybe guix has an example of such a nested C struct, but i can't poit to any, i don't know
<old>SDL_Rect is just a dummy example. C struct can be much more complex than 4 integers
<old>and they can compose without pointer.
<old>So yes for flat struct with native types, looks enough
<old>But if you can to build compose types, you need a type table and possibly two passes if you want to resolve types
<old>s/you can/you want
<old>The guix implementation is much cleaner than mine. I'm doing weird stuff with syntax-case D:
<old>But I like the approach of having a srfi-9 record that you can pass around. You're never aware of the underlying bytevector even when accessing sub-structure in it. You get a new srfi-9 record which has a bytevector slice of the overall bytevector
<old>And when you're ready to pass the record to C, just used the unpacking procedure you've put in the struct definition, e.g. my-struct->pointer
<old>It makes the ffi world much more declarative and less low level
<civodul>maybe the srfi-9 bit can be provided as an optional layer on top?
<civodul>the (guix build syscalls) thing is low-level so you can make tradeoffs
<civodul>maybe it's inflexible for the general case though, dunno
<old>civodul: I originaly just put a tag at the front of the bytevector for quick predicate. But thinking about it, having a bytevector move around is like having a void pointer
<daviid>old: ok, I wonder what C lib you are 'thinking' when you refer to 'we need to ... nested C struct', ime, in those situations, the C lib provide an apĂ­ to construct and access them ...
<daviid>and mnost of the time, are 'opaque', so you have to use their api to make annd access them ...
<old>It's really a trade-off I think. Some library will offer only opaque type or very flat structure
<old>daviid: Here's the public header file of my project: https://git.sr.ht/~old/libpatch/tree/master/item/include/libpatch/patch.h
<old>You have nested struct: struct patch_op { patch_addr addr; }
<old>It only the user to describe the instrumentation do be done in a declarative way : struct patch_op op = { .type = PATCH_INSTALL, .addr = { .func_sym = "foo", .insn_offset = 2 } }
<old>s/only/allows
<old>You can clearly read it has: Install a patch at the second instruction of function foo
<old>I can think also of a project that is WIP where the ABI specify the layout of types and compound types for instrumentation
<old>allowing any runtime to create their instrumentation event type without having to call any C function
<daviid>what is a patch in your context?
<daviid>old: actually, forget about my question, i see https://git.sr.ht/~old/libpatch/
<old>A patch is a divertion of the natural control flow of the program in order to execute a user defined callback, a.k.a the instrumentation
<old>Instructions at the patch location are replaced with a branch to some control flow outside of the natural program control flow graph
<old>They are then executed in a rellocation buffer before returning to the program continuation.
<old>Anyway, my point is that structure in C can take any form the author want. I think we want something that can represent any form a C struct can take
<old>For syscall I think that the Guix approach is enough since structure exposed by the kernel/glibc are flat enough
<daviid>old: maybe there is/are room for some improvment in libpatch, that would not imply such a complexity for lang binding in general, and a guile binding in particular - you might even consider make libpatch use GLib/GObject instead, then it would be(come) introspectable, and usable 'through' g-golf in a click ... just a 'random thought'
<daviid>old: just an intuition, but it seems to me you are reinventing the all C lib/lang binding 'thing' (again) ... if you (hve to) write a tiny C lib, fine, all your C struct will be 'flat', if you have to write the most complex C lib ever written by human being so far, use all this has been addressed, by a team, the last 20y,
<daviid>use GLib/GObject to make it availabvle to all lang on this planet ... my 2c
<daviid>meanwhile, i very much wish we can have the define-c-struct 'engineering'1 in guile 'proper'
<old>Unfortunatelly, I'm not familiar with GLib/GObject. I don't know what is its impact on the memory usage of a library nor its availability on linux distros
<old>I'm sticking to the strict minimum dependencies. Maybe it's possible to use GObject, but I would have to do a technical analysis of it
<daviid>old: sure, it is available on all platform, not just linux - but i was using this 'idea' also to suggest, as you are the libpatch author, to keep things simple in libpatch itself, then not only guile, but any othger C ffi equiped lang may use it ...
<old>yes true. Making an API/ABI is hard :-/
<daviid>rewriting libpatch to use GLib/GObject would be a tremendous investment ... as you'd have to learn 'the all thing' first ...
<daviid>if i had to write a C lib, but thanks god i don't have to :) - i would never use nested C struct, rather, pointers to other C struct when needed, then everybody understands, all lang can interface ...
<daviid>old: anyway, good luck, trhanks for the context of your work, i was curious
<old>daviid: Good talk :-)
<cow_2001> https://www.jwz.org/blog/2023/02/code-with-swearing-is-better-code/
<chrislck>Beginner question about continuations; if a continuation has access to an object and the latter is now out of scope,
<chrislck>Will this ensure that the object will never be gc'd as long as the continuation exists?
<lilyp>since the continuation is reachable (I guess?) and it has the object in its closure (surely), the object should survive
<chrislck>thought as such...
<chrislck>tx!
<stis>Howdy guilers!
<dadinn>hi all!
<dadinn>I am playing with SRFI-64 tests. What is the recommended way to disable all tests in the given module, unless some environment variable is set?
<dadinn>The reason I need this is because I have a "library" module, and the test get executed/printed whenever some other module/script uses it.
<dadinn>I see that there is test-skip, but that seems a bit low-level, I would like to disable all tests in he given module.
<dadinn>Also there is test-runner-current, which I assume I could use to set it to test-runner-null if the env variable is not set. The question is does that only apply to the current module or global? Also, my understanding is that test-runner-null would still execute the tests, it just wouldn't print out the results?
<dadinn>I would appreciate some examples how SRFI-64 used "in the wild", potentially with some use-cases covering my above problem...
<lilyp>dadinn (unless (getenv ...) (test-skip ...))
<dadinn>lilyp: but test-skip seems to be for disabling individual tests, I would like to disable all tests in the given module only
<dadinn>lilyp: also does test-runner-null still run the tests, and fails starting up the script if one fails, but just doesn't print the results? or does it not do anything with tests altogether?
<lilyp>the idea is to do (test-skip number-of-tests-in-your-module) or something similar
<lilyp>I don't think it'd be necessary to change the test runner
<dadinn>also there is this test-log-to-file option, if I set it to #f I am worried that affects all tests in all used modules, which is not what I would intend to do
<lilyp>tests are typically run in multiple processes and per file, so I don't think you need to worry too much about hygiene
<lilyp>that being said, the cleanest way would be to have a test but skip it
<dadinn>lilyp: actually I can see that test-skip would match even on test-group suite-name! So if I put all my tests in a module into a group, I could skip them with an (unless getenv ..) form?
<lilyp>that's the idea at least
<lilyp>anyway, gotta restart my computer
<dadinn>lilyp: for some reason it seems I am not able to use test-skip before using test-begin the first time? This measn I am not able to skip top level test group before starting it?
<old>dadinn: You can pass to tesk-skip group of tests
<old>since test-begin is a group .. you can do the same
<old>here's an example where the group x86-64 is only test if on this architecture: https://git.sr.ht/~old/libpatch/tree/master/item/tests/test-commit.scm#L109
<Zelphir>Hi! I am wondering, whether there are any projects for using the Guile REPL as ones shell. Not necessarily implementing all things equal to how sh or Bash do it, but making sure, that one has all things needed to comfortably navigate the file system and do common things like renaming files, finding files, filtering the found files, process them or their content, etc. Possibly involving new concepts in contrast to how sh or Bash or others work. Any known
<Zelphir>projects? (I know there is Gash, but I think that is a bash implementation written in Guile, not something I would load into the Guile REPL and use from there?)
<Zelphir>Maybe kind of like eshell in Emacs? But not necessarily implementing half of sh syntax? Maybe sticking to s-expressions.
<Zelphir>It would be cool to have something like that and be able to easily add another procedure/function to it, by coding Guile. I guess I could simply start implementing things, but maybe someone already created a lot.
<Zelphir>One could possibly then work with structured data instead of (as usual) work with plain text lines from files and so on.
<old>Zelphir: So for example you would have: scheme@(guile-user)> (ls) ?
<dadinn>old: in the code example you've sent I can see that there is a test-begin before the test-skip too! It seems to me that that is necessarry, else it will fail to compile, complaining that there is no test runner initialized :/
<old>dadinn: Maybe you can only use test-group? I'm not sure
<old>looking at test-group syntax, it's a dynamic wind around test-begin/test-end
<dadinn>old: I think it's because the first test-begin expression will initialize the test-runner, and you cannot use a stand-alone test-skip call before the runner is initialised?
<dadinn>old: the test-group macro wouldn't solve that problem i think, because if you do the test-skip statement inside the group, you can't skip the group itself. If you do the skip statement outside the test-group block, then it would have the same problem with the unitialized runner.
<lilyp>Zelphir: there is gash and scsh
<old>hmm I see
<old>How about this. You have a test-driver right? A shell script that run your test file
<old>what if that test-driver skip the entire file and print SKIPPING: FILE
<lilyp>gash is somewhat minimal, so you don't get much nice things, but you can drop into scheme or elisp from it with ,L
<old>dadinn: Look at this example of `run-tests' in my Makefile: https://git.sr.ht/~old/libpatch/tree/master/item/tools/run-tests
<old>You could very easily filter the list of tests with srfi-1 and looking at a environment variable
<old>And the test-driver, a classic I found: https://git.sr.ht/~old/libpatch/tree/master/item/tools/test-driver
<old>TLDR: If you can't skip from the file itself, skip from the test driver :-)
<Zelphir>lilyp: Hm, I will need to check Gash out again and scsh. Thanks for the pointers. I haven't yet gotten around to answering your e-mail, sorry about that!
<lilyp>I write so many emails, I forget which one people talk about, so don't worry.
<Zelphir>:D I receive way more than write, but I have some tag "awaiting-response" and I mark them with tags. But sometimes those accumulate as well ...
<graywolf>Hello, this is probably stupid question, but is it possible to switch the libc used by guix? And have based on musl instead of glibc? Or would that be too much work if possible at all?
<lilyp>It'd at least be a somewhat nasty porting effort
<old>graywolf: This is probably best answered in #guix :-) But in my honest opinion, 99% of the software on Linux rely on glibc specific features
<old>So the answer is a flat nope
<Zelphir>old: > So for example you would have: scheme@(guile-user)> (ls) ? ---- Yes something like that. And to make up for having to type a little more for simple things like `ls`, make some more difficult things easier to achieve than in sh/Bash.
<old>Zelphir: It could very "easily" be done. I think that augmenting the REPL reader so that you can do: scheme@(guile-user)> ls -l instead of (ls "-l") would be the first thing
<old>So the reader would do something like: FN ARGS ... -> (apply FN (quote (ARGS ...)))
<old>Then it's a matter of adding useful builtin commands like `cd', `dir', `echo' etc
<Zelphir>I don't really mind having to type "a few" parens, since they will also help me copying and cutting stuff and moving it around. For example lets say I have `->` bound to a pipeline macro, I don't mind having to write (-> step1 step2 step3) instead of `step1 | step2 | step3`.
<old>And a guile-coreutils for all the other commands like `ls'
<old>would be simple to just have a macro `(define-command ls "ls -l")' then in the repl: > ls -> (ls) -> (system* "ls" "-l")
<old>Right. I guess it's a matter of style
<old>But having to type (ls) everytime is kind of cumbersome
<Zelphir>OK that would be nice to have perhaps at some point, but I don't want to focus on that. I would rather want to focus on making harder things easier. Sometimes shell stuff does not compose as easily as functions in a Scheme.
<old>Agree. Shell is just a hack that work
<old>but it's dirty
<Zelphir>Perhaps one could even make the "more shell like syntax" or "non-s-expr syntax" macros an optional module, which one could load, if one wanted to, and otherwise accept the s-expr syntax like `(ls)`.
<old>yes!
<old>You put something like this in your ".guile-shell" config file: (and=> (false-if-exception (resolve-interface '(shell))) (lambda (module) ((module-ref module 'enable-shell-reader))))
<old>And you put wathever you want in there, like `(define-command foo "foo") (define-command-alias f foo)'
<old>Idk, making things up.
<old>What's more difficult for a shell though is the control of foreground/background jobs
<Zelphir>I imagine redirection of stdout and stderr to also be a bit of a hassle.
<old>Right. There's a couple of things to consider
<old>Nothing impossible with Guile
<graywolf>old: 1. Thanks for answer 2. Yeah, lately I visited #guile so muscle memory went there despite brain wanting #guix :)
<old>For which reason you would like muscl btw?
<old>I've quickly tried to port libpatch to muscl. I quickly abandon the thing when I realized that it does not even support _SC_LEVEL1_DCACHE_LINESIZE
<graywolf>old: In general I like the musl's philosophy and design goals more. Robustness, focus on being small and secure. Also I need to check if C.UTF-8 is supported by glibc now, because sorting rules under en_US.UTF-8 are... interesting. And I also like to use libc I can actually read and (mostly understand). This is a personal preference, but the GNU's C coding style is... not my favorite one.
<old>ah so you're hacking into the libc itself?
<old>The problem with Muscl (for me) is that is strictly implement the libc specification
<old>However, things are much more complex in reallity than what the libc specification says.
<graywolf>Not very often, but sometimes I find helpful to look at implementation if I'm unclear about something just based on the manual or specification.
<old>One example I have in mind is the usage of restartable sequence (rseq(2)) on Linux
<graywolf>Well it also includes most of POSIX, at least the mandatory parts afaik.
<old>Since latest version of glibc (2.37 I think), glibc is the owner of the rseq region shared with the kernel.
<old>Muscl does not care about that. But rseq is actually a component of the operating system and there's lot of performance gain in it
<graywolf>Which I find just weird (glibc ownership of rseq), since there technically is no "official" libc under linux.
<old>The reason why is that rseq region must be register with the kernel for every thread
<old>Since it's libc that control pthread you get the idea ..
<old>so glibc will register an rseq region everytime a thread is created through its runtime, a.k.a pthread
<old>Muscl will probably never do so because it want to be a portable implementation of libc which is fine
<graywolf>Yeah I guess. I think alpine demostrates that in practice musl is often enough, since the system produces is more then useable (writing from alpine laptop).
<old>And at some point, the implementation become the standard
<old>There's so much things that people use in glibc which are not portable at all that the "libc" on Linux is glibc
<graywolf>As for the rseq, dunno what the plans are there. But portability is not musl's goal afaict, the implementation is Linux specific, just the exponsed interface is standard. So not sure what will happen on the front.
<old>oh I see
<old>then it could probably implement it as well
<old>What really frustrate me though is that there's no macro to determine if using muscl
<old>I can't do something like #ifdef __muscl__
<graywolf>Yeah, I know from mailing list people complain about this a lot :) The idea is to feature test the feature, not the libc. But I get that sometimes it would be a handy shortcut compared to writing a configure test.
<old>but I can #ifdef __GLIBC__
<old>I guess I can look for libmuscl.so at configuration time and generate my own definition
<old>Anyway, I would be more incline to support muscl if there was at least that macro :p
<graywolf>Well but even for glibc you should probably also have some version range, since you have no idea if new version will implement the guarded feature or not. But in practice people take shortcuts (e.g. desired #ifdef __muslc__), so upstream does not want to add it. Since no one ever updates these checks when the libc does get the feature one day :/
<graywolf>(Also, sorry for this massive off topic, not sure what the policy is in this channel regardin that.)
<old>Right. There's no perfect solution
<old>True we're way off topic here ^^
<lilyp>Isn't this why featue check macros exist tho?
<akirakyle>.
<sneek>Welcome back akirakyle, you have 1 message!
<sneek>akirakyle, daviid says: i just pushed a few patches, to the devel branch, that implement a 'skip array length' mechanism - all examples updated, as the g-application-run method (specializers) is affected by this patch - any example/g-golf code you wrote will have to be updated accordingly ... (see the log for some example, and also update your calls to gsk-container-node-new ...)
<akirakyle>daviid: Awesome, I've updated and everything that I had running before still runs after updating the appropriate calls
<akirakyle>daviid: Also now that my semester has started, I'm probably not gonna be working on these g-golf projects nearly as much as I was over break, but so far I've not been blocked by any g-golf bugs
<akirakyle>There is one heisenbug g-golf crash that I'll sometimes run into with "large" gsk scene graphs, but it only happens occasionally and seems to be affected by whether guile compiles or not, so it seems plausible I'm doing something wrong somewhere and I haven't gotten around to trying to isolate a minimal reproducer script
<akirakyle>Anyways, once you decide to cut a release, I'll send in my patch for packaging it on guix and can do a little write up of how to get started with g-golf development on guix
<dadinn>For some reason I syntax-locally-bound-identifiers... I am using Guile version 3.0.5 :/
<dadinn>* I don't have syntax-locally-bound-identifiers
<dadinn>I do have generate-temporaries though, as documented here: https://www.gnu.org/software/guile/docs/docs-2.2/guile-ref/Syntax-Transformer-Helpers.html
<mwette>In call-with-values producers, is `exp' equivalent to `(values exp)' ?
<cow_2001>exercise 1.21. my math is poo, so it'll be hard.