public static MemberDef FromJson(DeserializationDomain domain, Json.Expression member) { if (member is not Json.ArrayExpression info) { throw new BonsaiParseException("Expected a JSON array for a member definition.", member); } if (info.ElementCount < 1) { throw new BonsaiParseException("Expected at least 1 JSON array element for a member definition.", member); } var type = info.GetElement(0); if (type.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string in 'node[0]' for the member type discriminator.", member); } var kind = (string)((Json.ConstantExpression)type).Value; return(kind switch { Discriminators.MemberInfo.Constructor => GetConstructorDef(domain, info), Discriminators.MemberInfo.Field => GetFieldDef(domain, info), Discriminators.MemberInfo.Property => GetPropertyDef(domain, info), Discriminators.MemberInfo.SimpleMethod => GetSimpleMethodDef(domain, info), Discriminators.MemberInfo.OpenGenericMethod => GetOpenGenericMethodDef(domain, info), Discriminators.MemberInfo.ClosedGenericMethod => GetClosedGenericMethodDef(info), _ => throw new BonsaiParseException(string.Format(CultureInfo.InvariantCulture, "Unexpected member type discriminator '{0}'.", kind), member), });
private object DeserializeConstant(Json.Expression json, Type type) { object result; var stream = new MemoryStream(); try { using var writer = new StreamWriter(stream); stream = null; var deserialize = _genericDeserialize.MakeGenericMethod(new[] { type }); writer.Write(json.ToString()); writer.Flush(); ((MemoryStream)writer.BaseStream).Position = 0; result = deserialize.Invoke(_dataSerializer, new[] { writer.BaseStream as MemoryStream }); } finally { stream?.Dispose(); } return(result); }
public static TypeDef FromJson(DeserializationDomain domain, Json.Expression expression) { if (expression is not Json.ArrayExpression type) { throw new BonsaiParseException("Expected a JSON array containing a type definition.", expression); } if (type.ElementCount == 0) { throw new BonsaiParseException("Expected at least one JSON array element containing a type discriminator.", expression); } var kind = type.GetElement(0); if (kind.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string at 'node[0]' containing a type discriminator.", expression); } var typeDiscriminator = (string)((Json.ConstantExpression)kind).Value; return(typeDiscriminator switch { Discriminators.Type.Simple => SimpleTypeDef.FromJson(type), Discriminators.Type.Generic => GenericTypeDef.FromJson(type), Discriminators.Type.Array => ArrayTypeDef.FromJson(type), Discriminators.Type.Anonymous => AnonymousStructuralTypeDef.FromJson(type), Discriminators.Type.Record => RecordStructuralTypeDef.FromJson(domain, type), _ => throw new BonsaiParseException(string.Format(CultureInfo.InvariantCulture, "Unexpected type discriminator '{0}' at 'node[0]'.", typeDiscriminator), expression), });
public static RecordStructuralTypeMember FromJson(Json.Expression expression) { if (expression is not Json.ArrayExpression array) { throw new BonsaiParseException("Expected a JSON array for a record structural type member definition.", expression); } if (array.ElementCount != 2) { throw new BonsaiParseException("Expected 2 JSON array elements for a record structural type member definition.", expression); } var nameExpr = array.GetElement(0); if (nameExpr.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string in 'node[0]' for the name of a record structural type member definition.", expression); } var name = (string)((Json.ConstantExpression)nameExpr).Value; var type = TypeRef.FromJson(array.GetElement(1)); return(new RecordStructuralTypeMember { Name = name, Type = type }); }
private Json.Expression[] EnumerateLabelTargets() { var labels = new Json.Expression[_labelTargetsDef.Count]; var i = 0; foreach (var labelTarget in _labelTargetsDef) { if (labelTarget.Name == null) { labels[i] = Json.Expression.Array( _domain.AddType(labelTarget.Type).ToJson() ); } else { labels[i] = Json.Expression.Array( _domain.AddType(labelTarget.Type).ToJson(), Json.Expression.String(labelTarget.Name) ); } i++; } return(labels); }
public DeserializationDomain(Json.Expression json) { if (json is not Json.ObjectExpression obj) { throw new BonsaiParseException("Expected a JSON object containing the context object used by the Bonsai representation of an expression.", json); } if (obj.Members.TryGetValue("Version", out Json.Expression version)) { Version = DeserializeVersion(version); } if (!obj.Members.TryGetValue("Assemblies", out Json.Expression assemblies)) { throw new BonsaiParseException("Expected a JSON object property 'node.Assemblies' containing the assembly table.", json); } DeserializeAssemblies(assemblies, ref _assemblyDefs); if (!obj.Members.TryGetValue("Types", out Json.Expression types)) { throw new BonsaiParseException("Expected a JSON object property 'node.Types' containing the type table.", json); } DeserializeTypes(types, ref _typeDefs); if (obj.Members.TryGetValue("Members", out Json.Expression members)) { DeserializeMembers(members, ref _memberDefs); } else { _memberDefs = Array.Empty <MemberDef>(); } }
public TypeSlim GetType(Json.Expression expression, params TypeSlim[] genericArguments) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (expression.NodeType != Json.ExpressionType.Number) { throw new BonsaiParseException("Expected a JSON number for the type table index of the type to look up.", expression); } var index = Helpers.ParseInt32((string)((Json.ConstantExpression)expression).Value); if (index < 0) { return(genericArguments[-index - 1]); } if (index >= _typeDefs.Length) { throw new BonsaiParseException(string.Format(CultureInfo.InvariantCulture, "A type with index {0} was not found in the type table.", index), expression); } var def = _typeDefs[index]; return(def.ToType(this, genericArguments)); }
/// <summary> /// Deserializes a Bonsai expression. /// </summary> /// <param name="expression">Bonsai expression to deserialize.</param> /// <returns>Slim expression represented by the given Bonsai.</returns> private ExpressionSlim JsonDeserialize(Json.Expression expression) { if (expression.NodeType == Json.ExpressionType.Null) { return(null); } if (expression is not Json.ObjectExpression obj) { throw new InvalidOperationException("Expected JSON object expression."); } if (!obj.Members.TryGetValue("Context", out Json.Expression context)) { throw new InvalidOperationException("Context not found."); } if (!obj.Members.TryGetValue("Expression", out Json.Expression expr)) { throw new InvalidOperationException("Expression not found."); } if (expr.NodeType == Json.ExpressionType.Null) { return(null); } var deserializationState = new DeserializationState(context, _version); var visitor = new DeserializerImpl(deserializationState, GetConstantDeserializerDelegate); return(visitor.Visit(expr)); }
public override Json.Expression ToJson(SerializationDomain domain) { if (domain.IsV08) { throw new NotSupportedException("Record types can only be serialized in Bonsai v0.9 or later."); } var count = _members.Length; var members = new Json.Expression[count]; for (var i = 0; i < count; i++) { members[i] = _members[i].ToJson(domain); } if (!_hasValueEqualitySemantics) { return(Json.Expression.Array( Discriminators.Type.RecordDiscriminator, Json.Expression.Array(members), Json.Expression.Boolean(false) )); } else { return(Json.Expression.Array( Discriminators.Type.RecordDiscriminator, Json.Expression.Array(members) )); } }
private static void DeserializeAssemblies(Json.Expression assemblies, ref AssemblySlim[] assemblyDefs) { // // TODO: confirm this behavior, technically "optional" in Bonsai spec, so value could be null. // if (assemblies is not Json.ArrayExpression assemblyTable) { throw new BonsaiParseException("Expected a JSON array containing the assembly table.", assemblies); } var n = assemblyTable.ElementCount; assemblyDefs = new AssemblySlim[n]; for (var i = 0; i < n; i++) { var assembly = assemblyTable.GetElement(i); if (assembly.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string containing the an assembly name.", assembly); } var asm = new AssemblySlim((string)((Json.ConstantExpression)assembly).Value); assemblyDefs[i] = asm; } }
private Json.Expression[] EnumerateGlobals() { var globals = new Json.Expression[_globalsDef.Count]; var i = 0; foreach (var global in _globalsDef) { if (global.Name == null) { globals[i] = Json.Expression.Array( _domain.AddType(global.Type).ToJson() ); } else { globals[i] = Json.Expression.Array( _domain.AddType(global.Type).ToJson(), Json.Expression.String(global.Name) ); } i++; } return(globals); }
public DeserializationState(Json.Expression state, Version version) { _domain = new DeserializationDomain(state); _params = new Stack <ParameterExpression[]>(); _globals = GetGlobals(state); _labelTagets = GetLabelTargets(state); Debug.Assert(_domain.SupportsVersion(version)); }
private static Version DeserializeVersion(Json.Expression version) { if (version.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string containing the Bonsai version.", version); } return(new Version((string)((Json.ConstantExpression)version).Value)); }
public override ExpressionSlim VisitArray(Json.ArrayExpression node) { var newElements = new Json.Expression[node.Elements.Count]; node.Elements.CopyTo(newElements, 0); newElements[0] = Json.Expression.Null(); var newNode = Json.Expression.Array(newElements); return(base.VisitArray(newNode)); }
public static TypeRef FromJson(Json.Expression expression) { if (expression.NodeType != Json.ExpressionType.Number) { throw new BonsaiParseException("Expected a JSON number for a type table index used in a type reference.", expression); } var index = Helpers.ParseInt32((string)((Json.ConstantExpression)expression).Value); return(new SimpleTypeRef(index)); }
public LabelTarget GetLabelTarget(Json.Expression expression) { if (expression is not Json.ConstantExpression indexJson || !int.TryParse(indexJson.Value.ToString(), out int index)) { throw new BonsaiParseException("Expected a JSON number containing a label target reference.", expression); } if (_labelTagets == null || index < 0 || index >= _labelTagets.Length) { throw new BonsaiParseException(string.Format(CultureInfo.InvariantCulture, "A label target with index {0} is not defined.", index), expression); } return(_labelTagets[index]); }
private LabelTarget[] GetLabelTargets(Json.Expression state) { if (state is not Json.ObjectExpression obj) { throw new BonsaiParseException("Expected JSON object expression for the Context property of the Bonsai expression.", state); } if (obj.Members.TryGetValue("LabelTargets", out Json.Expression res)) { return(DeserializeLabelTargets(res)); } return(null); }
public override Json.Expression ToJson(SerializationDomain domain) { var declType = DeclaringType.ToJson(); if (!domain.IsV08) { var indexParameterTypes = _property.IndexParameterTypes; var indexParameterCount = indexParameterTypes.Count; var indexParameterList = new Json.Expression[indexParameterCount]; for (var i = 0; i < indexParameterCount; i++) { indexParameterList[i] = domain.AddType(indexParameterTypes[i]).ToJson(); } var indexParameters = Json.Expression.Array(indexParameterList); if (_property.PropertyType != null) { var propType = domain.AddType(_property.PropertyType).ToJson(); return(Json.Expression.Array( Discriminators.MemberInfo.PropertyDiscriminator, declType, Json.Expression.String(_property.Name), indexParameters, propType )); } else { return(Json.Expression.Array( Discriminators.MemberInfo.PropertyDiscriminator, declType, Json.Expression.String(_property.Name), indexParameters )); } } else { return(Json.Expression.Array( Discriminators.MemberInfo.PropertyDiscriminator, declType, Json.Expression.String(_property.Name) )); } }
/// <summary> /// Deserializes a Bonsai expression. /// </summary> /// <param name="expression">Bonsai expression to deserialize.</param> /// <returns>Slim expression represented by the given Bonsai.</returns> public ExpressionSlim Deserialize(Json.Expression expression) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } Json.Expression expr; if (_mergeContext && _deserializationState != null) { expr = expression; } else { if (expression.NodeType == Json.ExpressionType.Null) { return(null); } if (expression is not Json.ObjectExpression obj) { throw new BonsaiParseException("Expected a JSON object containing the Bonsai representation of an expression.", expression); } if (!obj.Members.TryGetValue("Context", out Json.Expression context)) { throw new BonsaiParseException("Expected a JSON object property 'node.Context' containing the context object.", expression); } if (!obj.Members.TryGetValue("Expression", out expr)) { throw new BonsaiParseException("Expected a JSON object property 'node.Expression' containing the expression tree.", expression); } _deserializationState = new DeserializationState(context, _version); } if (expr.NodeType == Json.ExpressionType.Null) { return(null); } var visitor = new DeserializerImpl(_deserializationState, _reduceFactory); return(visitor.Visit(expr)); }
public override Json.Expression ToJson(SerializationDomain domain) { var count = _genericArguments.Length; var arguments = new Json.Expression[count]; for (var i = 0; i < count; i++) { arguments[i] = _genericArguments[i].ToJson(); } return(Json.Expression.Array( Discriminators.MemberInfo.ClosedGenericMethodDiscriminator, _genericMethodDefinition, Json.Expression.Array(arguments) )); }
public override Json.Expression ToJson(SerializationDomain domain) { var count = _parameters.Length; var parameters = new Json.Expression[count]; for (var i = 0; i < count; i++) { parameters[i] = _parameters[i].ToJson(); } return(Json.Expression.Array( Discriminators.MemberInfo.ConstructorDiscriminator, DeclaringType.ToJson(), Json.Expression.Array(parameters) )); }
public override Json.Expression ToJson(SerializationDomain domain) { var n = _members.Length; var args = new Json.Expression[n + 1]; args[0] = Discriminators.Type.AnonymousDiscriminator; for (var i = 0; i < n; i++) { args[i + 1] = _members[i].ToJson(domain); } return(Json.Expression.Array( args )); }
public override Json.Expression ToJson(SerializationDomain domain) { var count = _genericTypeArguments.Length; var genericTypeArguments = new Json.Expression[count]; for (var i = 0; i < count; i++) { genericTypeArguments[i] = _genericTypeArguments[i].ToJson(); } return(Json.Expression.Array( Discriminators.Type.GenericDiscriminator, _genericTypeDefinition.ToJson(), Json.Expression.Array(genericTypeArguments) )); }
protected override Json.Expression MakeBinary(BinaryExpression node, Json.Expression left, Json.Expression conversion, Json.Expression right) { return(node.NodeType switch { ExpressionType.Add => VisitBinarySimple(node, Discriminators.Expression.PlusDiscriminator, left, right), ExpressionType.AddChecked => VisitBinarySimple(node, Discriminators.Expression.PlusDollarDiscriminator, left, right), ExpressionType.Subtract => VisitBinarySimple(node, Discriminators.Expression.MinusDiscriminator, left, right), ExpressionType.SubtractChecked => VisitBinarySimple(node, Discriminators.Expression.MinusDollarDiscriminator, left, right), ExpressionType.Multiply => VisitBinarySimple(node, Discriminators.Expression.MultiplyDiscriminator, left, right), ExpressionType.MultiplyChecked => VisitBinarySimple(node, Discriminators.Expression.MultiplyCheckedDiscriminator, left, right), ExpressionType.Divide => VisitBinarySimple(node, Discriminators.Expression.DivideDiscriminator, left, right), ExpressionType.Modulo => VisitBinarySimple(node, Discriminators.Expression.ModuloDiscriminator, left, right), ExpressionType.Power => VisitBinarySimple(node, Discriminators.Expression.PowerDiscriminator, left, right), ExpressionType.RightShift => VisitBinarySimple(node, Discriminators.Expression.RightShiftDiscriminator, left, right), ExpressionType.LeftShift => VisitBinarySimple(node, Discriminators.Expression.LeftShiftDiscriminator, left, right), ExpressionType.LessThan => VisitBinaryComparison(node, Discriminators.Expression.LessThanDiscriminator, left, right), ExpressionType.LessThanOrEqual => VisitBinaryComparison(node, Discriminators.Expression.LessThanOrEqualDiscriminator, left, right), ExpressionType.GreaterThan => VisitBinaryComparison(node, Discriminators.Expression.GreaterThanDiscriminator, left, right), ExpressionType.GreaterThanOrEqual => VisitBinaryComparison(node, Discriminators.Expression.GreaterThanOrEqualDiscriminator, left, right), ExpressionType.Equal => VisitBinaryComparison(node, Discriminators.Expression.EqualDiscriminator, left, right), ExpressionType.NotEqual => VisitBinaryComparison(node, Discriminators.Expression.NotEqualDiscriminator, left, right), ExpressionType.And => VisitBinarySimple(node, Discriminators.Expression.AndDiscriminator, left, right), ExpressionType.AndAlso => VisitBinarySimple(node, Discriminators.Expression.AndAlsoDiscriminator, left, right), ExpressionType.Or => VisitBinarySimple(node, Discriminators.Expression.OrDiscriminator, left, right), ExpressionType.OrElse => VisitBinarySimple(node, Discriminators.Expression.OrElseDiscriminator, left, right), ExpressionType.ExclusiveOr => VisitBinarySimple(node, Discriminators.Expression.ExclusiveOrDiscriminator, left, right), ExpressionType.Coalesce => VisitBinaryCoalesce(node, left, conversion, right), ExpressionType.ArrayIndex => VisitBinarySimple(node, Discriminators.Expression.ArrayIndexDiscriminator, left, right), ExpressionType.Assign => VisitBinarySimple(node, Discriminators.Expression.AssignDiscriminator, left, right), ExpressionType.AddAssign => VisitBinaryOpAssign(node, Discriminators.Expression.AddAssignDiscriminator, left, conversion, right), ExpressionType.AddAssignChecked => VisitBinaryOpAssign(node, Discriminators.Expression.AddAssignCheckedDiscriminator, left, conversion, right), ExpressionType.AndAssign => VisitBinaryOpAssign(node, Discriminators.Expression.AndAssignDiscriminator, left, conversion, right), ExpressionType.DivideAssign => VisitBinaryOpAssign(node, Discriminators.Expression.DivideAssignDiscriminator, left, conversion, right), ExpressionType.ExclusiveOrAssign => VisitBinaryOpAssign(node, Discriminators.Expression.ExclusiveOrAssignDiscriminator, left, conversion, right), ExpressionType.LeftShiftAssign => VisitBinaryOpAssign(node, Discriminators.Expression.LeftShiftAssignDiscriminator, left, conversion, right), ExpressionType.ModuloAssign => VisitBinaryOpAssign(node, Discriminators.Expression.ModuloAssignDiscriminator, left, conversion, right), ExpressionType.MultiplyAssign => VisitBinaryOpAssign(node, Discriminators.Expression.MultiplyAssignDiscriminator, left, conversion, right), ExpressionType.MultiplyAssignChecked => VisitBinaryOpAssign(node, Discriminators.Expression.MultiplyAssignCheckedDiscriminator, left, conversion, right), ExpressionType.OrAssign => VisitBinaryOpAssign(node, Discriminators.Expression.OrAssignDiscriminator, left, conversion, right), ExpressionType.PowerAssign => VisitBinaryOpAssign(node, Discriminators.Expression.PowerAssignDiscriminator, left, conversion, right), ExpressionType.RightShiftAssign => VisitBinaryOpAssign(node, Discriminators.Expression.RightShiftAssignDiscriminator, left, conversion, right), ExpressionType.SubtractAssign => VisitBinaryOpAssign(node, Discriminators.Expression.SubtractAssignDiscriminator, left, conversion, right), ExpressionType.SubtractAssignChecked => VisitBinaryOpAssign(node, Discriminators.Expression.SubtractAssignCheckedDiscriminator, left, conversion, right), _ => throw new NotImplementedException(), });
public override Json.Expression ToJson(SerializationDomain domain) { var count = Parameters.Length; var parameters = new Json.Expression[count]; for (var i = 0; i < count; i++) { parameters[i] = Parameters[i].ToJson(); } return(Json.Expression.Array( Discriminators.MemberInfo.SimpleMethodDiscriminator, DeclaringType.ToJson(), Json.Expression.String(((SimpleMethodInfoSlim)Method).Name), Json.Expression.Array(parameters), ReturnType.ToJson() )); }
public static AnonymousStructuralTypeMember FromJson(Json.Expression expression) { if (expression is not Json.ArrayExpression array) { throw new BonsaiParseException("Expected a JSON array for an anonymous structural type member definition.", expression); } var count = array.ElementCount; if (count is not 2 and not 3) { throw new BonsaiParseException("Expected 2 or 3 JSON array elements for an anonymous structural type member definition.", expression); } var nameExpr = array.GetElement(0); if (nameExpr.NodeType != Json.ExpressionType.String) { throw new BonsaiParseException("Expected a JSON string in 'node[0]' for the name of an anonymous structural type member definition.", expression); } var name = (string)((Json.ConstantExpression)nameExpr).Value; var type = TypeRef.FromJson(array.GetElement(1)); var isKey = true; if (count == 3) { var isKeyExpr = array.GetElement(2); if (isKeyExpr.NodeType != Json.ExpressionType.Boolean) { throw new BonsaiParseException("Expected a JSON Boolean in 'node[2]' for IsKey flag of an anonymous structural type member definition.", expression); } isKey = (bool)((Json.ConstantExpression)isKeyExpr).Value; } return(new AnonymousStructuralTypeMember { Name = name, Type = type, IsKey = isKey }); }
private ParameterExpression[] GetScope(int index, Json.Expression expression) { if (index >= 0) { var idx = index; using var e = _params.GetEnumerator(); while (e.MoveNext()) { if (idx == 0) { return(e.Current); } idx--; } } throw new BonsaiParseException(string.Format(CultureInfo.InvariantCulture, "A scope with index {0} is invalid at the current scope depth in the expression.", index), expression); }
private ParameterExpression[] DeserializeGlobals(Json.Expression globals) { if (globals is not Json.ArrayExpression globalTable) { throw new BonsaiParseException("Expected JSON array expression for the Globals property of the Bonsai expression context.", globals); } var n = globalTable.ElementCount; var d = new ParameterExpression[n]; for (var i = 0; i < n; i++) { var globalRow = globalTable.GetElement(i); if (globalRow is not Json.ArrayExpression globalJson) { throw new BonsaiParseException("Expected JSON array expression for the declaration of a global 'Parameter' node.", globalRow); } var count = globalJson.ElementCount; if (count is not 1 and not 2) { throw new BonsaiParseException("Expected 1 or 2 JSON array elements for the type reference and an optional name of a global 'Parameter' expression node.", globalRow); } var parameterType = _domain.GetType(globalJson.GetElement(0)); var parameterName = default(string); if (count == 2) { parameterName = ((Json.ConstantExpression)globalJson.GetElement(1)).Value.ToString(); } d[i] = Expression.Parameter(parameterType, parameterName); } return(d); }
private LabelTarget[] DeserializeLabelTargets(Json.Expression labelTargets) { if (labelTargets is not Json.ArrayExpression labelTable) { throw new BonsaiParseException("Expected JSON array expression for the LabelTargets property of the Bonsai expression context.", labelTargets); } var n = labelTable.ElementCount; var d = new LabelTarget[n]; for (var i = 0; i < n; i++) { var labelTargetRow = labelTable.GetElement(i); if (labelTargetRow is not Json.ArrayExpression labelTargetJson) { throw new BonsaiParseException("Expected JSON array expression for the declaration of a 'LabelTarget' node.", labelTargetRow); } var count = labelTargetJson.ElementCount; if (count is not 1 and not 2) { throw new BonsaiParseException("Expected 1 or 2 JSON array elements for the type reference and an optional name of a 'LabelTarget' node.", labelTargetRow); } var labelTargetType = _domain.GetType(labelTargetJson.GetElement(0)); var labelTargetName = default(string); if (count == 2) { labelTargetName = ((Json.ConstantExpression)labelTargetJson.GetElement(1)).Value.ToString(); } d[i] = Expression.Label(labelTargetType, labelTargetName); } return(d); }
private void DeserializeMembers(Json.Expression members, ref MemberDef[] memberDefs) { // // TODO: confirm this behavior, technically "optional" in Bonsai spec, so value could be null. // if (members is not Json.ArrayExpression memberTable) { throw new BonsaiParseException("Expected a JSON array containing the members table.", members); } var n = memberTable.ElementCount; memberDefs = new MemberDef[n]; for (var i = 0; i < n; i++) { var member = memberTable.GetElement(i); var memberDef = MemberDef.FromJson(this, member); memberDefs[i] = memberDef; } }