---
# System prepended metadata

title: 'Eve: handling node sharing'
tags: [archive]

---

# Eve: handling node sharing

###### tags: `archive`

Playground: [DeepNote notebook](https://deepnote.com/project/8db6c32c-1bbf-4535-9b7d-6a0c3f987b15#%2Fgeneric_playground.ipynb)  

Problem:

```python

# common dialect
class Expr(Node):
  pass

class ACommonExpr(Node):
  expr: Expr

# dialect A
class ExprA(Expr):
  pass

class SpecialAExpr(ExprA): # not part of dialect B
  pass

class ComputationA(Node):
  exprs: List[ExprA]

# dialect B
class ExprB(Expr):
  pass

class SpecialBExpr(ExprB): # not part of dialect B
  pass

class ComputationB(Node):
  exprs: List[ExprB]

```

We want that `ComputationA` (a) can contain only `ExprA` nodes and common nodes (`ACommonExpr`). (b) But `ACommonExpr` itself if used in `ComputationA` must only contain `ExprA` nodes or common nodes.

In general, we have 2 ideas:

1. Pydantic with Generics
   - Solve (a) by using ABC: `ExprA.register(BinOp)`
   - Solve (b) Some mechanism using Generics `BinOpA = BinOp[ExprA]`
2. MLIR type hierarchy
   - For each node define its return type
   - For each field in a node define its allowed type

### 1. Pydantic

Neglecting (b), the problem has a nice solution. No conversion is necessary in lowering from BinOp of dialect A to BinOp of dialect B.
(Assuming the approach with generics works) This property is lost if we specialize BinOp on ExprA/ExprB as now they are different BinOps.

### 2. MLIR

Assume we want to represent the "Stencil AST" and the "CtrlFlow AST". Both ASTs allow a different subset of Exprs (taken from the same). If we describe them as generically typed (via return type and input types), all Expr would work in both ASTs. It sounds like we don't want this.

### Ideas

- "Import" all allowed nodes in a dialect (and inject Pydantic validator which ensures all nodes are in that dialect). Probably not the right approach, a bit hacky.

- 2020-10-26: just describe a mapping from one node to another, only requirement is that both nodes have the same subnodes (no need to derive from same basenode/genericnode)