Skip to content

Simplify Locs, remove -1s; symlink Input nodes in start_graph, and graph in each map-elem/loop-iter#280

Open
acl-cqc wants to merge 28 commits intomainfrom
acl/start_graph
Open

Simplify Locs, remove -1s; symlink Input nodes in start_graph, and graph in each map-elem/loop-iter#280
acl-cqc wants to merge 28 commits intomainfrom
acl/start_graph

Conversation

@acl-cqc
Copy link
Contributor

@acl-cqc acl-cqc commented Jan 14, 2026

  • Add start_graph that takes dict[string, OutputLoc] and symlinks to those for all Input nodes in the graph (silently skipping any missing inputs)
  • For Loc's ending in M or L, or the root Loc, do not write_node_def; instead write_graph_def (symlink).
    • read_node_def checks the Loc ends in N; read_graph_def the converse (returning a GraphData).
  • Rename NodeRunData to RunNodeTask and define Task = RunNodeTask | LoopIterTask (returned in WalkResult) where the latter, used for walk_loop, calls start_graph
  • Also add body input containing the graph, allowing recursive graphs
  • Thus, remove all N(-1)s and "fake" Eval((-1,..)...)s, and hence the need for ExteriorRef in feat: Rust internals #266, which this is intended to precede

TODOs:

  • Track Input nodes of Graph rather than search through all the nodes to find the Inputs?
  • Use a better name than body? E.g. __tkr_body
  • Check visualizer still works

ins: dict[PortID, OutputLoc],
) -> None:
# We have to write something here to mark the node/graph as started.
# TODO ALAN - pass NodeDef? But can't really make valid/correct inputs.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a bit dubious, as per PR description

executor: ControllerExecutor,
loc: Loc,
graph_input: OutputLoc,
ins: dict[PortID, OutputLoc],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could add an enable_logging here, to match start; there'd be no uses of it, but there are none in start either....

Copy link
Collaborator

@johnchildren johnchildren left a comment

Choose a reason for hiding this comment

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

I didn't get into the meat of the PR yet, but I had a couple of comments about minor things

@acl-cqc acl-cqc changed the title Write graph inputs when starting Simplify Locs, remove -1s; symlink Input nodes in start_graph, and graph in each map-elem/loop-iter Feb 13, 2026

def get_eval_node(
storage: ControllerStorage, node_location: Loc, errored_nodes: list[Loc]
def render_graph(
Copy link
Contributor Author

@acl-cqc acl-cqc Feb 13, 2026

Choose a reason for hiding this comment

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

thus, it feels like this should be graph.py and what's currently graph.py should be something else....I mean I can move this into the current graph.py and put just get_eval_node here but the latter is pretty trivial and hardly justifies its own file

if parent is None:
raise TierkreisError("Eval node must have parent.")

thunk = storage.read_output(parent.N(node.graph[0]), node.graph[1])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a shame to have to do this detailed inspection here....the alternative would be to store both graph_def and node_def in different files, and for Eval (only), write both files. Then storage.is_node_started would have to check whether either file existed.

Seems more work and perhaps complexity but more principled and better separation; thoughts?

["node_location_str", "graph", "port", "target"],
[
("-.N0", simple_eval(), "value", b"null"),
("-.N4.M0", simple_map(), "0", b"null"),
Copy link
Contributor Author

@acl-cqc acl-cqc Feb 14, 2026

Choose a reason for hiding this comment

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

Not sure about this "0". Previous code did have something to explicitly add a "0" to the node outputs if there was a port "*", which I have removed, because post-PR there wasn't a "*" either....

["node_location_str", "graph", "target"],
[
("-.N0", simple_eval(), ["value"]),
("-.N4.M0", simple_map(), ["0"]),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

similarly

raise TierkreisError(
f"No output named {output_name} in node {node_location}"
)
if node is not None and node.type == "const" and output_name == Labels.VALUE:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a bit different to the old _build_node_outputs, shout if you don't think it makes (more) sense....

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 in a recent pr for some visualizer changes, I implemented similar logic, yours seems more elegant.
Related to the tests in this:

   ("-.N0", simple_eval(), "value", b"null"),
   ("-.N4.M0", simple_map(), "0", b"null"),

A lot of the behavior in GraphData is retrofitted to behave like the original FileStorage implementation for the visualizer to work properly. This means for some ports we basically had to emulate a value being there so we can get a node to show up in the map to view its graph.

import os
from pathlib import Path

BODY_PORT = "body"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmmm, perhaps I should use this everywhere (and move to labels.py) rather than delete it!?


def start_nodes(
@dataclass
class LoopIterTask:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is actually StartGraphTask just that we only use it for loop iters...

@acl-cqc acl-cqc requested a review from johnchildren February 14, 2026 09:21
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.

3 participants