1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/* 2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License. 6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at 7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and 14d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License. 15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.expr; 18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 19c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport org.antlr.v4.runtime.misc.Nullable; 20c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 21731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.ErrorMessages; 22731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.Scope; 23731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.scopes.LocationScopeProvider; 24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass; 26c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport android.databinding.tool.store.Location; 27731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.util.L; 282611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions; 29e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mountimport android.databinding.tool.writer.KCode; 3059229481aec5a284d322a2ca80dff836485feb0cYigit Boyarimport android.databinding.tool.writer.LayoutBinderWriterKt; 31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 3218243f6f1b7527272ef4feccdf4327d80d9f2241George Mountimport java.util.ArrayList; 3318243f6f1b7527272ef4feccdf4327d80d9f2241George Mountimport java.util.BitSet; 3418243f6f1b7527272ef4feccdf4327d80d9f2241George Mountimport java.util.Collections; 3518243f6f1b7527272ef4feccdf4327d80d9f2241George Mountimport java.util.List; 36793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport java.util.Map; 3718243f6f1b7527272ef4feccdf4327d80d9f2241George Mount 38731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarabstract public class Expr implements VersionProvider, LocationScopeProvider { 390fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public static final int NO_ID = -1; 41895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar protected List<Expr> mChildren = new ArrayList<Expr>(); 42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // any expression that refers to this. Useful if this expr is duplicate and being replaced 44895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar private List<Expr> mParents = new ArrayList<Expr>(); 45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private Boolean mIsDynamic; 47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 4879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount private ModelClass mResolvedType; 49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private String mUniqueKey; 51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private List<Dependency> mDependencies; 53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 54c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private List<Dependency> mDependants = new ArrayList<Dependency>(); 55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private int mId = NO_ID; 57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private int mRequirementId = NO_ID; 59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 607b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar private int mVersion = 0; 617b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 62d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // means this expression can directly be invalidated by the user 63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private boolean mCanBeInvalidated = false; 64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 65c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar @Nullable 669784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar private List<Location> mLocations = new ArrayList<Location>(); 67c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * This set denotes the times when this expression is invalid. 70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * If it is an Identifier expression, it is its index 71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * If it is a composite expression, it is the union of invalid flags of its descendants 72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private BitSet mInvalidFlags; 74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Set when this expression is registered to a model 77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private ExprModel mModel; 79d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * This set denotes the times when this expression must be read. 82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * It is the union of invalidation flags of all of its non-conditional dependants. 84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet mShouldReadFlags; 86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet mReadSoFar = new BitSet();// i've read this variable for these flags 88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * calculated on initialization, assuming all conditionals are true 91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet mShouldReadWithConditionals; 93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private boolean mIsBindingExpression; 95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Used by generators when this expression is resolved. 98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private boolean mRead; 1005bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar private boolean mIsUsed = false; 101d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount private boolean mIsTwoWay = false; 102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr(Iterable<Expr> children) { 104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : children) { 105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mChildren.add(expr); 106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar addParents(); 108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr(Expr... children) { 111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Collections.addAll(mChildren, children); 112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar addParents(); 113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getId() { 1162611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(mId != NO_ID, "if getId is called on an expression, it should have" 1172611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar + " an id: %s", this); 118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mId; 119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setId(int id) { 1222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(mId == NO_ID, "ID is already set on %s", this); 123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mId = id; 124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 126c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public void addLocation(Location location) { 127c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mLocations.add(location); 128c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 129c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 130c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public List<Location> getLocations() { 131c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return mLocations; 132c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 133c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public ExprModel getModel() { 135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mModel; 136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public BitSet getInvalidFlags() { 139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mInvalidFlags == null) { 140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mInvalidFlags = resolveInvalidFlags(); 141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mInvalidFlags; 143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private BitSet resolveInvalidFlags() { 146019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar BitSet bitSet = (BitSet) mModel.getInvalidateAnyBitSet().clone(); 147dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar if (mCanBeInvalidated) { 148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.set(getId(), true); 149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : getDependencies()) { 151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // TODO optional optimization: do not invalidate for conditional flags 152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.or(dependency.getOther().getInvalidFlags()); 153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return bitSet; 155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setBindingExpression(boolean isBindingExpression) { 158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mIsBindingExpression = isBindingExpression; 159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 161dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar public boolean isBindingExpression() { 162dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar return mIsBindingExpression; 163dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar } 164dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar 165e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar public boolean canBeEvaluatedToAVariable() { 166e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar return true; // anything except arg expr can be evaluated to a variable 167e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 168e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 1697920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount public boolean isObservable() { 170fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount return getResolvedType().isObservable(); 1717920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount } 1727920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount 173793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount public Expr resolveListeners(ModelClass valueType, Expr parent) { 174793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount for (int i = mChildren.size() - 1; i >= 0; i--) { 175793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount Expr child = mChildren.get(i); 176793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount child.resolveListeners(valueType, this); 177716ba89e7f459f49ea85070d4710c1d79d715298George Mount } 178793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount resetResolvedType(); 179793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount return this; 180716ba89e7f459f49ea85070d4710c1d79d715298George Mount } 181716ba89e7f459f49ea85070d4710c1d79d715298George Mount 182d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public Expr resolveTwoWayExpressions(Expr parent) { 183d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount for (int i = mChildren.size() - 1; i >= 0; i--) { 184d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final Expr child = mChildren.get(i); 185d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount child.resolveTwoWayExpressions(this); 186d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 187d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return this; 188d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 189d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 190716ba89e7f459f49ea85070d4710c1d79d715298George Mount protected void resetResolvedType() { 191716ba89e7f459f49ea85070d4710c1d79d715298George Mount mResolvedType = null; 192716ba89e7f459f49ea85070d4710c1d79d715298George Mount } 193716ba89e7f459f49ea85070d4710c1d79d715298George Mount 194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public BitSet getShouldReadFlags() { 195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mShouldReadFlags == null) { 196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar getShouldReadFlagsWithConditionals(); 197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mShouldReadFlags = resolveShouldReadFlags(); 198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mShouldReadFlags; 200d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 201d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 202d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public BitSet getShouldReadFlagsWithConditionals() { 203d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mShouldReadWithConditionals == null) { 204d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mShouldReadWithConditionals = resolveShouldReadWithConditionals(); 205d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 206d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mShouldReadWithConditionals; 207d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 208d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 209d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setModel(ExprModel model) { 210d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mModel = model; 211d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 212d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 213d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public void setTwoWay(boolean isTwoWay) { 214d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount mIsTwoWay = isTwoWay; 215d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 216d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 217d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public boolean isTwoWay() { 218d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return mIsTwoWay; 219d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 220d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 221d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected String addTwoWay(String uniqueKey) { 222d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (mIsTwoWay) { 223d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return "twoWay(" + uniqueKey + ")"; 224d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } else { 225d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return "oneWay(" + uniqueKey + ")"; 226d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 227d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 228d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 229d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private BitSet resolveShouldReadWithConditionals() { 230d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // ensure we have invalid flags 231d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet bitSet = new BitSet(); 232d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // if i'm invalid, that DOES NOT mean i should be read :/. 233d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mIsBindingExpression) { 234d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.or(getInvalidFlags()); 235d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 236d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 237d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : getDependants()) { 238d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (dependency.getCondition() == null) { 239d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.or(dependency.getDependant().getShouldReadFlagsWithConditionals()); 240d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } else { 241d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.set(dependency.getDependant() 242d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar .getRequirementFlagIndex(dependency.getExpectedOutput())); 243d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 244d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 245d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return bitSet; 246d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 247d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private BitSet resolveShouldReadFlags() { 249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // ensure we have invalid flags 250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet bitSet = new BitSet(); 251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (isRead()) { 252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return bitSet; 253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mIsBindingExpression) { 255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.or(getInvalidFlags()); 256d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 257d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : getDependants()) { 2582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final boolean isUnreadElevated = isUnreadElevated(dependency); 259d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (dependency.isConditional()) { 260e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar continue; // will be resolved later when conditional is elevated 261d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 2627b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar if (isUnreadElevated) { 2637b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar bitSet.set(dependency.getDependant() 2647b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar .getRequirementFlagIndex(dependency.getExpectedOutput())); 265d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } else { 266d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.or(dependency.getDependant().getShouldReadFlags()); 267d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 268d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 269d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitSet.and(mShouldReadWithConditionals); 2707b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar bitSet.andNot(mReadSoFar); 271d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return bitSet; 272d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 273d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 2742611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private static boolean isUnreadElevated(Dependency input) { 2752611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return input.isElevated() && !input.getDependant().isRead(); 2762611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 277d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private void addParents() { 278d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mChildren) { 279d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.mParents.add(this); 280d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 281d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 282d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 283d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void onSwappedWith(Expr existing) { 284d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr child : mChildren) { 285d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar child.onParentSwapped(this, existing); 286d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 287d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 288d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 289d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private void onParentSwapped(Expr oldParent, Expr newParent) { 2902611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(mParents.remove(oldParent), "trying to remove non-existent parent %s" 2912611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar + " from %s", oldParent, mParents); 292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mParents.add(newParent); 293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Expr> getChildren() { 296d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mChildren; 297d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 298d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 299d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Expr> getParents() { 300d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mParents; 301d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 302d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 303d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 304d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Whether the result of this expression can change or not. 305d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 306d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * For example, 3 + 5 can not change vs 3 + x may change. 307d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 308d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Default implementations checks children and returns true if any of them returns true 309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 310d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * @return True if the result of this expression may change due to variables 311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 312d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean isDynamic() { 313d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mIsDynamic == null) { 314d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mIsDynamic = isAnyChildDynamic(); 315d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mIsDynamic; 317d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 318d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 319d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private boolean isAnyChildDynamic() { 3202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : mChildren) { 3212611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (expr.isDynamic()) { 3222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return true; 323d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 3242611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 3252611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return false; 326d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 327d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 32879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount public ModelClass getResolvedType() { 329d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mResolvedType == null) { 330d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // TODO not get instance 331731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar try { 332731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar Scope.enter(this); 333731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar mResolvedType = resolveType(ModelAnalyzer.getInstance()); 334731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar if (mResolvedType == null) { 335731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar L.e(ErrorMessages.CANNOT_RESOLVE_TYPE, this); 336731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 337731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } finally { 338731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar Scope.exit(); 339731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 340d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 341d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mResolvedType; 342d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 343d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 34479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount abstract protected ModelClass resolveType(ModelAnalyzer modelAnalyzer); 345d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 346d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar abstract protected List<Dependency> constructDependencies(); 347d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 348d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 349d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Creates a dependency for each dynamic child. Should work for any expression besides 350d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * conditionals. 351d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 352d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected List<Dependency> constructDynamicChildrenDependencies() { 353895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar List<Dependency> dependencies = new ArrayList<Dependency>(); 354d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr node : mChildren) { 355d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (!node.isDynamic()) { 356d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar continue; 357d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 358d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar dependencies.add(new Dependency(this, node)); 359d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 360d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return dependencies; 361d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 362d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 363d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public final List<Dependency> getDependencies() { 364d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mDependencies == null) { 365d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mDependencies = constructDependencies(); 366d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 367d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mDependencies; 368d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 369d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 370d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar void addDependant(Dependency dependency) { 371d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mDependants.add(dependency); 372d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 373d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 374d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Dependency> getDependants() { 375d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mDependants; 376d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 377d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 378d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected static final String KEY_JOIN = "~"; 379d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 380d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 381d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Returns a unique string key that can identify this expression. 382d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 383d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * It must take into account any dependencies 384d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 385d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * @return A unique identifier for this expression 386d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 387d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public final String getUniqueKey() { 388d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mUniqueKey == null) { 389d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mUniqueKey = computeUniqueKey(); 390d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Preconditions.checkNotNull(mUniqueKey, 391d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar "if there are no children, you must override computeUniqueKey"); 3922611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(!mUniqueKey.trim().equals(""), 393d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar "if there are no children, you must override computeUniqueKey"); 394d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 395d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mUniqueKey; 396d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 397d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 398d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected String computeUniqueKey() { 399d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return computeChildrenKey(); 400d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 401d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 402d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected final String computeChildrenKey() { 4032611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return join(mChildren); 404d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 405d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 406d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void enableDirectInvalidation() { 407d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mCanBeInvalidated = true; 408d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 409d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 410d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean canBeInvalidated() { 411d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mCanBeInvalidated; 412d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 413d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 414d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void trimShouldReadFlags(BitSet bitSet) { 415d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mShouldReadFlags.andNot(bitSet); 416d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 417d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 418d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean isConditional() { 419d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return false; 420d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 421d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 422d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getRequirementId() { 423d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mRequirementId; 424d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 425d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 426d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setRequirementId(int requirementId) { 427d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mRequirementId = requirementId; 428d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 429d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 430d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 431d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * This is called w/ a dependency of mine. 432d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Base method should thr 433d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 434d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getRequirementFlagIndex(boolean expectedOutput) { 4352611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(mRequirementId != NO_ID, "If this is an expression w/ conditional" 43609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar + " dependencies, it must be assigned a requirement ID. %s", this); 437d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return expectedOutput ? mRequirementId + 1 : mRequirementId; 438d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 439d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 440d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean hasId() { 441d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mId != NO_ID; 442d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 443d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 444d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void markFlagsAsRead(BitSet flags) { 445d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mReadSoFar.or(flags); 446d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 447d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 448d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean isRead() { 449d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mRead; 450d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 451d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 45274f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar public boolean considerElevatingConditionals(Expr justRead) { 453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar boolean elevated = false; 454d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : mDependencies) { 45574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar if (dependency.isConditional() && dependency.getCondition() == justRead) { 456d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar dependency.elevate(); 45774f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar elevated = true; 458d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 459d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 460d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return elevated; 461d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 462d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 463d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void invalidateReadFlags() { 464d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mShouldReadFlags = null; 4657b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mVersion ++; 4667b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 4677b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 4687b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar @Override 4697b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar public int getVersion() { 4707b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar return mVersion; 471d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 472d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 473d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean hasNestedCannotRead() { 474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (isRead()) { 475d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return false; 476d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 477d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (getShouldReadFlags().isEmpty()) { 478d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return true; 479d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 4802611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Dependency dependency : getDependencies()) { 4812611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (hasNestedCannotRead(dependency)) { 4822611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return true; 4832611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 4842611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 4852611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return false; 486d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 487d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 4882611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private static boolean hasNestedCannotRead(Dependency input) { 4892611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return input.isConditional() || input.getOther().hasNestedCannotRead(); 4902611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 491d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 492d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean markAsReadIfDone() { 493d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mRead) { 494d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return false; 495d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 496d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // TODO avoid clone, we can calculate this iteratively 497d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet clone = (BitSet) mShouldReadWithConditionals.clone(); 498d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 499d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar clone.andNot(mReadSoFar); 500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mRead = clone.isEmpty(); 501eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 502d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (!mRead && !mReadSoFar.isEmpty()) { 503d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // check if remaining dependencies can be satisfied w/ existing values 504d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // for predicate flags, this expr may already be calculated to get the predicate 505d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // to detect them, traverse them later on, see which flags should be calculated to calculate 506d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // them. If any of them is completely covered w/ our non-conditional flags, no reason 507d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // to add them to the list since we'll already be calculated due to our non-conditional 508d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // flags 509eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar boolean allCovered = true; 510d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (int i = clone.nextSetBit(0); i != -1; i = clone.nextSetBit(i + 1)) { 511d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final Expr expr = mModel.findFlagExpression(i); 512eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (expr == null) { 513d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar continue; 514d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 515eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (!expr.isConditional()) { 516eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar allCovered = false; 517eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar break; 518eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar } 519eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final BitSet readForConditional = (BitSet) expr.findConditionalFlags().clone(); 520eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 521eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // FIXME: this does not do full traversal so misses some cases 522d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // to calculate that conditional, i should've read /readForConditional/ flags 523eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // if my read-so-far bits cover that; that means i would've already 524d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // read myself 525eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar readForConditional.andNot(mReadSoFar); 526eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (!readForConditional.isEmpty()) { 527eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar allCovered = false; 5288533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar break; 5298533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar } 530d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 531eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar mRead = allCovered; 532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 53374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar if (mRead) { 53474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mShouldReadFlags = null; // if we've been marked as read, clear should read flags 53574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar } 536d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mRead; 537d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 539d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet mConditionalFlags; 5400fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 541d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private BitSet findConditionalFlags() { 5422611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(isConditional(), "should not call this on a non-conditional expr"); 543d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mConditionalFlags == null) { 544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mConditionalFlags = new BitSet(); 545d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar resolveConditionalFlags(mConditionalFlags); 546d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 547d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mConditionalFlags; 548d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 549d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 550d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private void resolveConditionalFlags(BitSet flags) { 551d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flags.or(getPredicateInvalidFlags()); 552d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // if i have only 1 dependency which is conditional, traverse it as well 553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (getDependants().size() == 1) { 554d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final Dependency dependency = getDependants().get(0); 555d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (dependency.getCondition() != null) { 556d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flags.or(dependency.getDependant().findConditionalFlags()); 5570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar flags.set(dependency.getDependant() 5580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar .getRequirementFlagIndex(dependency.getExpectedOutput())); 559d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 560d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 561d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 562d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 563d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 564d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 565d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String toString() { 566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return getUniqueKey(); 567d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 568d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 569d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public BitSet getReadSoFar() { 570d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mReadSoFar; 571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 572d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private Node mCalculationPaths = null; 5740fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 575eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar /** 576eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar * All flag paths that will result in calculation of this expression. 577eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar */ 578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected Node getAllCalculationPaths() { 579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mCalculationPaths == null) { 580d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Node node = new Node(); 581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (isConditional()) { 582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar node.mBitSet.or(getPredicateInvalidFlags()); 583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } else { 584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar node.mBitSet.or(getInvalidFlags()); 585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : getDependants()) { 587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final Expr dependant = dependency.getDependant(); 588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (dependency.getCondition() != null) { 589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Node cond = new Node(); 590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar cond.setConditionFlag( 591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar dependant.getRequirementFlagIndex(dependency.getExpectedOutput())); 592d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar cond.mParents.add(dependant.getAllCalculationPaths()); 593eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar node.mParents.add(cond); 594d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } else { 595d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar node.mParents.add(dependant.getAllCalculationPaths()); 596d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 597d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 598d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mCalculationPaths = node; 599d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 600d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mCalculationPaths; 601d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 602d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 603d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getDefaultValue() { 60479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount return ModelAnalyzer.getInstance().getDefaultValue(getResolvedType().toJavaCode()); 605d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 606d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected BitSet getPredicateInvalidFlags() { 6080fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar throw new IllegalStateException( 6090fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar "must override getPredicateInvalidFlags in " + getClass().getSimpleName()); 6100fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar } 6110fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 6120fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar /** 6130fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar * Used by code generation 6140fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar */ 6152611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar public boolean shouldReadNow(final List<Expr> justRead) { 6162611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (getShouldReadFlags().isEmpty()) { 6172611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return false; 6182611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6192611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Dependency input : getDependencies()) { 6202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar boolean dependencyReady = input.getOther().isRead() || (justRead != null && 6212611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar justRead.contains(input.getOther())); 6222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if(!dependencyReady) { 6232611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return false; 6242611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6252611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6262611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return true; 627d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 628d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 629d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean isEqualityCheck() { 630d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return false; 631d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 632d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 6335bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public void setIsUsed(boolean isUsed) { 6345bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar mIsUsed = isUsed; 635716ba89e7f459f49ea85070d4710c1d79d715298George Mount for (Expr child : getChildren()) { 636716ba89e7f459f49ea85070d4710c1d79d715298George Mount child.setIsUsed(isUsed); 637716ba89e7f459f49ea85070d4710c1d79d715298George Mount } 6385bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 6395bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 6405bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar public boolean isUsed() { 6415bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar return mIsUsed; 6425bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar } 6435bf3700759ff21696becadd4e6fcfe2c0db6cb83Yigit Boyar 64479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount public void updateExpr(ModelAnalyzer modelAnalyzer) { 645793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount final Map<String, Expr> exprMap = mModel.getExprMap(); 646793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount for (int i = mParents.size() - 1; i >= 0; i--) { 647793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount final Expr parent = mParents.get(i); 648793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount if (exprMap.get(parent.getUniqueKey()) != parent) { 649793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount mParents.remove(i); 650793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount } 651793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount } 65218243f6f1b7527272ef4feccdf4327d80d9f2241George Mount for (Expr child : mChildren) { 65318243f6f1b7527272ef4feccdf4327d80d9f2241George Mount child.updateExpr(modelAnalyzer); 65418243f6f1b7527272ef4feccdf4327d80d9f2241George Mount } 65518243f6f1b7527272ef4feccdf4327d80d9f2241George Mount } 65618243f6f1b7527272ef4feccdf4327d80d9f2241George Mount 6572611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar protected static String join(String... items) { 6582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar StringBuilder result = new StringBuilder(); 6592611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (int i = 0; i < items.length; i ++) { 6602611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (i > 0) { 6612611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.append(KEY_JOIN); 6622611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6632611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.append(items[i]); 6642611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6652611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result.toString(); 6662611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6672611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar 6682611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar protected static String join(List<Expr> items) { 6692611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar StringBuilder result = new StringBuilder(); 6702611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (int i = 0; i < items.size(); i ++) { 6712611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (i > 0) { 6722611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.append(KEY_JOIN); 6732611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6742611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.append(items.get(i).getUniqueKey()); 6752611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6762611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result.toString(); 6772611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6782611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar 67918243f6f1b7527272ef4feccdf4327d80d9f2241George Mount protected String asPackage() { 68018243f6f1b7527272ef4feccdf4327d80d9f2241George Mount return null; 6817920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount } 6827920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount 683731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar @Override 684731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar public List<Location> provideScopeLocation() { 685731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar return mLocations; 686731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar } 687731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar 688e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount public KCode toCode() { 689d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return toCode(false); 690d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 691d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 692d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected KCode toCode(boolean expand) { 693d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (!expand && isDynamic()) { 69459229481aec5a284d322a2ca80dff836485feb0cYigit Boyar return new KCode(LayoutBinderWriterKt.getExecutePendingLocalName(this)); 695e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 696d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return generateCode(expand); 697e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 698e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount 699e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount public KCode toFullCode() { 700d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return generateCode(false); 701d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 702d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 703d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected abstract KCode generateCode(boolean expand); 704d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 705d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public KCode toInverseCode(KCode value) { 706d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount throw new IllegalStateException("expression does not support two-way binding"); 707e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 708e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount 709d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public void assertIsInvertible() { 710d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final String errorMessage = getInvertibleError(); 711d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (errorMessage != null) { 712d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount L.e(ErrorMessages.EXPRESSION_NOT_INVERTIBLE, toFullCode().generate(), 713d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount errorMessage); 714d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 715d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 716d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 717d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount /** 718d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount * @return The reason the expression wasn't invertible or null if it was invertible. 719d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount */ 720d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected abstract String getInvertibleError(); 721e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount 72209aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar /** 72309aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar * This expression is the predicate for 1 or more ternary expressions. 72409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar */ 72509aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar public boolean hasConditionalDependant() { 72609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar for (Dependency dependency : getDependants()) { 72709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar Expr dependant = dependency.getDependant(); 72809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar if (dependant.isConditional() && dependant instanceof TernaryExpr) { 72909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar TernaryExpr ternary = (TernaryExpr) dependant; 73009aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar return ternary.getPred() == this; 73109aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar } 73209aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar } 73309aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar return false; 73409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar } 73509aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar 736d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar static class Node { 7370fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 738d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet mBitSet = new BitSet(); 739895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar List<Node> mParents = new ArrayList<Node>(); 740d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar int mConditionFlag = -1; 741d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 742d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean areAllPathsSatisfied(BitSet readSoFar) { 743d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mConditionFlag != -1) { 744eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar return readSoFar.get(mConditionFlag) 745eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar || mParents.get(0).areAllPathsSatisfied(readSoFar); 746d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } else { 747eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final BitSet myBitsClone = (BitSet) mBitSet.clone(); 748eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar myBitsClone.andNot(readSoFar); 749eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (!myBitsClone.isEmpty()) { 750eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // read so far does not cover all of my invalidation. The only way I could be 751eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // covered is that I only have 1 conditional dependent which is covered by this. 752eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (mParents.size() == 1 && mParents.get(0).mConditionFlag != -1) { 753eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar return mParents.get(0).areAllPathsSatisfied(readSoFar); 754eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar } 755eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar return false; 756d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 757d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mParents.isEmpty()) { 758eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar return true; 759d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 760d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Node parent : mParents) { 761eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar if (!parent.areAllPathsSatisfied(readSoFar)) { 762d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return false; 763d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 764d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 765d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return true; 766d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 767d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 768d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 769d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setConditionFlag(int requirementFlagIndex) { 770d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mConditionFlag = requirementFlagIndex; 771d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 772d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 773d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar} 774