Show HN: Ceu = Structured Concurrency and Event-Driven Programming
https://github.com/fsantanna/dceu
Hi, I'm the author of Ceu.Any feedback is welcome.Francisco
https://github.com/fsantanna/dceu
Hi, I'm the author of Ceu.Any feedback is welcome.Francisco
Any feedback is welcome.
Francisco
- C is more portable
- C is easier to generate
- Gérard Berry: "Real time programming: Special purpose or general purpose languages"
For the semantics, I like this paper focusing on abortion (for me, the most expressive construct of synchronous languages):
- Gérard Berry: "Preemption in Concurrent Systems"
There's also a well-known survey:
- Albert Benveniste: "The synchronous languages 12 years later"
This one is about bridging the gap between synchronous and asynchronous, something like Esterel+CSP:
- Gérard Berry: "Communicating reactive processes"
For a modern take (besides Céu), check ReactiveML:
- Louis Mandel: "ReactiveML: a reactive extension to ML"
You can also search for papers from professors Stephen A. Edwards and Reinhard von Hanxleden which still work actively on the subject.
Also, at some point in the code (e.g., after you include your libraries), one can disable these calls with a directive.
But typically, one will use bindings for asynchronous libraries, such as libuv (https://github.com/fsantanna/ceu-libuv).
We also take the syntax from Pascal/Lua and the basic types and expressions from C (due to source compatibility).
http://www-sop.inria.fr/esterel-org/files/Html/Downloads/Dow...
(AFAIK, it is not open source though.)
[EDIT] For documentation, see "The Esterel Language Primer":
http://www.rw.cdl.uni-saarland.de/~kaestner/es0203/esterel_p...
Don't know about Lustre.
It seems to be feasible given the language semantics.
We'll definitely investigate it.
This was not the original academic goal, but it is now.
We want to offer an imperative alternative to program reactive systems.
- Safe and seamless integration with C (everything in ES uses C). Approach: source-to-source compiler + finalization mechanisms.
- Allow shared memory concurrency (typical in ES with I/O ports and low-level manipulation). Approach: synchronous concurrency + full determinism.
- Small overhead (we target 8-bit micro-controllers). Approach: single-threaded implementation, lexical memory management (no GC).
After investigating the synchronous languages from the '80s (Esterel, Lustre, Signal), we came to the conclusion that we wanted something in the line of Esterel.
The thesis and papers [1] discuss the design decisions in extent.
The compiler is slow, but not the final binary.
We wrote a paper [1] that compares flash,RAM,CPU usage from Céu vs hand-written event-driven code in C. The differences are negligible.
- LPeg support [1]. PEGs are great!
- The creator of Lua was my advisor since undergrad. :) (Which means that I program in Lua for a long time...)
1. Dynamic abstractions with lexical scope (vs. mostly static language). You can dynamically spawn code into a lexically-scoped pool.
2. Internal/fine-grained determinism (vs. external determinism). All statements execute in a deterministic order. E.g., if you have two printf's in parallel awaking from the same event, they will execute in lexical order.
3. Safe integration with C. When calling a C function that returns a pointer (e.g., "malloc"), Céu forces you to write a finalization clause (in which you can call "free"). If this code is somehow aborted, the "free" is called automatically.
4. Timers as first-class events (e.g., "await 1s"). Besides the convenience, Céu adjusts timers in sequence, e.g., if a first timer awakes a little bit late (due to system overhead), the timer in sequence will compensate.
5. Internal events are stack-based (vs. queue based). This allows co-routine-like functionality, resumable exceptions, and some other mechanisms.
6. Event-based logical notion of time (vs. tick based). A single event can occur at a logical time (related to #2).
[EDIT] Didn't mention that these are "advantages" depending on the context. Esterel targets hardware synthesis and also hard real-time systems. Dynamic abstractions might be irrelevant, fine-grained/sequential determinism in hardware might be inefficient, a tick is closer to a hardware clock, etc...
In comparison to Lustre:
Very different programming mindset. IIRC, in Lustre you define equations and the system is responsible for keeping them up-to-date/correct. It is a data-flow language (vs control-flow), closer to FRP than Céu/Esterel.
In summary:
Reactive: code executes in reactions to events
Synchronous: reactions run to completion, i.e., there's no implicit preemption or real parallelism (this avoids explicit synchronization: locks, queues, etc)
Structured: programs use structured control mechanisms, such as "await" (to suspend a line of execution), and "par" (to combine multiple awaiting lines of execution)
Structured programming avoids deep nesting of callbacks letting you write programs in direct/sequential style. In addition, when a line of execution is aborted, all allocated resources are safely released.
In comparison to FRP/dataflow, it is more imperative supporting sequences/loops/conditionals/parallels. The notion of (multiple) program counter is explicit. Also, everything is lexically scoped, there's no GC involved.
In comparison to promises/futures, it provides lexical parallel constructs, allowing the branches to share local variables and, more importantly, supporting safe abortion of code (with the "par/or").
Although Céu is about 5 years now, this is the first time I post to "Show HN".
In this new version, we are trying to surpass the academic fences with a more polished work (docs, build, etc).
All feedback is welcome.
Francisco
(I'm the author of Céu.)
The static version shares similar restrictions to Esterel, as you both pointed out. The dynamic version allows dynamic allocation inside lexical pools, keeping static memory management (no GC or "free"), but with possible unbounded memory usage. The actual compiler is even less restrictive and just gives warnings for unbounded loops, recursive calls, and so on.