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 19d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport android.databinding.tool.BindingTarget; 206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.CallbackWrapper; 21b522c7650bf7d9ec566845bc9eb37e761eea853dGeorge Mountimport android.databinding.tool.InverseBinding; 22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 23ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyarimport android.databinding.tool.reflection.ModelClass; 24793e979f25e190162eacf46d6a4efc3efc1d2f91George Mountimport android.databinding.tool.reflection.ModelMethod; 25c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport android.databinding.tool.store.Location; 26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.L; 272611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions; 286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport android.databinding.tool.writer.ExprModelExt; 29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.FlagSet; 30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 31d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.antlr.v4.runtime.ParserRuleContext; 326047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport org.jetbrains.annotations.Nullable; 33d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.ArrayList; 3574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyarimport java.util.Arrays; 36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet; 37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.HashMap; 38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List; 39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.Map; 406047998943beebd81e0ae1068df39c0cbee38628Yigit Boyarimport java.util.concurrent.atomic.AtomicInteger; 41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class ExprModel { 43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 44895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar Map<String, Expr> mExprMap = new HashMap<String, Expr>(); 45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 46895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar List<Expr> mBindingExpressions = new ArrayList<Expr>(); 47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private int mInvalidateableFieldLimit = 0; 49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private int mRequirementIdCount = 0; 51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 52e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar // each arg list receives a unique id even if it is the same arguments and method. 53e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar private int mArgListIdCounter = 0; 54e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private static final String TRUE_KEY_SUFFIX = "== true"; 56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private static final String FALSE_KEY_SUFFIX = "== false"; 57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 59019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar * Any expression can be invalidated by invalidating this flag. 60019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar */ 61019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar private BitSet mInvalidateAnyFlags; 62eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar private int mInvalidateAnyFlagIndex; 63019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 64019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar /** 65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Used by code generation. Keeps the list of expressions that are waiting to be evaluated. 66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private List<Expr> mPendingExpressions; 68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Used for converting flags into identifiers while debugging. 71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private String[] mFlagMapping; 73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private int mFlagBucketCount;// how many buckets we use to identify flags 75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 76d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private List<Expr> mObservables; 77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 78e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar private boolean mSealed = false; 79e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 80895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar private Map<String, String> mImports = new HashMap<String, String>(); 81a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount 82c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private ParserRuleContext mCurrentParserContext; 83c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar private Location mCurrentLocationInFile; 846047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 856047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private Map<String, CallbackWrapper> mCallbackWrappers = new HashMap<String, CallbackWrapper>(); 866047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 876047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private AtomicInteger mCallbackIdCounter = new AtomicInteger(); 886047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 896047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private ExprModelExt mExt = new ExprModelExt(); 906047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Adds the expression to the list of expressions and returns it. 93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * If it already exists, returns existing one. 94d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * @param expr The new parsed expression 96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * @return The expression itself or another one if the same thing was parsed before 97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public <T extends Expr> T register(T expr) { 992611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(!mSealed, "Cannot add expressions to a model after it is sealed"); 100c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar Location location = null; 101c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (mCurrentParserContext != null) { 102c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar location = new Location(mCurrentParserContext); 103c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar location.setParentLocation(mCurrentLocationInFile); 104c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 1056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar //noinspection unchecked 106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar T existing = (T) mExprMap.get(expr.getUniqueKey()); 107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (existing != null) { 1082611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(expr.getParents().isEmpty(), 109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar "If an expression already exists, it should've never been added to a parent," 110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar + "if thats the case, somewhere we are creating an expression w/o" 111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar + "calling expression model"); 112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // tell the expr that it is being swapped so that if it was added to some other expr 113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // as a parent, those can swap their references 114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.onSwappedWith(existing); 115c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (location != null) { 116c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar existing.addLocation(location); 117c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return existing; 119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprMap.put(expr.getUniqueKey(), expr); 121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.setModel(this); 122c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (location != null) { 123c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar expr.addLocation(location); 124c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return expr; 126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar protected void markSealed() { 1296047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mSealed = true; 1306047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1316047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1326047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public ExprModelExt getExt() { 1336047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mExt; 1346047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1366047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public int obtainCallbackId() { 1376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mCallbackIdCounter.incrementAndGet(); 1386047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1396047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 140c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public void setCurrentParserContext(ParserRuleContext currentParserContext) { 141c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mCurrentParserContext = currentParserContext; 142c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 143c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1446047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public ParserRuleContext getCurrentParserContext() { 1456047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mCurrentParserContext; 1466047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1476047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 1486047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Location getCurrentLocationInFile() { 1496047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mCurrentLocationInFile; 1506047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 1516047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public Map<String, Expr> getExprMap() { 153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprMap; 154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int size() { 157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprMap.size(); 158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public ComparisonExpr comparison(String op, Expr left, Expr right) { 161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new ComparisonExpr(op, left, right)); 162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 164c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount public InstanceOfExpr instanceOfOp(Expr expr, String type) { 165c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount return register(new InstanceOfExpr(expr, type)); 166c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 167c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public FieldAccessExpr field(Expr parent, String name) { 169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new FieldAccessExpr(parent, name)); 170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1727920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount public FieldAccessExpr observableField(Expr parent, String name) { 173bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return register(new ObservableFieldExpr(parent, name)); 1747920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount } 1757920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount 176c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount public MethodReferenceExpr methodReference(Expr parent, String name) { 177c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount return register(new MethodReferenceExpr(parent, name)); 178c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount } 179c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount 180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public SymbolExpr symbol(String text, Class type) { 181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new SymbolExpr(text, type)); 182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public TernaryExpr ternary(Expr pred, Expr ifTrue, Expr ifFalse) { 185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new TernaryExpr(pred, ifTrue, ifFalse)); 186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public IdentifierExpr identifier(String name) { 189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new IdentifierExpr(name)); 190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public StaticIdentifierExpr staticIdentifier(String name) { 193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new StaticIdentifierExpr(name)); 194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1967c1b078ca84336caba7f811709836562bd5550d6George Mount public BuiltInVariableExpr builtInVariable(String name, String type, String accessCode) { 1977c1b078ca84336caba7f811709836562bd5550d6George Mount return register(new BuiltInVariableExpr(name, type, accessCode)); 1987c1b078ca84336caba7f811709836562bd5550d6George Mount } 1997c1b078ca84336caba7f811709836562bd5550d6George Mount 200d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public ViewFieldExpr viewFieldExpr(BindingTarget bindingTarget) { 201d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return register(new ViewFieldExpr(bindingTarget)); 202d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 203d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 204ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar /** 205ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar * Creates a static identifier for the given class or returns the existing one. 206ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar */ 207ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public StaticIdentifierExpr staticIdentifierFor(final ModelClass modelClass) { 208ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar final String type = modelClass.getCanonicalName(); 2092611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar // check for existing 2106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar StaticIdentifierExpr id = findStaticIdentifierExpr(type); 2116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (id != null) { 2126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return id; 213ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 214ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 215ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // does not exist. Find a name for it. 216ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar int cnt = 0; 217ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar int dotIndex = type.lastIndexOf("."); 218ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar String baseName; 2192611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(dotIndex < type.length() - 1, "Invalid type %s", type); 220ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar if (dotIndex == -1) { 221ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar baseName = type; 222ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } else { 223ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar baseName = type.substring(dotIndex + 1); 224ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 225ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar while (true) { 226ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar String candidate = cnt == 0 ? baseName : baseName + cnt; 227ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar if (!mImports.containsKey(candidate)) { 228c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar return addImport(candidate, type, null); 229ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 230ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar cnt ++; 2312611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(cnt < 100, "Failed to create an import for " + type); 232ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 233ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 234ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 2356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar @Nullable 2366047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar private StaticIdentifierExpr findStaticIdentifierExpr(String type) { 2376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (Expr expr : mExprMap.values()) { 2386047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (expr instanceof StaticIdentifierExpr) { 2396047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar StaticIdentifierExpr id = (StaticIdentifierExpr) expr; 2406047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (id.getUserDefinedType().equals(type)) { 2416047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return id; 2426047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 2436047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 2446047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 2456047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 2466047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 2476047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 248d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public MethodCallExpr methodCall(Expr target, String name, List<Expr> args) { 249d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new MethodCallExpr(target, name, args)); 250d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 251d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 252d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public MathExpr math(Expr left, String op, Expr right) { 253d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return register(new MathExpr(left, op, right)); 254d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 255d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 256c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount public TernaryExpr logical(Expr left, String op, Expr right) { 257c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount if ("&&".equals(op)) { 258c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount // left && right 2598533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar // left ? right : false 2608533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar return register(new TernaryExpr(left, right, symbol("false", boolean.class))); 261c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } else { 262c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount // left || right 2638533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar // left ? true : right 2648533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar return register(new TernaryExpr(left, symbol("true", boolean.class), right)); 265c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 266c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 267c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 268c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount public BitShiftExpr bitshift(Expr left, String op, Expr right) { 269c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount return register(new BitShiftExpr(left, op, right)); 270c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 271c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 272c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount public UnaryExpr unary(String op, Expr expr) { 273c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount return register(new UnaryExpr(op, expr)); 274c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount } 275c6bcb7bf9cab139b3141c4644e5b3267deed5213George Mount 27678dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount public Expr resourceExpr(BindingTarget target, String packageName, String resourceType, 27778dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount String resourceName, List<Expr> args) { 27878dc9ae6d67ae94bf3f637eeea0848e4f700b7a3George Mount return register(new ResourceExpr(target, packageName, resourceType, resourceName, args)); 279c752a5f795baf6df435ef60881316cb748df407cGeorge Mount } 280c752a5f795baf6df435ef60881316cb748df407cGeorge Mount 2815cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount public Expr bracketExpr(Expr variableExpr, Expr argExpr) { 2825cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount return register(new BracketExpr(variableExpr, argExpr)); 2835cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount } 2845cd681c345db8f606d7d5a8662e20e059f21a86cGeorge Mount 285e4b93061ac703e48fc2c9994c9059ed016f05559George Mount public Expr castExpr(String type, Expr expr) { 286e4b93061ac703e48fc2c9994c9059ed016f05559George Mount return register(new CastExpr(type, expr)); 287e4b93061ac703e48fc2c9994c9059ed016f05559George Mount } 288e4b93061ac703e48fc2c9994c9059ed016f05559George Mount 289d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount public TwoWayListenerExpr twoWayListenerExpr(InverseBinding inverseBinding) { 290d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return register(new TwoWayListenerExpr(inverseBinding)); 291d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 292d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Expr> getBindingExpressions() { 293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mBindingExpressions; 294d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 295d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 296c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public StaticIdentifierExpr addImport(String alias, String type, Location location) { 2976047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar String existing = mImports.get(alias); 2986047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (existing != null) { 2996047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (existing.equals(type)) { 3006047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final StaticIdentifierExpr id = findStaticIdentifierExpr(type); 3016047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar Preconditions.checkNotNull(id, "Missing import expression although it is" 3026047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar + " registered"); 3036047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return id; 3046047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } else { 3056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar L.e("%s has already been defined as %s but trying to re-define as %s", alias, 3066047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar existing, type); 3076047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 3086047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 3096047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 310a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount final StaticIdentifierExpr id = staticIdentifier(alias); 311a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount L.d("adding import %s as %s klass: %s", type, alias, id.getClass().getSimpleName()); 312a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount id.setUserDefinedType(type); 313c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar if (location != null) { 314c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar id.addLocation(location); 315c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 316a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount mImports.put(alias, type); 317ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar return id; 318a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount } 319a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount 320a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount public Map<String, String> getImports() { 321a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount return mImports; 322a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount } 323a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount 324d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 325d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * The actual thingy that is set on the binding target. 326d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 327d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Input must be already registered 328d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 329d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public Expr bindingExpr(Expr bindingExpr) { 3302611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar Preconditions.check(mExprMap.containsKey(bindingExpr.getUniqueKey()), 331d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar "Main expression should already be registered"); 332a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount if (!mBindingExpressions.contains(bindingExpr)) { 333a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount mBindingExpressions.add(bindingExpr); 334a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount } 335d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return bindingExpr; 336d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 337d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 338793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount public void removeExpr(Expr expr) { 339d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount Preconditions.check(!mSealed, "Can't modify the expression list after sealing the model."); 340793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount mBindingExpressions.remove(expr); 341c0c1dab0b6254e4d27f18c37a72a9e7952e958a0George Mount mExprMap.remove(expr.getUniqueKey()); 342793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount } 343793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount 344d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Expr> getObservables() { 345d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mObservables; 346d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 347d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 348d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar /** 349d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Give id to each expression. Will be useful if we serialize. 350d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 351793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount public void seal() { 3528533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar L.d("sealing model"); 353895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar List<Expr> notifiableExpressions = new ArrayList<Expr>(); 354d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar //ensure class analyzer. We need to know observables at this point 35579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount final ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); 356ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar updateExpressions(modelAnalyzer); 357d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 358d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar int counter = 0; 35979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount final Iterable<Expr> observables = filterObservables(modelAnalyzer); 3609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<String> flagMapping = new ArrayList<String>(); 3619784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mObservables = new ArrayList<Expr>(); 362d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : observables) { 363d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // observables gets initial ids 364d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flagMapping.add(expr.getUniqueKey()); 365d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.setId(counter++); 366d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mObservables.add(expr); 367dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar notifiableExpressions.add(expr); 368d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d("observable %s", expr.getUniqueKey()); 369d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 370d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 371d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // non-observable identifiers gets next ids 37279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount final Iterable<Expr> nonObservableIds = filterNonObservableIds(modelAnalyzer); 373d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : nonObservableIds) { 374d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flagMapping.add(expr.getUniqueKey()); 375d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.setId(counter++); 376dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar notifiableExpressions.add(expr); 377d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d("non-observable %s", expr.getUniqueKey()); 378d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 379d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 380ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // descendants of observables gets following ids 381d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : observables) { 382d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr parent : expr.getParents()) { 383d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (parent.hasId()) { 384d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar continue;// already has some id, means observable 385d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 386d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // only fields earn an id 3879e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar if (parent instanceof FieldAccessExpr) { 3889e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar FieldAccessExpr fae = (FieldAccessExpr) parent; 3899e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar L.d("checking field access expr %s. getter: %s", fae,fae.getGetter()); 3906047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar // FAE#getter might be null if it is used only in a callback. 3916047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (fae.getGetter() != null && fae.isDynamic() 3926047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar && fae.getGetter().canBeInvalidated()) { 3939e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar flagMapping.add(parent.getUniqueKey()); 3949e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar parent.setId(counter++); 3959e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar notifiableExpressions.add(parent); 3969e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar L.d("notifiable field %s : %s for %s : %s", parent.getUniqueKey(), 3979e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar Integer.toHexString(System.identityHashCode(parent)), 3989e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar expr.getUniqueKey(), 3999e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar Integer.toHexString(System.identityHashCode(expr))); 4009e20571da789c7d50650513c38d5a333b11b9fd3Yigit Boyar } 401d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 402d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 403d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 404dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar 405d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount // now all 2-way bound view fields 406d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount for (Expr expr : mExprMap.values()) { 407d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount if (expr instanceof FieldAccessExpr) { 408d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) expr; 409bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount if (fieldAccessExpr.getTarget() instanceof ViewFieldExpr) { 410d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount flagMapping.add(fieldAccessExpr.getUniqueKey()); 411d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount fieldAccessExpr.setId(counter++); 412d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 413d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 414d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 415d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 416dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar // non-dynamic binding expressions receive some ids so that they can be invalidated 4178533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar L.d("list of binding expressions"); 418a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount for (int i = 0; i < mBindingExpressions.size(); i++) { 419c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount L.d("[%d] %s", i, mBindingExpressions.get(i)); 420a70fed6415aa1e8bbbe929aee776402ac3b81c86George Mount } 4218533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar // we don't assign ids to constant binding expressions because now invalidateAll has its own 4228533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar // flag. 423dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar 424dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar for (Expr expr : notifiableExpressions) { 425d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.enableDirectInvalidation(); 426d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 427d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 428d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // make sure all dependencies are resolved to avoid future race conditions 429d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 430d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.getDependencies(); 431d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 432eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar mInvalidateAnyFlagIndex = counter ++; 433d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar flagMapping.add("INVALIDATE ANY"); 434658c71b9ba3211ac5c10f261a8c6f38b1916d3bfYigit Boyar mInvalidateableFieldLimit = counter; 4356047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar BitSet invalidateableFlags = new BitSet(); 436d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (int i = 0; i < mInvalidateableFieldLimit; i++) { 4376047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar invalidateableFlags.set(i, true); 438d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 439d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 440d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // make sure all dependencies are resolved to avoid future race conditions 441d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 442d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (expr.isConditional()) { 4438533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar L.d("requirement id for %s is %d", expr, counter); 444d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.setRequirementId(counter); 445d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flagMapping.add(expr.getUniqueKey() + FALSE_KEY_SUFFIX); 446d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flagMapping.add(expr.getUniqueKey() + TRUE_KEY_SUFFIX); 447d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar counter += 2; 448d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 449d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 4506047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar BitSet conditionalFlags = new BitSet(); 451d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (int i = mInvalidateableFieldLimit; i < counter; i++) { 4526047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar conditionalFlags.set(i, true); 453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 454d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mRequirementIdCount = (counter - mInvalidateableFieldLimit) / 2; 455d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 456d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // everybody gets an id 457d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Map.Entry<String, Expr> entry : mExprMap.entrySet()) { 458d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final Expr value = entry.getValue(); 459d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (!value.hasId()) { 460d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar value.setId(counter++); 461d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 462d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 463d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar 464d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mFlagMapping = new String[flagMapping.size()]; 465d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar flagMapping.toArray(mFlagMapping); 466d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 467019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mFlagBucketCount = 1 + (getTotalFlagCount() / FlagSet.sBucketSize); 468019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mInvalidateAnyFlags = new BitSet(); 469eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar mInvalidateAnyFlags.set(mInvalidateAnyFlagIndex, true); 470019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 471d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 472d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.getShouldReadFlagsWithConditionals(); 473d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 475d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 476d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // ensure all types are calculated 477d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.getResolvedType(); 478d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 479d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 480e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar mSealed = true; 481d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 482d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 483ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar /** 484ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar * Run updateExpr on each binding expression until no new expressions are added. 485ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar * <p> 486ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar * Some expressions (e.g. field access) may replace themselves and add/remove new dependencies 487ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar * so we need to make sure each expression's update is called at least once. 488ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar */ 489ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar private void updateExpressions(ModelAnalyzer modelAnalyzer) { 490ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar int startSize = -1; 491ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar while (startSize != mExprMap.size()) { 492ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar startSize = mExprMap.size(); 493ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar ArrayList<Expr> exprs = new ArrayList<Expr>(mBindingExpressions); 494ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar for (Expr expr : exprs) { 495ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar expr.updateExpr(modelAnalyzer); 496ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 497ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 498ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 499ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 500d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getFlagBucketCount() { 501d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mFlagBucketCount; 502d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 503d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 504d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getTotalFlagCount() { 505d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mRequirementIdCount * 2 + mInvalidateableFieldLimit; 506d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 507d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 508d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public int getInvalidateableFieldLimit() { 509d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mInvalidateableFieldLimit; 510d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 511d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 512d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String[] getFlagMapping() { 513d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mFlagMapping; 514d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 515d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 516d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getFlag(int id) { 517d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mFlagMapping[id]; 518d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 519d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 5202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private List<Expr> filterNonObservableIds(final ModelAnalyzer modelAnalyzer) { 5219784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> result = new ArrayList<Expr>(); 5222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr input : mExprMap.values()) { 5232611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (input instanceof IdentifierExpr 5242611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar && !input.hasId() 5252611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar && !input.isObservable() 5262611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar && input.isDynamic()) { 5272611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.add(input); 528d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 5292611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 5302611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result; 531d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 532d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 53379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount private Iterable<Expr> filterObservables(final ModelAnalyzer modelAnalyzer) { 5349784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> result = new ArrayList<Expr>(); 5352611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr input : mExprMap.values()) { 5362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (input.isObservable()) { 5372611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.add(input); 538d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 5392611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 5402611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result; 541d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 542d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 543d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public List<Expr> getPendingExpressions() { 544d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mPendingExpressions == null) { 5459784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar mPendingExpressions = new ArrayList<Expr>(); 546d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 54709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar // if an expression is NOT dynanic but has conditional dependants, still return it 54809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar // so that conditional flags can be set 54909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar if (!expr.isRead() && (expr.isDynamic() || expr.hasConditionalDependant())) { 550d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mPendingExpressions.add(expr); 551d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 552d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 553d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 554d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mPendingExpressions; 555d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 556d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 557d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean markBitsRead() { 558d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // each has should read flags, we set them back on them 5599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> markedSomeFlagsRead = new ArrayList<Expr>(); 560d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : filterShouldRead(getPendingExpressions())) { 561d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.markFlagsAsRead(expr.getShouldReadFlags()); 5627b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar markedSomeFlagsRead.add(expr); 563d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 5647b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar return pruneDone(markedSomeFlagsRead); 565d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 566d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 5677b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar private boolean pruneDone(List<Expr> markedSomeFlagsAsRead) { 568d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar boolean marked = true; 5699784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> markedAsReadList = new ArrayList<Expr>(); 570d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar while (marked) { 571d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar marked = false; 572d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprMap.values()) { 573d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (expr.isRead()) { 574d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar continue; 575d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 576d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (expr.markAsReadIfDone()) { 577d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d("marked %s as read ", expr.getUniqueKey()); 578d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar marked = true; 579d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar markedAsReadList.add(expr); 5807b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar markedSomeFlagsAsRead.remove(expr); 581d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 582d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 583d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 584d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar boolean elevated = false; 585d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr markedAsRead : markedAsReadList) { 586d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Dependency dependency : markedAsRead.getDependants()) { 587d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (dependency.getDependant().considerElevatingConditionals(markedAsRead)) { 588d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar elevated = true; 589d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 590d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 591d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 592f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar if (!elevated) { 593f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar for (Expr partialRead : markedSomeFlagsAsRead) { 594f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar // even if all paths are not satisfied, we can elevate certain conditional 595f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar // dependencies if all of their paths are satisfied. 596f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar for (Dependency dependency : partialRead.getDependants()) { 597f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar Expr dependant = dependency.getDependant(); 598f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar if (dependant.isConditional() && dependant.getAllCalculationPaths() 599f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar .areAllPathsSatisfied(partialRead.mReadSoFar)) { 600f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar if (dependant.considerElevatingConditionals(partialRead)) { 601f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar elevated = true; 602f58c3bd412f9bdc5ec589fdcfed470889abb6ea6Yigit Boyar } 603eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar } 6047b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 6057b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 6067b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 607d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (elevated) { 608d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // some conditionals are elevated. We should re-calculate flags 609d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : getPendingExpressions()) { 610d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (!expr.isRead()) { 611d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar expr.invalidateReadFlags(); 612d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 613d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 614d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mPendingExpressions = null; 615d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 616d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return elevated; 617d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 618d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 6192611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private static boolean hasConditionalOrNestedCannotReadDependency(Expr expr) { 6202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Dependency dependency : expr.getDependencies()) { 6212611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (dependency.isConditional() || dependency.getOther().hasNestedCannotRead()) { 6222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return true; 6232611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6242611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 6252611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return false; 626d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 627d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 6286047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public static ArrayList<Expr> filterShouldRead(Iterable<Expr> exprs) { 6296047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar ArrayList<Expr> result = new ArrayList<Expr>(); 6302611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : exprs) { 6312611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (!expr.getShouldReadFlags().isEmpty() && 6322611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar !hasConditionalOrNestedCannotReadDependency(expr)) { 6332611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.add(expr); 6342611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 635d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 6362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result; 6372611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 638d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 639d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar /** 640d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar * May return null if flag is equal to invalidate any flag. 641d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar */ 642d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public Expr findFlagExpression(int flag) { 643d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar if (mInvalidateAnyFlags.get(flag)) { 644d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar return null; 645d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar } 646d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final String key = mFlagMapping[flag]; 647d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mExprMap.containsKey(key)) { 648d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprMap.get(key); 649d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 650d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar int falseIndex = key.indexOf(FALSE_KEY_SUFFIX); 651d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (falseIndex > -1) { 652d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final String trimmed = key.substring(0, falseIndex); 653d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprMap.get(trimmed); 654d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 655d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar int trueIndex = key.indexOf(TRUE_KEY_SUFFIX); 656d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (trueIndex > -1) { 657d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final String trimmed = key.substring(0, trueIndex); 658d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mExprMap.get(trimmed); 659d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 660d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar // log everything we call 661d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar StringBuilder error = new StringBuilder(); 662d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar error.append("cannot find flag:").append(flag).append("\n"); 663d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar error.append("invalidate any flag:").append(mInvalidateAnyFlags).append("\n"); 664d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar error.append("key:").append(key).append("\n"); 665d1369ca2b7114fa456293695f3850e5be5e6d21eYigit Boyar error.append("flag mapping:").append(Arrays.toString(mFlagMapping)); 6662611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar L.e(error.toString()); 667d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return null; 668d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 669019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 670019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public BitSet getInvalidateAnyBitSet() { 671019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar return mInvalidateAnyFlags; 672019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 673e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar 674eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar public int getInvalidateAnyFlagIndex() { 675eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar return mInvalidateAnyFlagIndex; 676eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar } 677eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 678e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar public Expr argListExpr(Iterable<Expr> expressions) { 679e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar return register(new ArgListExpr(mArgListIdCounter ++, expressions)); 680e9b33bac04bb1ce1444d7f1744fcec1ecd3a57daYigit Boyar } 681716ba89e7f459f49ea85070d4710c1d79d715298George Mount 682c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public void setCurrentLocationInFile(Location location) { 683c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mCurrentLocationInFile = location; 684c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 685c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 686793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount public Expr listenerExpr(Expr expression, String name, ModelClass listenerType, 687793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount ModelMethod listenerMethod) { 688793e979f25e190162eacf46d6a4efc3efc1d2f91George Mount return register(new ListenerExpr(expression, name, listenerType, listenerMethod)); 689716ba89e7f459f49ea85070d4710c1d79d715298George Mount } 6906047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 691bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public FieldAssignmentExpr assignment(Expr target, String name, Expr value) { 692bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount return register(new FieldAssignmentExpr(target, name, value)); 693bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount } 694bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount 6956047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public Map<String, CallbackWrapper> getCallbackWrappers() { 6966047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return mCallbackWrappers; 6976047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 6986047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 6996047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public CallbackWrapper callbackWrapper(ModelClass klass, ModelMethod method) { 7006047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar final String key = CallbackWrapper.uniqueKey(klass, method); 7016047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar CallbackWrapper wrapper = mCallbackWrappers.get(key); 7026047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (wrapper == null) { 7036047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar wrapper = new CallbackWrapper(klass, method); 7046047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar mCallbackWrappers.put(key, wrapper); 7056047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 7066047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return wrapper; 7076047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 7086047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 709bb4a033fcd5cd20e5be46ef8ead442dc7db2454dGeorge Mount public LambdaExpr lambdaExpr(Expr expr, CallbackExprModel callbackExprModel) { 7106047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return register(new LambdaExpr(expr, callbackExprModel)); 7116047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 7126047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar 7136047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar public IdentifierExpr findIdentifier(String name) { 7146047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar for (Expr expr : mExprMap.values()) { 7156047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar if (expr instanceof IdentifierExpr && name.equals(((IdentifierExpr) expr).getName())) { 7166047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return (IdentifierExpr) expr; 7176047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 7186047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 7196047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar return null; 7206047998943beebd81e0ae1068df39c0cbee38628Yigit Boyar } 721d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar} 722