public void WriteMap(Variable mapVariable, IList <Expr> indicies, Expr value) { if (!IsMapVariable(mapVariable)) { throw new ArgumentException("expected map variable"); } MapProxy mapProxyObj = null; MapTypeVariableStore.TryGetValue(mapVariable, out mapProxyObj); if (mapProxyObj == null) { throw new KeyNotFoundException("map variable not in store"); } if (mapProxyObj.CopyOnWriteOwnerKey != this.CopyOnWriteKey) { // Perform copy var newMp = mapProxyObj.Clone(this.CopyOnWriteKey); MapTypeVariableStore[mapVariable] = newMp; mapProxyObj = newMp; } Debug.Assert(mapProxyObj.CopyOnWriteOwnerKey == this.CopyOnWriteKey); mapProxyObj.WriteMapAt(indicies, value); }
public void Add(Variable v, Expr initialValue) { TypeCheckDirectAssign(v, initialValue); if (IsMapVariable(v)) { var mp = new MapProxy(initialValue, this.CopyOnWriteKey); MapTypeVariableStore.Add(v, mp); } else { BasicTypeVariableStore.Add(v, initialValue); } }
public Expr ReadMap(Variable mapVariable, IList <Expr> indicies) { if (!IsMapVariable(mapVariable)) { throw new ArgumentException("expected map variable"); } MapProxy mapProxyObj = null; MapTypeVariableStore.TryGetValue(mapVariable, out mapProxyObj); if (mapProxyObj == null) { throw new KeyNotFoundException("map variable not in store"); } return(mapProxyObj.ReadMapAt(indicies)); }
// Avoid using this for maps. It will force map store flushes public Expr this[Variable v] { get { if (IsMapVariable(v)) { return(MapTypeVariableStore[v].Read()); } else { return(BasicTypeVariableStore[v]); } } set { TypeCheckDirectAssign(v, value); if (IsMapVariable(v)) { if (MapTypeVariableStore.ContainsKey(v)) { var mp = MapTypeVariableStore[v]; if (mp.CopyOnWriteOwnerKey != this.CopyOnWriteKey) { // Make copy var newMp = mp.Clone(this.CopyOnWriteKey); MapTypeVariableStore[v] = newMp; } MapTypeVariableStore[v].Write(value); } else { MapTypeVariableStore[v] = new MapProxy(value, this.CopyOnWriteKey); } Debug.Assert(MapTypeVariableStore[v].CopyOnWriteOwnerKey == this.CopyOnWriteKey); } else { BasicTypeVariableStore[v] = value; } } }
public override Expr VisitNAryExpr(NAryExpr node) { // Try to do direct map indexing // FIXME: If there are nested mapselects but they don't end on a variable // then we'll do a lot of unnecessary work every time we traverse into a map select down. var asMapSelect = ExprUtil.AsMapSelect(node); if (asMapSelect != null) { // Gather the indices. They will be backwards as we traversing top down so have to // reverse at the end. // // Here's an example showing this: // // var m:[int][int]bool; // y:= m[0][1] // // The indicies we want are [0][1], but when traverse we will visit them backwards as // we start at the root of the expression tree. // // The structure of this is // // mapselect // / \ // mapselect 1 // / \ // m 0 var indices = new List <Expr>(); Expr firstArg = null; do { // Traverse multi-arity arguments in reverse because later on we reverse them. for (int index = asMapSelect.Args.Count - 1; index >= 1; --index) { // Don't do index variable mapping here because we might // need to throw away what we've done indices.Add(asMapSelect.Args[index]); } firstArg = asMapSelect.Args[0]; asMapSelect = ExprUtil.AsMapSelect(firstArg); } while (asMapSelect != null); // Hopefully a map variable we can write to var asId = ExprUtil.AsIdentifer(firstArg); if (asId != null && asId.Decl.TypedIdent.Type.IsMap) { // Do a remapping if necessary // FIXME: This sucks. Fix boogie instead! Variable V = null; if (preReplacementReMap.ContainsKey(asId.Decl)) { V = preReplacementReMap[asId.Decl]; } else { V = asId.Decl; } // We need to make sure that the map variable isn't bound and that // Note: that map is being fully indexed into and not partially if ((!BoundVariables.Contains(V)) && indices.Count == MapProxy.ComputeIndicesRequireToDirectlyIndex(asId.Decl.TypedIdent.Type)) { // Put indices in correct order indices.Reverse(); // Expand the indices so variables are mapped var expandedIndices = new List <Expr>(); foreach (var index in indices) { expandedIndices.Add((Expr)this.Visit(index)); } var valueFromMap = State.ReadMapVariableInScopeAt(V, expandedIndices); return(valueFromMap); } } } // Handle all other NAryExpr and fall back when we encounter a mapselect we can't support // (e.g. the map variable being used is not known). return(base.VisitNAryExpr(node)); }