Firefly is a language with object capabilities for...
# devlog-together
j
Firefly is a language with object capabilities for regaining control over I/O and with implicit async/await. Currently working on the build system.
đź‘€ 1
In the
build-system
branch, the CLI has become incredibly simple. The only thing it can do is to run a main file:
firefly Main.ff
That main file may be a build script written in Firefly as below though. The next step is to get this working:
Copy code
main(system: BuildSystem) {
    system.compile("Main.ff")
    system.bundle()
    system.executable()
}
To create a statically linked executable.
🤔 1
w
You're going to have to tell us more because at one level one can read this as, "good old fashioned structured programming that blocks on IO and uses 'files' as capabilities."
j
Gladly - here's an excerpt from the main file of the Firefly compiler, which is written in Firefly/ self-hosted. It showcases how effects are controlled via object capabilities, which is essentially just dependency injection taken to the logical conclusion.
The file system, the network, etc. is not globally available as in mainstream languages. The
System
object that is passed to
main
is the only way to get access to these things. It's just a value, so it can be passed on to other functions via their arguments. The FileSystem is a more narrow capability that can only be used to access the file system.
These posts explain the implicit async/await feature: https://www.ahnfelt.net/async-await-inference-in-firefly/amp/ In addition to that there is a structured concurrency system and CSP-like channels.
j
I really like this idea. Zig’s idea of passing around an allocator made so much sense for a low-level language. Passing around IO feels very similar, but for the needs of a higher level language. I’m curious about global state. Seems like if I can have global state, I can get around these guarantees. Is that forbidden? Tracked? An idea to deal with later?
j
Global state is forbidden in Firefly for that reason.
j
Does System have any in-memory storage abilities? It would be pretty neat to have something exposed there. Often my desire for “global” state is for things like observablity and metrics. Having that available via System would be a nice explicitness.
j
It currently only has logging as a "benign effect". It's safe because it can't be observed within the language (at least without a capability).
I'd be interested in suggestions for a safe metrics/observability api.
j
I definitely think it would be worth exploring adding something like a key value store of something in System. Maybe with the values being like clojure's atoms if you want some thread safety.
j
You can pass mutable objects around at your hearts content though, it's only global mutability that's disallowed.
j
Ahh, yeah. So used to immutability by default that is where my brain was going. Guess if you have mutability everywhere you don't technically need that
j
Everything is immutable by default, but you can explicitly make individual fields and variables mutable
👍 1
g
i just read like four of your blog posts—very cool. huge fan of the concurrency story in firefly
j
Thank you, it's always encouraging to hear such feedback.