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

Thy rework ir #3

Open
wants to merge 21 commits into
base: feat-implement-ir
Choose a base branch
from
Open

Thy rework ir #3

wants to merge 21 commits into from

Conversation

Soulthym
Copy link
Collaborator

New graph structure for the IR

One bug is left: when using the builder pattern, nodes get duplicated into multiple parents if a call is delegated to a sub-node. I suspect it's due to the automatic unlinking from the old parent (it also removes it from the old parent's children) getting triggered while the parent is still unset.

Copy link
Collaborator

@Leo-Besancon Leo-Besancon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Left a few comments mainly about the code, but will probably need some more time and dig deeper into it to really understand the usage and what can be improved when using it :)

ir/src/ir2/graph/graph.rs Outdated Show resolved Hide resolved
impl Child for Link<NodeTypes> {
fn get_parent(&self) -> BackLink<NodeTypes> {
match self.borrow().deref() {
NodeTypes::Graph(_) => panic!("get_parent called on graph"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the goal of this NodeTypes is to represent nodes that don't have a parent.
IMO it's clearer to have a NodeTypes::Root that only reference one "Node", and then a Graph is basically a Vec<Root> (or a Graph { boundary_roots: Vec<Root>, integrity_roots: Vec<Root> }).

Would that be possible? Or does this require too much change / is not possible because of some edge case?

The main reason not to do it I think is if this duplicates code to handle adding roots to a graph or similar

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is possible, but that currently means duplicating the code almost verbatim for the graph builder pattern (modulo what's generic and what's behind the enum variant)

I was thinking of splitting NodeType(s) into multiple categories, but havent yet found a way to make that generic enough to avoid big code duplication. If I find a way to, I'll make it a separate one with just the graph. For now, this has been the easiest to implement/extend upon.

NodeTypes::I32(ref mut leaf) => leaf.swap_parent(parent),
NodeTypes::Add(ref mut add) => add.swap_parent(parent),
NodeTypes::Function(ref mut function) => function.swap_parent(parent),
_ => panic!("set_parent called on non-node"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe "... on a NodeType that does not implement Child" is clearer?

self.node.get_children().borrow().deref()[1].clone()
}
pub fn body(&self) -> Link<NodeTypes> {
self.node.get_children().borrow().deref()[2].clone()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep in mind that index access can panic.
I don't think adding error handling is necessary, but maybe we can ensure that Function can only be created through Function::new() and without direct Object instantiation. Here, the field node: Node is private so it's fine, but on Add below it's not for example.

So nothing to change in this case, but just commenting to share :)

}
}
if not_a_node {
panic!("add_child called on non-node: {:?}", self);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

weird naming there, I think having an helper function is_node / can_have_children on NodeTypes is clearer. Then, once you check, you can have "unreachable".
and change the message to "on a NodeTypes that does not impl Parent" maybe

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, thats probably a way to customize the node's behaviour in traits with default implementations too, via such helpers.

use std::ops::{Deref, DerefMut};

#[derive(Clone, Eq, PartialEq)]
pub enum NodeTypes {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the convention is to use singular NodeType to have, when you reference variants: NodeType::Function(_)

pub enum NodeTypes {
Graph(Graph),
Node(Node),
I32(Leaf<i32>),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be Value(Leaf) basically?
And you'd have something like Variable(Leaf) along side it as the two Leaf types?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes pretty much, the Leaf is just used as a special case where it has no children. It's meant as a way to represent raw values, types, etc. Elements that cannot have sub-nodes essentially. I found it easier to think of it as a link to an arbitrary struct that should not link to other nodes (other than their parent).

Variable probably can be one too, but I need to think about edgecases more before committing to that answer. As a first guess, I agree.

The I32 naming is a relique from my testing, I'll rename to Value.

rename NodeTypes to NodeType
split NodeType into LeafNode, RootNode, MiddleNode
removed debugging
new_i32 replaced by generic new_value
LeafNode::I32 renamed to Value
implemented Felt Leaf node
improved conversions
removed debugging
removed MiddleNode::Node
renamed new_body -> new_scope
implement Default
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants