Fun is an experiment, just for fun, but Fun works!
Fun is a highly strict programming language, but also highly simple. It looks like Python (My favorite language), but there are differences.
Influenced by Bash, C, Lua, PHP, Python, and a little Rust.
Fun is written in C(C99) and many libs are implemented in pure Fun. Smartcard(PCSC) is available as extension written in C while sha256 or sha512 are implemented in Fun.
Would love to get some feedback (hanez@fun-lang.xyz), but please read the content on https://fun-lang.xyz first.
Have fun!
hanez
frank_nord•1w ago
Looks interesting... ;) Thank You!
hanez•1w ago
You're welcome! Would love to get some feedback!
storystarling•1w ago
How are you handling shared state with the new concurrency primitives? Since it is embeddable I am curious if you went with a global lock approach like Python or isolated states similar to Lua. Managing thread safety while keeping the C API simple is usually the hardest part of these implementations so I would love to hear more about the architectural choices there.
hanez•1w ago
I chose isolated state (like Lua) rather than a single global lock (like Python’s GIL). Each VM has its own heap, scheduler, and garbage collection. There are no cross-VM pointers. Concurrency and data exchange happen via message passing and a few carefully scoped shared-memory primitives for high‑throughput use cases. This keeps the C API simple, predictable, and safe to embed in multi‑threaded hosts.
storystarling•1w ago
Isolated state seems like the right call. I am curious how you implemented the shared memory primitives though. I spent a while trying to get zero-copy buffer sharing right in a previous project and usually ended up complicating the host API significantly to guarantee safety. Are you using reference counting or some kind of ownership transfer model there?
hanez•1w ago
• We default to isolates for safety and scaling.
• Zero‑copy sharing is done with fun_shared_buffer, an off‑heap, GC‑untracked, pointer‑free block that’s immutable from the VM’s point of view.
• Lifetime is managed with plain reference counting (retain/release).
• For hot paths, we also support an adoption (ownership‑transfer) pattern during message passing so the sender can drop its ref without copying.
storystarling•1w ago
Isolated state is definitely the right call. I am curious how you implemented the shared memory primitives though. Usually that is where the complexity creeps back in if you want to avoid global locks. How do you expose that without forcing the host to manage its own synchronization?
hanez•1w ago
We don’t expose shared mutability to VMs. The trick is: publish‑as‑immutable plus adoption via ports. Ports/queues do the synchronization; fun_shared_buffer is off‑heap and refcounted with atomic ops. The host doesn’t need to lock anything for the common paths.
hanez•1w ago
I added a section to https://git.xw3.org/fun/fun/src/branch/main/docs/internals.m... that describes this more detailed. I copied from other documents some seconds ago and I am not sure if this all is 100% correct actually. I will check this and will update the file if I find some wrong parts...
storystarling•1w ago
Thanks for the link. I will take a look at the internals. The trade-off between global locks and isolated states is usually the most critical decision for embeddable languages so I am curious to see how the implementation handles it.
storystarling•1w ago
Isolated state is the sensible choice for embedding; fighting a GIL from the host language is miserable. I guess those shared-memory primitives are the escape hatch for when message passing serialization gets too expensive? The documentation seems consistent, though I'd be curious if the per-VM garbage collectors need to stop-the-world to scan those shared regions.
hanez•1w ago
• Yes: isolated state (one VM per embed) is usually the right default. It avoids global locks (e.g., a GIL), makes scheduling simpler, and keeps failure/lifetime boundaries crisp.
• Yes: shared‑memory primitives are the “escape hatch” for when copying/serialization is too expensive, but they should be very carefully constrained.
• GC: If you design shared regions to be untraced (no VM heap pointers inside), each VM’s GC can remain independent and never stop other VMs. If you allow GC’d objects to be shared across VMs, you either need a global safepoint (stop‑the‑world across participants) or a more complex concurrent/barriered scheme.
I added some more information about this to the internals document.
hanez•1w ago
I need to say, that issues can be opened at https://github.com/hanez/fun/issues, but I do not develop Fun on GitHub. Pull requests will not be accepted there. Send patches or ask me for an account on https://git.xw3.org... ;)
hanez•1w ago
Fun is an experiment, just for fun, but Fun works!
Fun is a highly strict programming language, but also highly simple. It looks like Python (My favorite language), but there are differences.
Influenced by Bash, C, Lua, PHP, Python, and a little Rust.
Fun is written in C(C99) and many libs are implemented in pure Fun. Smartcard(PCSC) is available as extension written in C while sha256 or sha512 are implemented in Fun.
Would love to get some feedback (hanez@fun-lang.xyz), but please read the content on https://fun-lang.xyz first.
Have fun! hanez
frank_nord•1w ago
hanez•1w ago
storystarling•1w ago
hanez•1w ago
storystarling•1w ago
hanez•1w ago
• Zero‑copy sharing is done with fun_shared_buffer, an off‑heap, GC‑untracked, pointer‑free block that’s immutable from the VM’s point of view.
• Lifetime is managed with plain reference counting (retain/release).
• For hot paths, we also support an adoption (ownership‑transfer) pattern during message passing so the sender can drop its ref without copying.
storystarling•1w ago
hanez•1w ago
hanez•1w ago
storystarling•1w ago
storystarling•1w ago
hanez•1w ago
• Yes: shared‑memory primitives are the “escape hatch” for when copying/serialization is too expensive, but they should be very carefully constrained.
• GC: If you design shared regions to be untraced (no VM heap pointers inside), each VM’s GC can remain independent and never stop other VMs. If you allow GC’d objects to be shared across VMs, you either need a global safepoint (stop‑the‑world across participants) or a more complex concurrent/barriered scheme.
I added some more information about this to the internals document.
hanez•1w ago