On 2008-02-22, at 13:13 EST, Donald Anderson wrote:
I'm deeper into this today and trying to figure out how it all ties
together.
It's fine for the compiler to spit out these functions that
reference each other,
but someone needs to invoke a dependency to begin with.
I'm assuming that there will be something in the tag compiler that
emits an explicit call, something like:
X = $lzc$foo_dependencies();
in the right spot in the generated code? The calculation of what to
call cannot happen at
runtime (like the rp.dependencies.call(this) that is in LzNode.lzx),
I don't see any way
to lookup a function by variable name and then call it in the
reflection API.
[Aside: it appears the flex reflection API is different then ES4
proposal].
If you take my changes from trunk, you will see how this will work.
In trunk, constraints come across as an LzConstraintExpr in the attrs
list of a user class. Right now this has only 1 slot, the name of the
'binder method' to call when dependencies change, and it gets the
dependencies from `.dependencies` on that, per usual.
Once your change is in, I can re-work the tag compiler to put the
dependency computing method in a second slot of LzConstraintExpr and
fix up applyArgs to work with that. (I'd like to do this in trunk, if
possible, which is why I'm hoping you'll put your changes there.)
In fact, if you make your analyzer work on an arbitrary code fragment,
and return just the body of the constraint computation, you don't need
to worry about naming at all -- I'll make up the names in the tag
compiler when I attach the binder and dependency methods to the class
and insert the LzConstraintExpr on the attrs list.
This (working in code fragments) is really the better approach because
_eventually_ all the dependency computations can be hoisted into the
body of a custom applyArgs method for each particular class and not
have to be attached as separate methods at all.
Henry, is this something that you'll do, once I have this in hand?
I'm wondering about logistics of the change, since it involves sc,
tagcompiler
and runtime. I could hand off the sc changes to you, or you could
hand
off tagcompiler changes to me. Or I could do a phase-one-commit:
keeping current implementation in place with a new API for the
new stuff (it's not that onerous).
Also, in LPP-5452, Tucker wrote that the first two args (who,
self,...) to the current
dependencies function may not be needed - I agree with 'self' as it
can be obtained
from 'this' - and if there is no this, then self is also undefined.
But as for 'who',
I see a complex dependencies function in LaszloView.lzs:
setAttributeRelative.dependencies
that uses 'who'.
Ok, we gotta keep `who`. Now I know why.
We can keep self for now too, but while you are in there, you should
fix up the calls to dependency methods to pass `this` too. That
should ease transition, and will also make the broken methods that
believe `this` to be correct start working (I wonder what fixing
_that_ will break? :P).
Looking through sources, there are a few dozen spots to change in
runtime on the 'flag day':
/lps/components/extensions/views/richinputtext.lzx
./test/constraints.lzx
./test/lfc/testmethoddepend.lzx
./WEB-INF/lps/lfc/core/LzNode.lzs
./WEB-INF/lps/lfc/data/LzDataElement.lzs
./WEB-INF/lps/lfc/data/LzDataNode.lzs
./WEB-INF/lps/lfc/data/LzDatapointer.lzs
./WEB-INF/lps/lfc/data/LzReplicationManager.lzs
./WEB-INF/lps/lfc/views/LaszloView.lzs
./WEB-INF/lps/lfc/views/LzInputText.lzs
./WEB-INF/lps/lfc/views/LzText.lzs
Most would be mechanical, but a few, like setAttributeRelative will
need special care.
- Don
On Feb 20, 2008, at 1:07 PM, P T Withington wrote:
You'll want to follow closely http://jira.openlaszlo.org/jira/browse/LPP-5452
However we go, there is a flag day to do this when the compiler and
the LFC must be changed in sync. IWBN to fix everything at once.
The pattern I have been using is `$lzc$` as a prefix and
`_<qualifier>` as a suffix. So, for instance, the setter method
for `foo` is called `$lzc$foo_setter`, and I would make the
dependencies method for `Fcn` be `$lzc$Fcn_depenencies`.
[It would be a groovy optimization to have the unparser compress
all the $lzc$ names in production mode.]
On 2008-02-20, at 12:34 EST, Donald Anderson wrote:
Did we come up with a decision for the new dependency function
naming?
Since there are recursive dependency computation, I'll need to
know how to call
(and name) the new functions. At the moment (using the old naming
style), the expression
a.b.c + this.something.Fcn(1)
Returns this dependency array:
[a.b,
"c"].concat(this.something.Fcn.hasOwnProperty("dependencies") ?
this.something.Fcn.dependencies(this, this.something, 1) : [])
If we use $lzsc$dep$Fcn for function Fcn, then this becomes:
[a.b, "c"].concat(this.something.hasOwnProperty("$lzsc$dep
$Fcn") ? this.something.$lzsc$dep$Fcn(this, this.something, 1) : [])
I think we discussed this, not sure what was decided.
- Don
On Feb 20, 2008, at 5:05 AM, P T Withington wrote:
On 2008-02-19, at 19:00 EST, Donald Anderson wrote:
Henry,
I have the constraint function generator mostly ready.
First question - do we need an option to compute meta references?
That's apparently a compile time option, but I don't see when
it's turned on.
That was a failed experiment. Correct, but determined to be too
slow. For now, we are just keeping the code as a reference
implementation, turned off. It is trying to solve the problem
that if a constraint says `a.b.c`, we only listen for `c`
changing in `a.b`; if `b` changes in `a`, we won't notice.
In my current version, I am accepting as arguments 1) the name
of the original function,
and 2) the source for the function, for the moment I expect the
source
to look just like what you are now generating.
I am returning the source of a function with the name
XXX_dependencies.
I agree with you and Henry that it will be more useful going
forward if you accept an arbitrary expression (as a string) and
return the expression that computes the dependencies for that
(also as a string). Thus, to retrofit your code to the current
"pattern" you would analyze the expression that is the second
argument to setAttribute in the current constraint functions.
Are you doing this in RingDing? I think that would be the best
place, since then we can test against the known-working test cases.
For example, input source is this: (culled from where this
string is made in NodeModel.java):
===
function $base$2Fbasefocusview$2Elzx_282_41_x_always () {
#pragma 'constraintFunction'
#pragma 'withThis'
this.setAttribute("x",
#beginAttribute
#file base/basefocusview.lzx
#line 282
-classroot.offset
#endAttribute
)}
===
Output source is currently:
===
/* -*- file: Compiler.substitute#-1.1 -*- */
function $base$2Fbasefocusview
$2Elzx_282_41_x_always_dependencies () {
#pragma "warnUndefinedReferences=false";
with (this) {
return [classroot, "offset"]
}}
===
I'm thinking instead I could accept simply '-classroot.offset'
and return just the text of the statements:
with (this) {
return [classroot, "offset"]
}
I would leave out the `with (this)` and have that be an implicit
burden on the callee. (Especially because that is implicit in
JS2 method bodies).
Then you could name the function whatever you want or
use it as a function expression. Or I could return just the
array (as an expression) like '[classroot, "offset"]' . It
depends
on how you plan to use it, vs. how much of the details you need
to know.
- Don
--
Don Anderson
Java/C/C++, Berkeley DB, systems consultant
voice: 617-547-7881
email: [EMAIL PROTECTED]
www: http://www.ddanderson.com
--
Don Anderson
Java/C/C++, Berkeley DB, systems