public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info) { if (source.Dimensions != null) { string typeName = this.nameLookup.Lookup(source.Type, true); info.Interop = new TypedDefinition { Name = source.Name, Type = typeName }; if (source.Dimensions.Length == 2) { info.Public.Add(new TypedDefinition { Name = source.Name, Type = "ArrayProxy<string>" + (context.IsMethod ? "?" : ""), DefaultValue = source.IsOptional ? Null : null, Comment = this.commentGenerator.Lookup(context.VkName, source.VkName) }); info.MarshalTo.Add((getTarget, getValue) => { return(new AssignAction { ValueExpression = StaticCall("Interop.HeapUtil", "MarshalTo", getValue(source.Name)), TargetExpression = getTarget(source.Name), MemberType = this.nameLookup.Lookup(source.Type, false), Type = AssignActionType.Assign }); }); } else if (source.Dimensions.Length == 1) { switch (source.Dimensions[0].Type) { case LenType.NullTerminated: info.Public.Add(new TypedDefinition { Name = source.Name, Comment = this.commentGenerator.Lookup(context.VkName, source.VkName), Type = "string" }); info.InteropFullType = typeName; info.MarshalTo.Add((getTarget, getValue) => new AssignAction { ValueExpression = StaticCall("Interop.HeapUtil", "MarshalTo", getValue(source.Name)), TargetExpression = getTarget(source.Name), MemberType = this.nameLookup.Lookup(source.Type, false), Type = AssignActionType.Assign }); info.MarshalFrom.Add((getTarget, getValue) => new AssignAction { ValueExpression = StaticCall("Interop.HeapUtil", "MarshalStringFrom", getValue(source.Name)), TargetExpression = getTarget(source.Name), MemberType = this.nameLookup.Lookup(source.Type, false), Type = AssignActionType.Assign }); break; case LenType.Expression: var elementType = source.Type.Deref(); bool isDoubleMarshalled = false; string semiMarshalledName = "semiMarshalled" + source.Name.FirstToUpper(); string semiMarshalType = this.nameLookup.Lookup(elementType, true); if (elementType.PointerType.IsPointer()) { info.MarshalTo.Add((getTarget, getValue) => new DeclarationAction { MemberType = semiMarshalType, MemberName = semiMarshalledName }); isDoubleMarshalled = true; elementType = elementType.Deref(); } if (elementType.VkName == "void") { elementType.VkName = "uint8_t"; } var marshalling = this.marshallingRules.ApplyFirst(elementType); info.InteropFullType = marshalling.InteropType; if (source.Type.PointerType.IsPointer()) { info.InteropFullType += new string('*', source.Type.PointerType.GetPointerCount()); } string arrayType = $"{marshalling.MemberType}[]"; if (context.IsMethod) { info.Public.Add(new TypedDefinition { Name = source.Name, Type = $"ArrayProxy<{marshalling.MemberType}>?", Comment = new[] { "" }.ToList(), DefaultValue = source.IsOptional ? Null : null }); info.ReturnType = arrayType; info.MarshalTo.Add((getTarget, getValue) => { var proxyValue = Member(getValue(source.Name), "Value"); var isNullOptional = new OptionalAction { CheckExpression = Call(getValue(source.Name), "IsNull") }; var isSingleOptional = new OptionalAction { CheckExpression = IsEqual(Member(proxyValue, "Contents"), EnumField("ProxyContents", "Single")) }; var loopAssign = new AssignAction { TargetExpression = isDoubleMarshalled ? Variable(semiMarshalledName) : getTarget(source.Name), MemberType = marshalling.InteropType, IsLoop = true, IndexName = "index", Type = marshalling.MarshalToActionType, LengthExpression = StaticCall("Interop.HeapUtil", "GetLength", proxyValue), ValueExpression = marshalling.BuildMarshalToValueExpression(Index(proxyValue, Variable("index")), context.GetHandle) }; isSingleOptional.Actions.Add(new AssignAction { Type = AssignActionType.Alloc, TargetExpression = isDoubleMarshalled ? Variable(semiMarshalledName) : getTarget(source.Name), MemberType = marshalling.InteropType }); isSingleOptional.Actions.Add(new AssignAction { Type = marshalling.MarshalToActionType, MemberType = marshalling.InteropType, ValueExpression = marshalling.BuildMarshalToValueExpression(Call(proxyValue, "GetSingleValue"), context.GetHandle), TargetExpression = Deref(Cast(marshalling.InteropType + "*", isDoubleMarshalled ? Variable(semiMarshalledName) : getTarget(source.Name))) }); isSingleOptional.ElseActions.Add(loopAssign); if (isDoubleMarshalled) { isSingleOptional.ElseActions.Add(new AssignAction { TargetExpression = getTarget(source.Name), MemberType = semiMarshalType, IsLoop = true, IndexName = "index", Type = AssignActionType.Assign, LengthExpression = StaticCall("Interop.HeapUtil", "GetLength", proxyValue), ValueExpression = AddressOf(Index(Variable(semiMarshalledName), Variable("index"))), FieldPointerName = "marshalledFieldPointer" }); } isNullOptional.Actions.Add(new AssignAction { TargetExpression = getTarget(source.Name), ValueExpression = Null }); isNullOptional.ElseActions.Add(isSingleOptional); return(isNullOptional); }); } else { info.Public.Add(new TypedDefinition { Name = source.Name, Comment = this.commentGenerator.Lookup(context.VkName, source.VkName), Type = arrayType }); info.MarshalTo.Add((getTarget, getValue) => new AssignAction { TargetExpression = isDoubleMarshalled ? Variable(semiMarshalledName) : getTarget(source.Name), MemberType = marshalling.InteropType, IsLoop = true, IndexName = "index", Type = marshalling.MarshalToActionType, NullCheckExpression = IsNotEqual(getValue(source.Name), Null), LengthExpression = Member(getValue(source.Name), "Length"), ValueExpression = marshalling.BuildMarshalToValueExpression(Index(getValue(source.Name), Variable("index")), context.GetHandle) }); if (isDoubleMarshalled) { info.MarshalTo.Add((getTarget, getValue) => new AssignAction { TargetExpression = getTarget(source.Name), MemberType = semiMarshalType, IsLoop = true, IndexName = "index", Type = AssignActionType.Assign, NullCheckExpression = IsNotEqual(getValue(source.Name), Null), LengthExpression = Member(getValue(source.Name), "Length"), ValueExpression = AddressOf(Index(Variable(semiMarshalledName), Variable("index"))) }); } } Func <Func <string, Action <ExpressionBuilder> >, Action <ExpressionBuilder> > lenValue = null; if (source.Dimensions[0].Value is LenExpressionToken lenToken) { lenValue = getValue => getValue(others.Single(x => x.VkName == lenToken.Value).Name); } else { lenValue = getValue => this.expressionBuilder.Build(source.Dimensions[0].Value, x => others.Single(y => y.VkName == x)); } info.MarshalFrom.Add((getTarget, getValue) => new AssignAction { TargetExpression = getTarget(source.Name), MemberType = marshalling.MemberType, IsLoop = true, IsArray = true, IndexName = "index", Type = marshalling.MarshalFromActionType, NullCheckExpression = IsNotEqual(getValue(source.Name), Null), LengthExpression = lenValue(getValue), ValueExpression = marshalling.BuildMarshalFromValueExpression(Index(getValue(source.Name), Variable("index")), context.GetHandle) }); break; } } return(true); } else { return(false); } }
public static void SetAssignProperty(AssignAction assignAction, string property) => assignAction.Property = property;
public static void SetAssignExpression(AssignAction assignAction, string expression) => assignAction.Expression = expression;
public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info) { var marshalling = this.marshallingRules.ApplyFirst(source.Type); bool isOptional = source.IsOptional && this.typeData[source.Type.VkName].Pattern != TypePattern.Delegate && this.typeData[source.Type.VkName].Pattern != TypePattern.Handle; string memberType = marshalling.MemberType + (isOptional ? "?" : ""); info.Public.Add(new TypedDefinition { Name = source.Name, Comment = this.commentGenerator.Lookup(context.VkName, source.VkName), Type = memberType, DefaultValue = isOptional ? Default(memberType) : null }); string typeName = this.nameLookup.Lookup(source.Type, true); info.Interop = new TypedDefinition { Name = source.Name, Type = typeName }; info.InteropFullType = marshalling.InteropType; if (marshalling.HandleType != null) { info.HandleLookup.Add((marshalling.HandleType, getValue => getValue(source.Name))); } if (source.Type.PointerType.IsPointer()) { info.InteropFullType += new string('*', source.Type.PointerType.GetPointerCount()); } info.MarshalTo.Add((getTarget, getValue) => { var valueExpression = isOptional ? marshalling.BuildMarshalToValueExpression(Member(getValue(source.Name), "Value"), context.GetHandle) : marshalling.BuildMarshalToValueExpression(getValue(source.Name), context.GetHandle); var assignment = new AssignAction { ValueExpression = valueExpression, TargetExpression = getTarget(source.Name), MemberType = marshalling.InteropType, Type = marshalling.MarshalToActionType }; if (isOptional) { var result = new OptionalAction { CheckExpression = IsNotEqual(getValue(source.Name), Null) }; result.Actions.Add(assignment); result.ElseActions.Add(new AssignAction { Type = AssignActionType.Assign, TargetExpression = getTarget(source.Name), ValueExpression = Default(info.InteropFullType) }); return(result); } else { return(assignment); } }); bool optionalMarshalFrom = isOptional && source.Type.PointerType != PointerType.Value; info.MarshalFrom.Add((getTarget, getValue) => { var valueExpression = marshalling.BuildMarshalFromValueExpression(getValue(source.Name), context.GetHandle); var assignment = new AssignAction { ValueExpression = valueExpression, TargetExpression = getTarget(source.Name), MemberType = marshalling.MemberType, Type = marshalling.MarshalFromActionType }; if (optionalMarshalFrom) { var result = new OptionalAction { CheckExpression = IsNotEqual(getValue(source.Name), Null) }; result.Actions.Add(assignment); result.ElseActions.Add(new AssignAction { Type = AssignActionType.Assign, TargetExpression = getTarget(source.Name), ValueExpression = Null }); return(result); } else { return(assignment); } }); return(true); }