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

Feature: Reverse graph for block annotation and block reference search #2

Open
ProfessorDey opened this issue Sep 26, 2021 · 4 comments
Labels
enhancement New feature or request

Comments

@ProfessorDey
Copy link

ProfessorDey commented Sep 26, 2021

The graph command produces the top down reference tree for the program, but in complex programs, finding the parents of a block could be quite difficult and searching the entire graph is not exactly ideal.

Providing a reversed graph with block targetting would allow for a user to quickly identify all the instances where a given block is used, which is particularly useful for reverse engineering as well as providing a way to automatically annotate code blocks with in-document linking to all parents that use the block, so users can navigate up and down the codebase within the document itself.

As an example, for a markdown file containing:

Output a set of words
    lang: zig esc: [[]] tag: #just return a string
    ---------------------------------
    pub fn test() []u8 {
        const str : []u8 = "[[words:from('text')]]";
        return str;
    }

These are the words to be said
    lang: text esc: none tag: #words
    --------------------------------
    arbitrary text

The query of zangle graph --reverse --target=#words example.md might output something along the lines of (as a simple single-target list output example):

[ "#words", [.{.tag="#just return a string", .line=2, .character=25}]]

This could then be used by other tools or in the cleanup command to annotate blocks with references, to for example output the following:


Output a set of words
#just return a string

pub fn test() []u8 {
    const str : []u8 = "[[words:from('text')]]";
    return str;
}

Code block referenced in: example.md, line 2, column 5

These are the words to be said
#words

arbitrary text

Code block referenced in: #just return a string, line 2, column 25


The flexibility of this kind of reference extraction would also be quite useful for debugging and potential integration with document editors, such as vim plugins.

@tauoverpi tauoverpi added the enhancement New feature or request label Sep 26, 2021
@tauoverpi
Copy link
Owner

I wouldn't mind providing this through Graphviz DOT for visualization as with the current function along with a --json flag for rendering the information as JSON with more or less the same information.

Something like this for JSON:

$ zangle graph --json --reverse --tag=words example.md
{
  "tag": "words",
  "location": { "line": 2, "column": 5, "file": "example.md" },
  "parents":
  [
    { "name": "just return a string", "line": 44, "column": 8, "file": "example.md" }
  ], 
  "outputs":
  [
      { "name": "example.zig", "line": 33, "column": 4 },
      { "name": "tests.zig", "line": 8, "column": 4 }
  ]
}

where

  • the parents field refers all locations where the tag is called from in the literate document and
  • the outputs field refers to the location of the block in generated files.

Is this along the lines of what you were thinking of?

@ProfessorDey
Copy link
Author

That would certainly cover most cases that immediately come to mind with the functionality, JSON is easy enough to parse and pass around to other programs and feed to APIs and IDEs. Having both graph and reverse graph give similar non-nested output like that would likely also be useful, though the example you provide only has a single level of depth and a single target. I would presume the differences would be that instead of 'parents' it would be 'children' for the regular graph direction in that case.

Though if it is flattened in both directions, then simply having a single structure including parents and children would serve the same purpose, which may simplify the implementation and leave the sorting to the recipient of the flattened graph.

@tauoverpi
Copy link
Owner

I could also provide a list of all nodes referenced just like in the graphviz output since that's then a 1:1 mapping of the different formats.

$ zangle graph --json --reverse --tag=words example.md
[
  {
    "tag": "words",
    "location": { "line": 2, "column": 5, "file": "example.md" },
    "parents":
    [
      { "name": "just return a string", "line": 44, "column": 8, "file": "example.md" }
    ], 
    ...
  },
  {
    "tag": "just return a string",
    ...
  },
]

I would presume the differences would be that instead of 'parents' it would be 'children' for the regular graph direction in that case.

Yes as it would follow the same direction as the graphviz output however,

Though if it is flattened in both directions, then simply having a single structure including parents and children would serve the same purpose, which may simplify the implementation and leave the sorting to the recipient of the flattened graph.

giving both would be a sensible format since the interpreter will also traverse the children.

@tauoverpi
Copy link
Owner

I have a different solution in mind for this one. Adding a --filter=<tagname> flag which ensures that only paths which include that tag are kept ensures that one can easily see both where it's used along with what it implies.

Would this suffice for your usecase?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants