/// <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); }
/// <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)); }
/// <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) )); }
/// <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); }
/// <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); }
/// <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)); } }
/// <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 ); } }
/// <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)); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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; }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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; }
/// <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); }