Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Express all changes to objects as operations #1613

Closed
hannobraun opened this issue Feb 24, 2023 · 1 comment
Closed

Express all changes to objects as operations #1613

hannobraun opened this issue Feb 24, 2023 · 1 comment
Labels
topic: core Issues relating to core geometry, operations, algorithms type: development Work to ease development or maintenance, without direct effect on features or bugs

Comments

@hannobraun
Copy link
Owner

The objective of this issue is to create a system in which all changes to shapes in the Fornjot kernel are expressed in terms of reified operations, meaning each operation exists as a value that can be inspected at runtime. See #1385 for some higher-level thoughts on this.

Eventually, the goal is to display these operations in the GUI, and allow the user to inspect the results of each operation, seeing the intermediate states that led to the final result. However, this issue is only about laying the groundwork, by defining these operations and by having a system that processes them (with no other means of object modification being allowed).

In the rest of this issue description, I'll be going into some context that is relevant to this issue, as well as thoughts on how to implement it.

The Builder API

Modifying objects in the kernel to build up shapes has proven to be a somewhat hard problem, and one that I'm still in the process of getting a grip on. Earlier on, the level of abstraction that this object modification happened at, was very much a "structs and their fields" kind of thing. One thing that has become clear by now, is that it is very beneficial to deal with object modification on a higher level of abstraction.

One example of this, is adding a half-edge to a cycle. If what you're doing is reading from and writing to struct fields, then creating an edge consists of many little steps. So does connecting that edge to other edges in the cycle. I was able to radically simplify this a while ago, by turning "add half-edge to cycle" into a discrete operation, which takes care of the tricky parts, then returns the half-edge for further manipulation. This operation can now be reused in all scenarios where creating half-edges is required, which simplified a lot of code.

There have been other such lessons learned, which over time have coalesced into the builder API. This API is far from perfect, but it is a basis for further improvements and simplifications. Eventually, I hope that it will provide a set of simple, easy-to-understand, and orthogonal operations.

Full and Partial Objects

The builder API operates on partial objects, which are basically the first stage in an object's lifecycle. In contrast to "full" objects, which are immutable, partial objects are mutable.

This is relevant to this issue, as the builder API currently operates on partial objects. There are plans to unify the two types (#1570), and depending on how those shake out, it may be a good idea to defer this issue until that work is done, or work on both of these issues in lock-step.

Doing this work in lock-step might work out well, as the full/partial object unification will require what basically amounts to a rewrite of the builder API anyway. At that point, we might as well combine that rewrite with the implementation of this issue.

The Objects Service

I already did some experimenting with making changes to objects inspectable at runtime. The result of that is the objects service. This is in a rather rudimentary form right now, but it already provides a single place that can modify object state.

It provides a straight-forward path towards the objective outlined above, which can be achieved by expanding the commands processed by the object service to include more and more operations, until the current "insert object" command is completely replaced.

The Object Graph

As stated above, full objects are immutable, and I hope that this characteristic can be kept, as we merge full and partial objects (see #1570 for some thoughts). This implies that "modifying" an object actually means replacing it with a new object, which in turn implies that all objects referencing the original object need to be replaced with new versions as well.

Right now, the graph that objects form is only available through the object structs themselves, meaning it is defined by the struct fields that reference other objects. To make updating the object graph as described above practical, it might become necessary to have a more abstract representation of the object graph available, that allows the objects service to query which objects reference another.

If that becomes necessary, it might be best to build that abstract representation using a proc macro that derives a trait for object types. That way, we wouldn't have a duplicate representation that needs to be updated any time the object structs change.


That's all the relevant information I can think of for now.

While I believe that this issue is very important long-term, I won't start working on it immediately. The ongoing simplification work (#1589) will make implementing this issue much easier, the more it progresses.

@hannobraun hannobraun added type: development Work to ease development or maintenance, without direct effect on features or bugs topic: core Issues relating to core geometry, operations, algorithms labels Feb 24, 2023
@hannobraun
Copy link
Owner Author

I think everything mentioned here has been implemented. See the linked issues, and the pull requests referencing #1713. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: core Issues relating to core geometry, operations, algorithms type: development Work to ease development or maintenance, without direct effect on features or bugs
Projects
None yet
Development

No branches or pull requests

1 participant