In my humble opinion this is kind of the breaking point of almost all higher order programming tools. I think it’s also the reason most “no-code” or “design-to-code” tools feel like a sham to engineers. I’d love to hear how you overcame merge conflicts for your tool, I’m skeptical, but I’m all ears.
I did check on FMJ many years ago when researching about Visual Programming Languages. I recall the very inspiring notes on the FMJ website (http://www.fmjlang.co.uk/fmj/FMJ.html).
(1) The type system is inspired by TypeScript. It has generics that are resolved when unit pins are connected to concrete types. Right now there’s no way to define new types. Hopes are that type inference alone would be good enough for a start. Likewise, new interfaces cannot be created. Only the system defined interfaces can be exposed, such as channel `CH` and media stream `ST`. That is interesting because it influences the design of machines in terms of common interfaces and protocols for inputs and outputs.
(2) The visual representation is a graph specification stored in JSON. I think JSON works well with current version control systems in terms of diff readability, but I don’t see why custom unit components couldn’t be created to show the diff in graph, visually.
(3) The unit will stop the data flow and emit an “error” event. To catch this event particularly, there’s a `catch unit.
(4) Yes, there’s a few examples of recursive units, such as a `merge sort` in the open source system. The `editor` unit can’t create them from scratch right now though… but it can be done with a meta trick…
(5) The graph is loaded and saved as a JSON. The JSON has to be read by an interpreter that will instantiate all the primitives and make all the connections. Unit specification is language agnostic, but currently the project is all written in JavaScript (works with Web and NodeJS).
Similarities: code as directed graphs (less obvious in FMJ); can only connect outputs to units of compatible type; if and wait (looping is handled differently); sticky values; sliders. These design decisions are practically forced on you, but are often absent in earlier visual dataflow languages (e.g. Prograph, LabVIEW).
Differences: (1) inputs are named in Unit, ordered in FMJ (though they're named in formulas and edges can be labelled). (2) I experimented with automatic code layout but found this was too slow and not always what I wanted. Well done for getting this to work. (3) FMJ is now fully homoiconic - this maybe isn't a priority for Unit.
The Unit design philosophy is explained in https://github.com/samuelmtimbo/unit/blob/main/src/docs/conc... . This doesn't mention earlier approaches (e.g. the Manchester Dataflow Computer, Prograph) and it seems to be based on vaguely similar ideas developed more recently (Morrison's Flow Based programming; possibly React and similar systems for web development - I'm unfamiliar with these).
I have a number of questions:
(1) How does the type system work? Is it Dependently typed, Hindley-Milner, or something more basic? (FMJ is Hindley-Milner, with dependent typing partially implemented). How are new types be defined?
(2) How is the visual representation stored? One criticism I faced was that people wanted a readable textual representation which would work well with existing version control systems, a problem I have now largely solved.
(3) How are runtime errors handled?
(4) Is recursion supported? (I assume yes, but I didn't see any examples.) What about macros?
(5) What does Unit compile to? (FMJ has an experimental compiler where programs are compiled by running their source without evaluating their inputs, output is Lisp.)