  Dataflow languages provide natural support for specifying constraints between
objects in dynamic applications, where programs need to react efficiently to
changes of their environment. Researchers have long investigated how to take
advantage of dataflow constraints by embedding them into procedural languages.
Previous mixed imperative/dataflow systems, however, require syntactic
extensions or libraries of ad hoc data types for binding the imperative program
to the dataflow solver. In this paper we propose a novel approach that smoothly
combines the two paradigms without placing undue burden on the programmer. In
our framework, programmers can define ordinary commands of the host imperative
language that enforce constraints between objects stored in "reactive" memory
locations. Reactive objects can be of any legal type in the host language,
including primitive data types, pointers, arrays, and structures. Constraints
are automatically re-executed every time their input memory locations change,
letting a program behave like a spreadsheet where the values of some variables
depend upon the values of other variables. The constraint solving mechanism is
handled transparently by altering the semantics of elementary operations of the
host language for reading and modifying objects. We provide a formal semantics
and describe a concrete embodiment of our technique into C/C++, showing how to
implement it efficiently in conventional platforms using off-the-shelf
compilers. We discuss relevant applications to reactive scenarios, including
incremental computation, observer design pattern, and data structure repair.
The performance of our implementation is compared to ad hoc problem-specific
change propagation algorithms and to language-centric approaches such as
self-adjusting computation and subject/observer communication mechanisms,
showing that the proposed approach is efficient in practice.
