lf-lang / lf-python-support

Python package for supporting code generated by the Lingua Franca compiler
Other
5 stars 0 forks source link

Too Easy to Share state variable as Pointer in Python #18

Open zoey1124 opened 2 years ago

zoey1124 commented 2 years ago

If the target language is Python, it is really easy to share the state variable as a pointer but not as value. Here is an example of me incorrectly passing the pointer of a list to reactors. Also, it will be better if the example here from the tutorial video can clarify the state value must not be pointer when share to downstream reactors.

lhstrh commented 2 years ago

:thinking: I had never really thought about this problem because I don't use Python much and I haven't been involved in the development of the Python target. But in Python, everything is an object, and Python is "pass-by-object-reference." This suggests that anything passed down to another reactor must either be deep copied or considered immutable. The latter of seems unenforceable in Python but the former would be costly.

edwardalee commented 2 years ago

I don't think "everything" needs to be deep copied, only things that remain in scope at the source reactor, namely state variables (or global variables, but in that case it is obvious what you are doing). Any local variable containing a reference to a state variable will also create problems.

Python does not have any notion of "Const" variables, so I think we are stuck and just have to carefully document this flaw.

lhstrh commented 2 years ago

Right. How can we check whether a value is accessible through the source reactor's state though? If there is no good answer to that question, then we need to either always copy to be safe, or rely on the programmer to do the right thing.

petervdonovan commented 2 years ago

This suggests that anything passed down to another reactor must either be deep copied or considered immutable. The latter of seems unenforceable in Python but the former would be costly.

Python does not have any notion of "Const" variables, so I think we are stuck and just have to carefully document this flaw.

Integers, floats, and strings in Python are immutable. Tuples and frozensets of immutable objects are immutable. Immutability can be emulated using arbitrary user-defined classes; furthermore, abstract data types can be implemented using tuples and primitives and be made immutable thereby. It is true that Python does not have "const" variables, but I don't think we need that in order to solve this problem. To my knowledge, we just need Python messages to be immutable, which seems like a practical solution to me because Python programmers are already used to being forced to make certain objects hashable, which is typically more restrictive than immutability.

We could even force messages to be immutable by throwing a runtime error if they are not hashable -- I think this would give wrong answers (both false positive and false negative) sometimes, but it would be very easy and it would at least "kind of" work.

This has already been a known issue for some time though and also applies to some other targets, especially the C target. The solution in the C target would involve parsing the C code as if non-unsafe C code were an integral part of LF. I suspect we will have to do this eventually if the C target is not superseded by the C++ target or Rust target.