Point72 / csp

csp is a high performance reactive stream processing library, written in C++ and Python
https://github.com/Point72/csp/wiki
Apache License 2.0
219 stars 37 forks source link

Node parser fails to recognize renamed `ts` inputs #261

Open AdamGlustein opened 5 months ago

AdamGlustein commented 5 months ago

Describe the bug

Baskets in csp are not iterable, but should be.

To Reproduce

This code will raise an error:

import csp
from csp import ts

@csp.node
def n(values: [ts[int]]):
    for val in values:
        if csp.ticked(val):
            pass

>> CspParseError: unrecognized input 'val'

This code will not:

import csp
from csp import ts

@csp.node
def n(values: [ts[int]]):
    for i in range(len(values)):
        if csp.ticked(values[i]):
            pass

Similarly for dictbaskets:

import csp
from csp import ts

@csp.node
def n(values: {str: ts[int]}):
    for key, val in values.items():
        if csp.ticked(val):
            pass

>> CspParseError: unrecognized input 'val'
import csp
from csp import ts

@csp.node
def n(values: {str: ts[int]}):
    for key, val in values.items():
        if csp.ticked(values[key]):
            pass

Expected behavior

Both of the snippets given above (for list/dictbaskets) should be equivalent.

Error Message

Runtime Environment

0.0.4 3.8.12 (default, Apr 7 2022, 17:33:24) [GCC 11.2.0] linux

Additional context

AdamGlustein commented 4 months ago

The real issue is that the node parser is failing to recognize a time-series if its renamed. This code snippet will also fail for the exact same reason:

@csp.node
def n(x: ts[int]):
    y = x
    if csp.ticked(y):
        pass
robambalu commented 4 months ago

Thats right, because ts inputs have this sort of duality. They can act as ts inputs ( which can be passed to csp.xxx() methods ), or they can be accessed as the current value ( ie x + y ) when iterating there, its accessing by value and then cant be passed to csp methods

AdamGlustein commented 4 months ago

We can maintain the duality of an input type and value during iteration so that for val in values works the exact same as for i in range(len(values)). We just need to ast parse the loop properly and update the input map.

I think it's feasible to implement, but maybe I'm missing some of the complexity. The error message here is pretty cryptic too.