nevalang / neva

🌊 Dataflow programming language with static types and implicit parallelism. Compiles to native code and Go
https://nevalang.org
MIT License
91 stars 7 forks source link

How to represent connection where we send different struct fields to different receivers? #594

Closed emil14 closed 4 months ago

emil14 commented 4 months ago

Here's how to do this without new syntax

const {
    pathToData string = "data"
    pathToIdx string = "idx"
    pathToLast string = "last"
}

component Foo(...) (...) {
    nodes {
        #bind(pathToData)
        data Field<any>

        #bind(pathToIdx)
        idx Field<int>

        #bind(pathToLast)
        last Field<bool>
    }
    net {
        :item -> [data, idx, last]
        ...
    }
}

Obv this isn't not the option. We can do better

Option 1 - Just allow several connections with same sender

:item -> lock:data
:item.data -> handler:data
:item.idx -> handler:idx
:item.last -> handler:last

Related to #473 and #501

Option 2 - Introduce special syntax

Because we have syntax for struct fields (selectors) for sender shouldn't we have it for receivers?

This version is probably consistent with "sender selector" syntax, but selector is not after port address but before it. It might be weird to have it there tho.

:item -> [
  data.handler:data,
  idx.handler:idx,
  last.handler:last
]

Another option could be this:

:item -> [
  .data -> handler:data,
  .idx -> handler:idx,
  .last -> handler:last
]

It looks better imo but less consistent with the language. It looks like a list of several connections, which they are actually, but sender selector doesn't look like that. If sender selector could look like this:

:item -> .data -> handler:data

Then it probably could more be consistent. It kind of looks like a chained connection (which, again, it actually is, in some sense).

Another thing is that some code will be bigger this way

httpGet:resp.body -> println

Will become

httpGet:resp -> .body -> println
emil14 commented 4 months ago

Solution

After conversation with @Catya3 I decided to do 2 things to solve this

Add new syntax

For cases where one message is sent to several receivers but with different struct selectors syntax gonna be this

:item -> [
  .last -> wrap:last,
  .data -> handler -> wrap:data,
  .idx -> wrap:idx
]
  1. It's consistent with existing ->[...] syntax
  2. Also with idea of allowing chained connections inside []
  3. And finally with the new one that we gonna add in the second section here

Implementation

Looks like a chained connection

RN it's implemented at the level of parser because that's easy (even tho it's dirty)

So we need to

  1. Remove selectors from SenderSide
  2. Add another type of sender - selector
  3. Implement this as a chained connections

Update existing syntax

Replace :item.data -> handler with :item -> .data -> handler

  1. That will be consistent with prev syntax
  2. It reflects what is actually going on much better
emil14 commented 4 months ago

Close in flavor of https://github.com/nevalang/neva/issues/653