[hls-fuzzer] Implement support for output contexts#905
Conversation
Prior to this PR, contexts within an AST node generation could be forwarded between siblings elements and from parents to siblings. Consuming a siblings context incorrectly meant consuming its input context. This PR properly implements the concept of an _output_ context. After an AST element has been constructed an output context is derived from it and optionally the output contexts of its children. Consuming a sibling context now also means consuming its output context. This enables the fully power of attributed grammars: Any information can now be propagated through the entire AST in any direction. This is especially useful for any typesystems that want to move information between statements. As an inititial use case the dynamatic type system has been adapted to no longer rely on randomness in the type system to choose type constraints for subelements. Rather, in cases where either choice of integer or floating point are valid, but they do not need to match (e.g. a `+` requires both operands be integers or floats), we use the output context to generate the constraint that the actual AST node adheres to and forward it to the other operands.
|
Random question: if we do Can the compiler automatically deduce the type from "this"? |
Yes, absolutely! |
|
Question: I understood that a (input) transferFn can be configured with an evaluation order. For instance, we say for an array write like We can specify that B must be generated after A. Does it have anything to do with the output context? Apparantly in the previous PR where transferFn was added this wasn't the case (because we didn't have output context). |
Reading the PR description again. does this mean that before we can only specify the order between siblings but there's no information flow? |
No this functionality was independent of the output context functionality. Output contexts are always executed at the very end (hardcoded), so do not participate in the topological sort.
There was information flow, but the information flow was as-if For your example above e.g. we could say that
Now we:
This is why all generate functions now return a pair of contexts and AST nodes |
|
For instance, for the transferFns of conditional expr:
Here, whenever we specify
We always refer to the output context when generating the |
|
Should we call the output context I think calling it
Maybe for clarity, we can also rename TransferFns and OutputTransferFns:
Some other alternative names from chat
|
Hmm not the biggest fan of the The fact that an output of one AST generation is also used as the input for another is not too crazy to me IMO. It is just like how the output (result) of a What I would suggest instead probably is to rename "parent" to "input" everywhere. That way we can simply say: "Every AST node generation has an input context and an output context and is a |
Yeah this is a good argument for input/output Just to clarify one more thing: Parent/Output is not a consistent naming:
|
Yes. In the context of the transfer functions I'd only use the "input" terminology. That we are referring to the input and output of a given AST node generation should be clear from the context (i.e., if we are in the |
|
What’s the difference between the OutputTransferFn cpp class vs. TransferFn? From the above I learned that an OutputTransferFn can depend on any output context as well as the input context, which sounds to me exactly the same as TransferFn |
|
So I don’t get why they are two separate classes 🤔 |
The only reason is really the different signature of the function. For say the transfer functions of An |
| /// It primarily differs from 'TransferFn' in that it receives a fully | ||
| /// constructed instance of 'ASTNode' rather than subelements and is always | ||
| /// executed last. |
There was a problem hiding this comment.
Okay now I get this. Let's document the discussion here (we need to also communicate to the reader why there is an extra AST node here (and it is impossible to have it in TransferFn))
|
Another question: in which situation that a transferFn needs the ast node at its input? |
|
I thought since we make the context arbitrary powerful, we don’t need to additionally pass the node itself |


Prior to this PR, contexts within an AST node generation could be forwarded between siblings elements and from parents to siblings. Consuming a siblings context incorrectly meant consuming its input context.
This PR properly implements the concept of an output context. After an AST element has been constructed an output context is derived from it and optionally the output contexts of its children. Consuming a sibling context now also means consuming its output context.
This enables the fully power of attributed grammars: Any information can now be propagated through the entire AST in any direction. This is especially useful for any typesystems that want to move information between statements.
As an inititial use case the dynamatic type system has been adapted to no longer rely on randomness in the type system to choose type constraints for subelements. Rather, in cases where either choice of integer or floating point are valid, but they do not need to match (e.g. a
+requires both operands be integers or floats), we use the output context to generate the constraint that the actual AST node adheres to and forward it to the other operands.