-
Notifications
You must be signed in to change notification settings - Fork 10
Semagrams Next Overview
"Semagrams Next" refers to the next generation of Semagrams, implemented in Scala.js and Laminar. The purpose of this refactor is to take the lessons we have learned from the first implementation, which was useful, but too janky to be sustainable, and apply them to make a more principled, stable, and extensible Semagrams.
The underlying philosophy is that we want as much code as possible to be written in extension DSLs. This will enable flexible development of many different UIs, and also vastly simplify the core code.
One key change from the original Semagrams is that in Semagrams Next, there is no longer a separation of "logical" and "layout" attributes. When preparing a UI for editing a specific ACSet, one adds in as many attributes as one likes to control the graphics. So, for instance, to prepare the standard graph schema for presentation, one might add a "position" attribute to the vertices, and a "curve" attribute to the edges. The underlying logical acset is then retrieved via a data migration.
We also take a more principled approach to drawing. For each object in the schema, we give a drawing function, which takes in the dictionary of attributes for a part and produces a graphical object. These attributes can include "derived" attributes, i.e. src.pos
and tgt.pos
for edges in a graph. This vastly simplifies the drawing logic, as we only need worry about drawing one part at a time.
However these drawings are more than simple pictures, they also will include "handles". These handles can be clicked or dragged, and upon clicking or dragging, they update attributes of the part that they are attached to.
The first domain-specific language in Semagrams Next is a domain-specific language for these drawing functions, including the handles. For now, we call this DrawLang
The second domain-specific language in Semagrams is a language for mutating acsets. The idea is that snippets of this domain-specific language will be bound to key presses, enabling custom-built keymappings for different acsets. Additionally, this domain-specific language will provide facilities for communication with an external process, and facilities for user input through user-interface elements, like pop-up dialogues or forms. For now, we call this EditLang.
The final domain-specific language is a language for specifying "hooks" on an acset. Each hook has a query associated with it, and when an acset is modified, if the results of the query change then the hook is re-run. The most important purpose of this language is to facilitate automatic update of graphical parameters of the acset, so that, for instance, the wires between a specific source and target are always evenly spaced. However, hooks could be arbitrarily complex, for instance running a spring-based layout. Hooks will use EditLang internally for their bodies, but also will need to perform additional operations. Additionally, queries need to be specified. Thus hooks are their own language, which we call HookLang.
As I think more about DrawLang/EditLang/HookLang, it's clear to me that there are definitely going to be a lot of parts that they share. Specifically, there's a logic/math layer in both drawlang and editlang that's going to be shared. Also, it would be ideal if the syntaxes for each are as similar as possible. Thus, I propose that each of these should be seen as parts of an overall language, which we will call GramScript.