Пример #1
0
        /// <summary>
        /// Pushes a new frame, e.g. when starting to process a lambda expression or a block expression.
        /// </summary>
        /// <param name="json">JSON representation of the serialization frame.</param>
        /// <param name="types">Type space used to lookup parameter types.</param>
        /// <returns>Frame containing mappings for the specified parameters.</returns>
        public DeserializationFrame PushFrame(Json.Expression json, TypeSpace types)
        {
            var frame = new DeserializationFrame(json, types);

            _environment.Push(frame);
            return(frame);
        }
Пример #2
0
            /// <summary>
            /// Reconstructors a label registration from a JSON representation.
            /// </summary>
            /// <param name="label">JSON representation of a label registration.</param>
            /// <param name="types">Type space to look up label types.</param>
            /// <returns>Label registration corresponding to the JSON representation.</returns>
            public static LabelTarget FromJson(Json.Expression label, TypeSpace types)
            {
                var jo   = (Json.ObjectExpression)label;
                var type = types.Lookup(TypeRef.FromJson(jo.Members["Type"]));
                var name = (string)((Json.ConstantExpression)jo.Members["Name"]).Value;

                return(Expression.Label(type, name));
            }
Пример #3
0
        /// <summary>
        /// Reconstructs a label tracking instance from the given JSON representation.
        /// </summary>
        /// <param name="json">JSON representation of a label tracking instance.</param>
        /// <param name="types">Type space to lookup label types.</param>
        /// <returns>Label tracking instance corresponding to the given JSON representation.</returns>
        public static Labels FromJson(Json.Expression json, TypeSpace types)
        {
            var labels = (Json.ArrayExpression)json;

            return(new Labels(labels.Elements
                              .Select((label, i) => (Label: LabelRegistration.FromJson(label, types), Id: i))
                              .ToDictionary(x => x.Id, x => x.Label)
                              ));
        }
Пример #4
0
        /// <summary>
        /// Retrieves a label target using the given label registration JSON representation.
        /// This method can only be used during deserialization.
        /// </summary>
        /// <param name="target">Label registration JSON representation.</param>
        /// <returns>Label target for the given label registration JSON representation.</returns>
        public LabelTarget GetLabel(Json.Expression target)
        {
            var i = int.Parse((string)((Json.ConstantExpression)target).Value, CultureInfo.InvariantCulture);

            if (!_deserializationLabels.TryGetValue(i, out LabelTarget t))
            {
                throw new InvalidOperationException("Unknown label with index " + i);
            }

            return(t);
        }
Пример #5
0
        /// <summary>
        /// Tries to get the address of the specified object on the heap.
        /// This method can only be used during serialization.
        /// </summary>
        /// <param name="item">Object to lookup in the heap.</param>
        /// <param name="address">Object reference representation to use for serialization.</param>
        /// <returns>true if the object was found on the heap; otherwise, false.</returns>
        public bool TryGetAddress(object item, out Json.Expression address)
        {
            var res = ADDRESS_NULL;

            if (item == null || _addressOf.TryGetValue(item, out res))
            {
                address = AddressToJson(res);
                return(true);
            }

            address = null;
            return(false);
        }
Пример #6
0
        /// <summary>
        /// Tries to get an object instance from the heap at the specified address.
        /// This method can only be used during deserialization.
        /// </summary>
        /// <param name="address">Address to retrieve the object instance from.</param>
        /// <param name="item">Object instance found on the heap.</param>
        /// <returns>true if the object was found on the heap; otherwise, false.</returns>
        public bool TryLookup(Json.Expression address, out object item)
        {
            var n = AddressFromJson(address);

            if (n == ADDRESS_NULL)
            {
                item = null;
                return(true);
            }
            else
            {
                return(_deserializedObjects.TryGetValue(n, out item));
            }
        }
Пример #7
0
        /// <summary>
        /// Creates a deserialization frame from the given JSON representation.
        /// </summary>
        /// <param name="json">JSON representation of a frame.</param>
        /// <param name="types">Type space used to lookup parameter types.</param>
        public DeserializationFrame(Json.Expression json, TypeSpace types)
        {
            _parameters = new List <ParameterExpression>();
            _mapping    = new Dictionary <string, ParameterExpression>();

            foreach (Json.ObjectExpression p in ((Json.ArrayExpression)json).Elements)
            {
                //
                // Note: keep in sync with SerializationFrame::ToJson code.
                //
                Add(
                    (string)((Json.ConstantExpression)p.Members["Name"]).Value,
                    types.Lookup(TypeRef.FromJson(p.Members["Type"])),
                    (string)((Json.ConstantExpression)p.Members["FriendlyName"]).Value
                    );
            }
        }
Пример #8
0
        /// <summary>
        /// Adds the specified object to the heap.
        /// This method can only be used during serialization.
        /// </summary>
        /// <param name="item">Object to add to the heap.</param>
        /// <param name="serialized">Serialized object representation.</param>
        /// <returns>Object reference representation to use for serialization.</returns>
        public Json.Expression Add(object item, Json.Expression serialized)
        {
            var address = ADDRESS_NULL;

            if (item != null)
            {
                if (_addressOf.ContainsKey(item))
                {
                    throw new InvalidOperationException("Heap already contains the specified object.");
                }

                address           = ADDRESS_FIRST + _addressOf.Count;
                _addressOf[item]  = address;
                _objects[address] = serialized;
            }

            return(AddressToJson(address));
        }
Пример #9
0
        /// <summary>
        /// Restores a heap, used for deserialization, from the given JSON representation.
        /// </summary>
        /// <param name="expression">JSON representation of a heap.</param>
        /// <returns>Heap used for deserialization.</returns>
        public static Heap FromJson(Json.Expression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var objects = (Json.ArrayExpression)expression;

            var res = new Heap(false);

            var address = ADDRESS_FIRST;

            foreach (var obj in objects.Elements)
            {
                res._objects[address++] = obj;
            }

            return(res);
        }
Пример #10
0
        /// <summary>
        /// Restores an expression tree serialization context, used for deserialization, from the given JSON representation.
        /// </summary>
        /// <param name="expression">JSON representation of an expression tree serialization context.</param>
        /// <param name="typeResolutionService">Type resolution service. Can be null.</param>
        /// <returns>Expression tree serialization context used for deserialization.</returns>
        public static ExpressionJsonSerializationContext FromJson(Json.Expression expression, ITypeResolutionService typeResolutionService)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var ctx = (Json.ObjectExpression)expression;

            //
            // Important! The type space needs to be rehydrated first because of its use by scope
            // tracking and label serialization.
            //
            var typeSpace = TypeSpace.FromJson(ctx.Members["Types"], typeResolutionService);

            var heap = default(Heap);

            if (ctx.Members.TryGetValue("Heap", out Json.Expression heapJson))
            {
                heap = Heap.FromJson(heapJson);
            }

            var scope = default(Scope);

            if (ctx.Members.TryGetValue("Globals", out Json.Expression globals))
            {
                scope = Scope.FromJson(globals, typeSpace);
            }

            var labels = default(Labels);

            if (ctx.Members.TryGetValue("Labels", out Json.Expression labelsJson))
            {
                labels = Labels.FromJson(labelsJson, typeSpace);
            }

            return(new ExpressionJsonSerializationContext(typeSpace, scope, heap, labels));
        }
Пример #11
0
 /// <summary>
 /// Gets an address from a JSON representation.
 /// </summary>
 /// <param name="address">JSON representation of an address.</param>
 /// <returns>Address in the specified JSON representation.</returns>
 private static int AddressFromJson(Json.Expression address)
 {
     return(int.Parse((string)((Json.ConstantExpression)address).Value, CultureInfo.InvariantCulture));
 }
Пример #12
0
 /// <summary>
 /// Adds the specified object instance at the specified address.
 /// This method can only be used during deserialization.
 /// </summary>
 /// <param name="address">Address to store the object instance at.</param>
 /// <param name="item">Object instance to store at the specified address.</param>
 public void Add(Json.Expression address, object item)
 {
     _deserializedObjects[AddressFromJson(address)] = item;
 }
Пример #13
0
        /// <summary>
        /// Restores scope tracking information from the given JSON representation.
        /// </summary>
        /// <param name="json">JSON representation of scope tracking information.</param>
        /// <param name="types">Type space used to lookup referenced types.</param>
        /// <returns>Scope tracking instance used during deserialization.</returns>
        public static Scope FromJson(Json.Expression json, TypeSpace types)
        {
            var state = new DeserializationState(json, types);

            return(new Scope(state));
        }
Пример #14
0
        /// <summary>
        /// Gets a type space object from a JSON representation.
        /// </summary>
        /// <param name="expression">JSON representation of the type space.</param>
        /// <param name="typeResolutionService">Type resolution service. Can be null.</param>
        /// <returns>Type space for the given JSON representation.</returns>
        public static TypeSpace FromJson(Json.Expression expression, ITypeResolutionService typeResolutionService)
        {
            //
            // Referencing mscorlib for default lookups. See SimpleTypeDef.FromJson for the
            // special treatment of this assembly in order to shorten names in serialization
            // payload.
            //
            if (typeResolutionService != null)
            {
                typeResolutionService.ReferenceAssembly(typeof(int).Assembly.GetName() /* mscorlib */);
            }

            //
            // Inverse of ToJson.
            //
            var defs = ((Json.ArrayExpression)expression).Elements;

            //
            // First, get enough type reference objects to support the full range of ordinals.
            //
            var typeRefs = Enumerable.Range(0, defs.Count).Select(i => new TypeRef(i)).ToArray();

            //
            // Using a findRef delegate, we can now import the type definitions. Notice this
            // assumes that type references are in a fixed zero-based range.
            //
            var findRef  = new Func <Json.Expression, TypeRef>(r => typeRefs[TypeRef.FromJson(r).Ordinal]);
            var typeDefs = defs.Select(def => TypeDef.FromJson(def, findRef, typeResolutionService)).ToArray();

            //
            // Next, we associate all of the type references with their corresponding definition,
            // again based on ordinal number indexes.
            //
            var j = 0;

            foreach (var typeDef in typeDefs)
            {
                var typeRef = typeRefs[j++];
                typeRef.Definition = typeDef;
            }

            //
            // The first phase of defining the type space consists of compilation of the types,
            // resulting in recreation of structural types. Entries are added to the type def
            // table to allow for Lookup calls during deserialization of the expression tree.
            //
            var res             = new TypeSpace();
            var structuralTypes = new List <StructuralTypeDef>();

            foreach (var typeRef in typeRefs)
            {
                var def = typeRef.Definition;
                res._typeDefs[typeRef] = def;
                def.Compile(res._compiler, typeResolutionService);

                //
                // Structural types need a separate compilation stage in order to "freeze" the
                // reconstructed types. See comment below for more information.
                //
                if (def is StructuralTypeDef std)
                {
                    structuralTypes.Add(std);
                }
            }

            //
            // Second stage of compilation, triggering the CreateType on TypeBuilder to cause
            // final construction of the types.
            //
            foreach (var structuralType in structuralTypes)
            {
                structuralType.ToType(); // side-effect described above
            }

            //
            // The following piece of code can be re-enabled for debugging purposes in order to
            // see a Type-based index for type references. This is only needed for serialization,
            // so we eliminate this step for deserialization.
            //

            /*
             * foreach (var typeRef in typeRefs)
             * {
             *  var type = typeRef.Definition.ToType();
             *  res._typeRefs[type] = typeRef;
             * }
             */

            return(res);
        }
Пример #15
0
        /// <summary>
        /// Obtains a type reference object from a JSON representation.
        /// </summary>
        /// <param name="json">JSON representation of the type reference.</param>
        /// <returns>Type reference for the given JSON representation.</returns>
        public static TypeRef FromJson(Json.Expression json)
        {
            var ordinal = int.Parse((string)((Json.ConstantExpression)json).Value, CultureInfo.InvariantCulture);

            return(new TypeRef(ordinal));
        }
Пример #16
0
 /// <summary>
 /// Creates a new deserialization state object.
 /// </summary>
 /// <param name="globals">JSON representation of globals to make available.</param>
 /// <param name="types">Type space for lookup of types.</param>
 public DeserializationState(Json.Expression globals, TypeSpace types)
 {
     _environment = new Stack <DeserializationFrame>();
     _globals     = new DeserializationFrame(globals, types);
 }
Пример #17
0
 /// <summary>
 /// Creates a new label registration.
 /// </summary>
 /// <param name="target">Target label.</param>
 /// <param name="type">Type reference JSON representation for the target label type.</param>
 public LabelRegistration(LabelTarget target, Json.Expression type)
 {
     _target = target;
     _type   = type;
 }
Пример #18
0
 /// <summary>
 /// Gets an object from the heap at the specified address.
 /// </summary>
 /// <param name="address">Address of the object to retrieve.</param>
 /// <returns>Representation of the object at the specified address.</returns>
 public Json.Expression Get(Json.Expression address)
 {
     return(_objects[AddressFromJson(address)]);
 }
        /// <summary>
        /// Deserializes the given JSON representation into an expression tree object.
        /// </summary>
        /// <param name="input">JSON representation of an expression tree.</param>
        /// <returns>Expression tree represented by the specified JSON representation.</returns>
        public new Expression Deserialize(Json.Expression input)
        {
            var res = (Expression)base.Deserialize(input);

            return(res);
        }