Overview of bind implementation

26 views
Skip to first unread message

Yang Zhang

unread,
Jul 26, 2012, 5:56:12 PM7/26/12
to visag...@googlegroups.com
Is there an overview of how Visage implements reactivity? I
understand the semantics for the user; I'm just curious how it
compiles (since there are many possibilities).

I've been poking around with decompiling visagec-produced class files,
and noticed a few basic things:

- the compiler statically determines the dependency graph (not
surprising, but interesting since it's different from / harder than
the dynamic approach some other systems take, e.g. knockout, angular,
meteor, ...)

- it maintains for each variable some metadata flags (VFLG) that
indicate among other things freshness/dirtiness

- reading a variable `x` is always done via a get$x() call that checks
these flags and updates $x if necessary (if dirty) by re-evaluating
the entire original bind expression (making other get$y() call on the
dependencies)

- writing a variable `x` is always done via a set$y() call that
updates the flags and invalidates dependents with invalidate$y

- this metadata and getter/setter pair are generated only as
necessary, requiring whole-program analysis / preventing binding from
working across dynamically loaded Visage code

- the above only describes simple static/global bindings; things get
more complicated when binding fields across object instances, which
seems to result in a dependency graph being established dynamically
rather than being hard-coded

These are my notes so far. I'd love to learn more, if anyone has
pointers to good high-level resources. The only other "archaeological
study" I could find on this is (which seems to be based on older
versions):

http://blog.cedarsoft.com/2010/05/analyzing-javafx/

I also had a specific question. I thought lazy evaluation was only
done by `bind lazy`, but it appears that the laziness is there even
with normal `bind`, as opposed to eager updates (recomputing x only
happens in get$x(), and not in set$y(), where x depends on y). I
actually didn't notice any difference between the generated code for
`bind` and `bind lazy`. If laziness is indeed how normal `bind`s work
too, then when do the updates get propagated in a GUI/event-loop app?
(On user event / periodic polling?)

Thanks!

--
Yang Zhang
http://yz.mit.edu/

William

unread,
Aug 14, 2012, 11:37:36 PM8/14/12
to visag...@googlegroups.com
I think there are two main guys that would help you with it which are Chris Oliver and Steve.

What I can say is that Visage uses antlr and digging the source will be the only way to find out :(

Weiqi Gao

unread,
Aug 14, 2012, 11:59:53 PM8/14/12
to visag...@googlegroups.com
In addition to the source code, you can also peruse the mailing list
d...@openjfx-compiler.dev.java.net. OpenJFX-compiler was the open source
project on dev.java.net where JavaFX Script was developed. The original
mailing list archive on dev.java.net is no longer available. However
you can find the messages in MarkMail.org:

http://markmail.org/search/?q=net.java.dev.openjfx-compiler.dev

All aspects of the compiler were discussed in the open on the mailing list.

--
Weiqi Gao
weiq...@gmail.com
http://www.weiqigao.com/blog/

Christopher Oliver

unread,
Aug 18, 2012, 2:28:42 PM8/18/12
to visag...@googlegroups.com
I also had a specific question.  I thought lazy evaluation was only
done by `bind lazy`, but it appears that the laziness is there even
with normal `bind`, as opposed to eager updates (recomputing x only
happens in get$x(), and not in set$y(), where x depends on y).  I
actually didn't notice any difference between the generated code for
`bind` and `bind lazy`.  If laziness is indeed how normal `bind`s work
too, then when do the updates get propagated in a GUI/event-loop app?
(On user event / periodic polling?)

Yes, all binding is implicitly lazy. Updates occur when a trigger reads a bound variable.  Unfortunately this also makes the syntactic triggers in the language practically useless. Since triggers force eager evaluation, they are mostly to be avoided.  

For graphics, presumably you want at most 2 "triggers" per frame, namely the processing of keyboard, mouse, and timer input ("event handling") and the regeneration of the frame buffer ("draw"). If done right, the former  presumably writes variables that various bound variables read by the latter depend on (e.g transform matrices, shader parameters, etc) such that these latter have their bindings updated exactly once per frame.

If you have more questions, you might try over here: http://code.google.com/p/form-follows-function/
Reply all
Reply to author
Forward
0 new messages