What if I started afresh, and wrote the Fennel bindings this time, too? No store yet, just KDL config + Fennel extensions, and just enough code to arrive at a single, toplevel derivation.
Feels like I need to do a bit more sketching first. Lets put the distro thing on hold for a bit.
This will be hard, because I have a reasonably good idea of where I want to end up, and I'm itching to start building the distro itself. But I need the package manager first.
input pkgin type=pkgin {
path "/sexshop/toys/<hash>-pkgin"
hash algo=blake3 "..."
}
input sickos type=sickos {
path "/sexshop/toys/<hash>-sickos"
}
netbsd "carota-sativa" {
sets {
base
comp
kern-GENERIC
etc
man
rescue
}
network {
vioif0 { dhcp; }
}
packages from=pkgin {
git
rust
curl
dinit
vim
}
service from=sickos ssh {
enable
}
}
Something along these lines, maybe.
Or rather...
input pkgin {
source {
pkgin
}
current {
path "/sexshop/toys/<hash>-pkgin"
hash algo=blake3 "..."
}
}
input sickos {
source {
sickos {
url "https://git.madhouse-project.org/fuck/sickos"
}
current {
path "/sexshop/toys/<hash>-sickos"
hash algo=blake3 "..."
}
That source { pkgin; } would make sure that the derivation built is something that the rest of the packaging can work with.
The source extensions would transform the KDL into something like this:
input pkgin {
source {
fetcher pkgin
build-system pkgin
}
}
And the pkgin fetcher and pkgin build-system would be implemented in Fennel.
Another question is: how does fuck find the fennel stuff? There'd be the built-in stuff, yes, and inputs would have an extensions/ directory to load extensions from, but... how do I bootstrap that?
Tbh, inputs need a bit of thinking in general.
But I'm getting ahead of myself, again.
First things first: lets make it possible to declare a derivation.
Ooooh! EPIPHANY!
So one of the problems I was struggling with is how extensions would register themselves as handlers for various KDL nodes. You see, just registering their intent to handle "source" nodes is insufficient, because there are hierarchies!
So... what if there were two ways? One to register top-level node handlers, and another to register a transformer for a name, and the Fennel side could invoke those?
So this bit:
package hello {
source {
tree { ... }
}
build-system declarative
}
This would invoke the package.source handlers, and the package.build-system handlers. Both of those should return one of Response::Untouched, Response::Kdl, or Response::Derivation (or an error).
They'd receive as parameters the derivation that's being constructed, the parent node, and the node, and the communication channels.
If a handler returns Response::Untouched, the same thing gets passed to the next handler. If it returns Response::Kdl, then we replace the original node with the new one, and start processing it again. If no handler does anything with a node, and the final result remains Response::Untouched, we report an error.
Yes, I realize I am making my own life harder by insisting that the extension mechanism is pluggable.
Maybe I shouldn't, but... then I might have to rewrite large parts again.
So, first order of business: figure out a protocol to talk over the extension<->fuck channel, because the idea is that
fuckwill ask each exetnsion about what kind of stuff it supports, and then set up appropriate channels for each.Now, the ideal thing would be if the negotiation would be automatic. I can't enforce that at compile time, because it depends on the extension, and that's a runtime thing. But I can teach the Rust side bridge to figure out which functions are exported from Fennel, and do the negotiation itself, so it doesn't need to be implemented - or even exposed - to the Fennel side.