Пример #1
0
        /// <summary>
        /// Creates a store operation of an object field using the given field access.
        /// </summary>
        /// <param name="location">The current location.</param>
        /// <param name="objectValue">The object value.</param>
        /// <param name="fieldSpan">The field span.</param>
        /// <param name="value">The field value to store.</param>
        /// <returns>A reference to the requested value.</returns>
        public ValueReference CreateSetField(
            Location location,
            Value objectValue,
            FieldSpan fieldSpan,
            Value value)
        {
            var structureType = objectValue.Type.As <StructureType>(location);

            location.Assert(structureType.Get(Context, fieldSpan) == value.Type);

            // Fold structure values
            if (objectValue is StructureValue structureValue)
            {
                var instance = CreateStructure(location, structureType);
                foreach (Value fieldValue in structureValue.Nodes)
                {
                    instance.Add(fieldValue);
                }

                for (int i = 0; i < fieldSpan.Span; ++i)
                {
                    instance[fieldSpan.Index + i] = CreateGetField(
                        location,
                        value,
                        new FieldSpan(i));
                }

                return(instance.Seal());
            }

            return(objectValue is NullValue && fieldSpan.Span == structureType.NumFields
                ? (ValueReference)value
                : Append(new SetField(
                             GetInitializer(location),
                             objectValue,
                             fieldSpan,
                             value)));
        }
Пример #2
0
        public ValueReference CreateGetField(
            Location location,
            Value objectValue,
            FieldSpan fieldSpan)
        {
            var structureType = objectValue.Type as StructureType;

            if (structureType == null && fieldSpan.Span < 2)
            {
                return(objectValue);
            }

            // Must be a structure type
            location.AssertNotNull(structureType);

            // Try to combine different get and set operations operating on similar spans
            switch (objectValue)
            {
            case StructureValue structureValue:
                return(structureValue.Get(this, location, fieldSpan));

            case NullValue _:
                return(CreateNull(
                           location,
                           structureType.Get(Context, fieldSpan)));

            case SetField setField:
                // Optimize for simple cases
                if (setField.FieldSpan == fieldSpan)
                {
                    return(setField.Value);
                }
                // Check whether our field span is included in the updated field span
                else if (setField.FieldSpan.Contains(fieldSpan))
                {
                    // Our field span is included in the parent span
                    return(CreateGetField(
                               location,
                               setField.Value,
                               new FieldSpan(
                                   fieldSpan.Index - setField.FieldSpan.Index,
                                   fieldSpan.Span)));
                }
                // If our field span overlaps with the found one we have to split
                // the part into an overlapping part and the remaining part(s)
                else if (fieldSpan.Overlaps(setField.FieldSpan))
                {
                    // Ignore this case for now as it adds even more nodes
                    break;
                }
                // These field spans have to be distinct from each other
                else
                {
                    location.Assert(!fieldSpan.Contains(setField.FieldSpan));
                    // We can safely continue with the parent value since this
                    // SetField operation does not influence the new GetField value
                    return(CreateGetField(
                               location,
                               setField.ObjectValue,
                               fieldSpan));
                }
            }

            // We could not find any matching constant value
            return(Append(new GetField(
                              GetInitializer(location),
                              objectValue,
                              fieldSpan)));
        }
Пример #3
0
 /// <summary>
 /// Appends the referenced field accessor.
 /// </summary>
 /// <param name="fieldAccess">The field access.</param>
 public void AppendField(FieldSpan fieldAccess)
 {
     stringBuilder.Append('.');
     AppendFieldName(fieldAccess.Index);
 }
Пример #4
0
 /// <summary>
 /// Appends a field target.
 /// </summary>
 /// <param name="target">The target.</param>
 /// <param name="fieldSpan">The field span.</param>
 internal void AppendFieldTarget(Variable target, FieldSpan fieldSpan)
 {
     BeginAppendTarget(target, false);
     AppendField(fieldSpan);
     stringBuilder.Append(" = ");
 }
Пример #5
0
        /// <summary>
        /// Creates a store operation of an object field using the given field access.
        /// </summary>
        /// <param name="location">The current location.</param>
        /// <param name="objectValue">The object value.</param>
        /// <param name="fieldSpan">The field span.</param>
        /// <param name="value">The field value to store.</param>
        /// <returns>A reference to the requested value.</returns>
        public ValueReference CreateSetField(
            Location location,
            Value objectValue,
            FieldSpan fieldSpan,
            Value value)
        {
            var structureType = objectValue.Type.As <StructureType>(location);

            location.Assert(structureType.Get(BaseContext, fieldSpan) == value.Type);

            // Fold structure values
            if (objectValue is StructureValue structureValue)
            {
                var instance = CreateStructure(location, structureType);
                foreach (Value fieldValue in structureValue.Nodes)
                {
                    instance.Add(fieldValue);
                }

                for (int i = 0; i < fieldSpan.Span; ++i)
                {
                    instance[fieldSpan.Index + i] = CreateGetField(
                        location,
                        value,
                        new FieldSpan(i));
                }

                return(instance.Seal());
            }

            // Optimize common cases in which this set field operation fills a whole
            // structure instance
            if (objectValue is SetField &&
                !fieldSpan.HasSpan &&
                fieldSpan.Index + 1 == structureType.NumFields &&
                structureType.NumFields < 32)
            {
                // Initialize our internal field-value lookup
                var fieldValues = new Value[structureType.NumFields];
                fieldValues[fieldSpan.Index] = value;

                // Traverse the whole chain of all set-field operations
                var parent          = objectValue;
                int traversalLength = structureType.NumFields - 1;
                while (!(parent is NullValue) && traversalLength > 0)
                {
                    // Check whether we are still on the right track while traversing
                    // set of (possibly unordered) set-field operations
                    if (!(parent is SetField otherSetField) ||
                        otherSetField.FieldSpan.HasSpan ||
                        fieldValues[otherSetField.FieldSpan.Index] != null)
                    {
                        break;
                    }

                    // Register this set-field operation
                    fieldValues[otherSetField.FieldSpan.Index] = otherSetField.Value;
                    // Decrease the traversal length
                    --traversalLength;
                    // Update the parent
                    parent = otherSetField.ObjectValue;
                }

                // Check whether all indices have been visited found
                if (traversalLength < 1 && parent is NullValue)
                {
                    // Build new structure value containing all traversed values
                    var instance = CreateStructure(location, structureType);
                    foreach (var fieldValue in fieldValues)
                    {
                        instance.Add(fieldValue);
                    }
                    return(instance.Seal());
                }
            }

            return(objectValue is NullValue && fieldSpan.Span == structureType.NumFields
                ? (ValueReference)value
                : Append(new SetField(
                             GetInitializer(location),
                             objectValue,
                             fieldSpan,
                             value)));
        }