Skip to content

How to represent a while loop #24

@samwaseda

Description

@samwaseda

In semantikon, I managed to parse a function without if, for and while to create a workflow (cf. this file). The dict-representation is based on this one. Now, I would like to extend it to if, for and while. For this, let's take a look at the following workflow:

def add(x, y):
    return x + y

def my_workflow(x, y):
    while x < 0:
        x = add(x, y)
        y = add(x, y)
    return y

(Note: This function has no particular meaning, except for having a while loop)

According to the AST syntax, this while loop has two components: test and body. As the names already sort of suggest, test is the part after while, i.e. x < 0 and body is the indented part after while. In principle, the body can be considered as a workflow itself, knowing that it's a cyclic graph and therefore should not be put in the same way as a normal workflow, and the whole while loop can be wrapped as a nested node. In this case, my_workflow can therefore be considered to be a workflow containing one step:

def my_workflow(x, y):
    y = injected_while_loop(x, y)
    return y

From the technical point of view, we still have to make sure that the inputs and the outputs are correctly identified. In this case the inputs are x and y, and the output is y. I think that's easily achievable. The bigger question is how to represent it. An obvious choice is to represent it just like a normal node and mark it with an additional tag, such as "type", i.e. the one above could be represented as:

{
    'inputs': {'x': {}, 'y': {}},
    'outputs': {'result': {}},
    'nodes': {
        'injected_while_loop_0': {
            'type': 'while',
            'test': 'x < 0',
            'inputs': {'x': {}, 'y': {}},
            'outputs': {'result': {}},
            'nodes': {
                'inputs': {'x': {}, 'y': {}},
                'outputs': {'result': {}},
                'nodes': {
                    'add_0': {
                        'function': <function __main__.add(x, y)>,
                        'inputs': {'x': {}, 'y': {}},
                        'outputs': {'output': {}}
                    },
                    'add_1': {
                        'function': <function __main__.add(x, y)>,
                        'inputs': {'x': {}, 'y': {}},
                        'outputs': {'output': {}}
                },
            'data_edges': [
                ['inputs.x', 'add_0.inputs.x'],
                ['inputs.x', 'add_1.inputs.x'],
                ['inputs.y', 'add_0.inputs.y'],
                ['inputs.y', 'add_1.inputs.y'],
                ['add_1.outputs.output', 'outputs.y']
            ],
            'label': 'injected_while_loop'
        },
    'data_edges': [
        ['inputs.x', 'injected_while_loop_0.inputs.x'],
        ['inputs.y', 'injected_while_loop_0.inputs.y'],
        ['injected_while_loop_0.outputs.output', 'outputs.result']
    ],
    'label': 'my_workflow'
}

And while writing this, I started feeling more and more that this is the right way to go. Anyway suggestions are welcome.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions