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

[Proposal] Custom Region DSL #52

Open
gregsn opened this issue Feb 2, 2022 · 1 comment
Open

[Proposal] Custom Region DSL #52

gregsn opened this issue Feb 2, 2022 · 1 comment
Labels

Comments

@gregsn
Copy link
Member

gregsn commented Feb 2, 2022

targets Quest: #51

Current situation

The current custom region API allows regions with BCPs (border control points).
However, some features are lacking:

  • the ability to make the region If-like or Loop-like with their special BCPs (accumulators and splicers)
  • the ability of feeding data into the region via a patch input pin, instead of a BCP
  • the ability to get back data from the region via a patch output pin, instead of a BCP
  • the ability to type the BCPs
  • if we'd have splicers: the ability to tell how the inside and outside types of a BCP differ

Stance

We should try everything to have this one unified API. It promises a unified and fluent patching experience and at the same time enables anyone to define new regions.
However, the way it is built only knows a one-way information flow: From the application-side to the definition-side of the region. It's really just able to query into the users' use of the region: "give me the BCPs and I'll try to make use of them".

What we need is to enhance this API in a way that the definition-side has a say. This is true for every single requested feature above.
And also for all of those features, we need to have a say at "compile-time":

  • the compiler wants to know about the types already
  • the IDE wants to know about which types of control points are ok
  • the node browser wants to know which pins to offer inside the region
    (...)

So how do we talk to the compiler? We only have an API that allows doing calls on runtime.

Solution

This proposal is saying: the requested feature set is big enough to NOT go for attributes as this would be too messy.
How about defining a little domain-specific language?
A language only for defining the intrinsics of the region.

As a region designer, you already create a pin and type it as a ICustomRegion in order to establish it. How about being able to configure this pin and put a small code snippet that declares how the region behaves at compile time?

Examples

Let's say you want to define a reactive loop, that allows working with one input splicer and many output splicers:

IsLoopLike
InSplicer<T>: Observable<T> -> T
OutSplicer<T>: T -> Observable<T>

This is saying how the inside and the outside data types of the splicer BCPs relate.
It might also say that the region designer doesn't care for accumulators. Let's say the patch editor only knows If-like regions, Loop-like regions, and others (in order to not overdesign everything). In that case, by specifying how splicers work, you'd already end up with a loop-like region, which also comes with accumulator pins.
But maybe that's fine:

  • if you don't support accumulators: use the Warn node if you stumble upon one
  • If there is more than one input BCP and you only support one: again use the Warn node.

Let's say you want to define a GPU-loop:

IsLoopLike
InSplicer<T>: GPUValue<T> -> GPUValue<T>
OutSplicer<T>: GPUValue<T> -> GPUValue<T>
Accumulator<T>: GPUValue<T>
Input Index: GPUValue<Integer32>

In this loop, the input and output types on splicers are the same.
It also comes with an Index pin in the patch.

In general

The instruction set can be fine-tuned and extended. We don't need to attach several attributes to one code element.

  • Accumulator: can be used in loop and If regions; You may use T to stay generic or any other concrete type.
  • Splicer In, Splicer Out ability to set the data types. The -> points downwards - the direction of the data flow.
  • Input : allows you to name an input pin

Statements that might get obsolete at some point:

  • IsLoopLike or just Loop: look and feel of the region is like a loop with its splicers and accumulators
  • IsIfLike or just If: look and feel of the region is like an If with its accumulators
  • if those are missing you get the current behavior with independent BCPs
    These might get obsolete at some point when we want to enable any kind of BCP combination(?) But they also could stay and always be a shorthand for specifying a certain set of features with a small statement.

Optional:

  • on a no-if and no-loop region: NoInputBCPs allows to opt-ouf input BCPs, since often enough it's enough to link into the region.
  • NoIngoingLinks: sometimes you might disallow crossing closure-like incoming links. E.g. when defining a GPU-function region.
@gregsn
Copy link
Member Author

gregsn commented Feb 3, 2022

I forgot to mention:
Feeding data to the patch inputs (like Index) or retrieving data from a patch output would just work along the same lines as with the BCPs, which currently is done via the ICustomRegionPatch.Update call.

    public ICustomRegionPatch Update(
        IReadOnlyList<object> inputs, IReadOnlyList<(string name, object value)> patchInputs, IReadOnlyList<object> incomingLinks,
        out Spread<object> outputs, out IReadOnlyList<(string name, object value)> patchOutputs);

However, like discussed in #54 the design of this interface depends on whether or not the multi-moment idea shall be tackled as well.

What's interesting with the approach here is that BCPs and patchPins are treated in the same fashion. The other approach of defining moments via operations of an interface looks like patch pins are treated differently from BCPs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant