private void ProcessFieldReferenceOperation(IFieldReferenceOperation fieldOp) { if (fieldOp.Instance == null) { // Static members are not supported now // TODO: Report a warning return; } var referenceModel = this.TryGetVariableFromOperation(fieldOp.Instance) as ReferenceModel; if (referenceModel == null) { // Compute the reference in a separate node if it is not a variable referenceModel = (ReferenceModel)this.Context.CreateTemporaryVariableModel( this.Context.ModelManager.TryGetFactory(fieldOp.Instance.Type), fieldOp.Instance.Type); var referenceNode = this.Context.PrependCurrentNode(fieldOp.Instance.Syntax, DisplayNodeConfig.Inherit); referenceNode.VariableModel = referenceModel; } var fields = this.Context.ModelManager.TypeContext.GetFieldDefinitions(fieldOp.Field); if (this.Context.CurrentNode.VariableModel == null && this.Context.CurrentNode.Operation == null) { // Start by filling the left side of the assignment, if not filled already // (by a variable or an operation) this.Context.CurrentNode.Operation = new HeapOperation( SpecialOperationKind.FieldWrite, referenceModel, fields); } else { Contract.Assert(this.Context.CurrentNode.ValueModel == null); // Otherwise, fill the right side of the assignment var readOp = new HeapOperation(SpecialOperationKind.FieldRead, referenceModel, fields); if (this.Context.CurrentNode.Operation == null) { this.Context.CurrentNode.Operation = readOp; } else { // If there is already an operation (such as field write), put the read to a new node var readResult = this.Context.CreateTemporaryVariableModel( this.Context.ModelManager.TryGetFactory(fieldOp.Type), fieldOp.Type); var readNode = this.Context.PrependCurrentNode( fieldOp.Syntax, DisplayNodeConfig.Inherit, isFinal: true); readNode.VariableModel = readResult; readNode.Operation = readOp; this.Context.CurrentNode.ValueModel = readResult; } } }
private IEnumerable <Operation> TranslateHeapOperations( ITypeModel variableModel, ITypeModel valueModel, HeapOperation heapOp) { if (heapOp.Kind == SpecialOperationKind.FieldRead) { if (variableModel == null) { yield break; } var translatedReference = this.TranslateVariable(heapOp.Reference.AssignmentLeft.Single()); var variables = variableModel.AssignmentLeft; Contract.Assert(variables.Count == heapOp.Fields.Length); for (int i = 0; i < variables.Count; i++) { Contract.Assert(variables[i].Sort == heapOp.Fields[i].Sort); yield return(new FieldRead( this.TranslateVariable(variables[i]), translatedReference, heapOp.Fields[i])); } } else { Contract.Assert(heapOp.Kind == SpecialOperationKind.FieldWrite); if (valueModel == null) { yield break; } var translatedReference = this.TranslateVariable(heapOp.Reference.AssignmentLeft.Single()); var values = valueModel.AssignmentRight; Contract.Assert(values.Count == heapOp.Fields.Length); for (int i = 0; i < values.Count; i++) { Contract.Assert(values[i].Sort == heapOp.Fields[i].Sort); yield return(new FieldWrite( translatedReference, heapOp.Fields[i], this.TranslateExpression(values[i]))); } } }