Пример #1
0
        /// <summary>
        /// Gets the translated code for the grammar structure.
        /// </summary>
        /// <returns>The translated code for the grammar structure.</returns>
        public override object Translate(TranslationContext context)
        {
            ITypedDeclaration value = GetDeclaration(context);

            switch (value)
            {
            case null:
                // Error already processed
                return(null);

            case GlobalListDeclaration _:
                return(new Block(BlockSpecs.GetItemOfList, Index.Balance().Translate(context), value.Name));

            case StackValue scopedArray:
                if (scopedArray.StackSpace == 1)
                {
                    return(scopedArray.CreateArrayLookup(Index.Balance().Translate(context)));
                }

                context.ErrorList.Add(new CompilerError($"'{value.Name}' is not an array",
                                                        ErrorType.ImproperUsage, ErrorToken, FileName));
                return(null);

            default:
                context.ErrorList.Add(new CompilerError($"'{value.Name}' is not an array",
                                                        ErrorType.ImproperUsage, ErrorToken, FileName));
                return(null);
            }
        }
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Name == "Next")
            {
                info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                {
                    ValueExpression  = Null,
                    TargetExpression = getTarget(source.Name)
                });

                string typeName = this.nameLookup.Lookup(source.Type, true);

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #3
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.FixedValue != null)
            {
                var enumInfo     = this.enumLookup[source.FixedValue];
                var enumTypeName = this.nameLookup.Lookup(enumInfo.TypeVkName);

                info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                {
                    ValueExpression  = EnumField(enumTypeName, enumInfo.FieldName),
                    TargetExpression = getTarget(source.Name)
                });

                string typeName = this.nameLookup.Lookup(source.Type, true);

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #4
0
 /// <summary>
 /// Creates a new instance of the <see cref="LookupExpression"/> class.
 /// </summary>
 /// <param name="variable">The variable being looked up.</param>
 /// <param name="fileName">The name of the file.</param>
 /// <param name="errorToken">The token to report any compiler errors to.</param>
 public LookupExpression(ITypedDeclaration variable, string fileName, IToken errorToken)
 {
     _variable       = variable;
     _identifierName = variable.Name;
     FileName        = fileName;
     ErrorToken      = errorToken;
 }
Пример #5
0
        /// <summary>
        /// Gets the translated code for the grammar structure.
        /// </summary>
        /// <returns>The translated code for the grammar structure.</returns>
        public virtual object Translate(TranslationContext context)
        {
            ITypedDeclaration variable = GetDeclaration(context);

            switch (variable)
            {
            case null:
                // Error already processed
                return(null);

            case StackValue stackValue:
                return(stackValue.CreateVariableLookup());

            case ParamDeclaration _:
                return(new Block(BlockSpecs.GetParameter, variable.Name));

            case GlobalVarDeclaration _:
                return(new Block(BlockSpecs.GetVariable, variable.Name));

            case ConstDeclaration constDeclaration:
                return(constDeclaration.Value.Value);

            default:
                context.ErrorList.Add(new CompilerError($"'{_identifierName}' is not a variable",
                                                        ErrorType.ImproperUsage, ErrorToken, FileName));
                return(null);
            }
        }
Пример #6
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Name.EndsWith("Version") && source.Type.VkName.StartsWith("uint32"))
            {
                info.Public.Add(new TypedDefinition
                {
                    Name = source.Name,
                    Type = "Version"
                });

                info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                {
                    ValueExpression  = Cast("Version", getValue(source.Name)),
                    TargetExpression = getTarget(source.Name),
                });

                string typeName = this.nameLookup.Lookup(source.Type, true);

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #7
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Name == "Next")
            {
                if (context.IsMethod)
                {
                    var variableName = (context.VkName + "NextPointer").FirstToLower();

                    info.MarshalTo.Add((getTarget, getValue) => new DeclarationAction
                    {
                        MemberType = "void*",
                        MemberName = variableName
                    });

                    info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                    {
                        ValueExpression  = Variable(variableName),
                        TargetExpression = getTarget(source.Name)
                    });
                }
                else
                {
                    info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                    {
                        ValueExpression  = Null,
                        TargetExpression = getTarget(source.Name)
                    });
                }

                string typeName = this.nameLookup.Lookup(source.Type, true);

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #8
0
        /// <summary>
        /// Finds a declaration (excluding methods) with the specified name
        /// </summary>
        /// <param name="name">The name of the declaration to search for.</param>
        /// <returns>The declaration with the specified name or null if not found.</returns>
        public IDeclaration GetDeclaration(string name)
        {
            // Project
            if (Project == null)
            {
                return(null);
            }

            IDeclaration superGlobalDeclaration = Project.GetDeclaration(name);

            if (superGlobalDeclaration != null)
            {
                return(superGlobalDeclaration);
            }

            // Sprite
            if (CurrentSprite == null)
            {
                return(null);
            }

            ITypedDeclaration globalDeclaration = CurrentSprite.GetDeclaration(name);

            if (globalDeclaration != null)
            {
                return(globalDeclaration);
            }

            // Methods
            if (CurrentScope == null)
            {
                return(null);
            }

            // Method params
            ParamDeclaration methodParam = (CurrentScope.Method as MethodDeclaration)?.FindParam(name);

            if (methodParam != null)
            {
                return(methodParam);
            }

            // Scoped variables
            return(CurrentScope.Search(name));
        }
Пример #9
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Type.FixedLength.Type != FixedLengthType.None)
            {
                string name        = source.Name;
                string memberType  = this.nameLookup.Lookup(source.Type, false);
                string interopType = this.nameLookup.Lookup(source.Type, true);

                if (this.typeData[source.Type.VkName].Pattern == TypePattern.Primitive)
                {
                    string length = "1";

                    if (source.Type.FixedLength.Type == FixedLengthType.IntegerLiteral)
                    {
                        length = source.Type.FixedLength.Value;
                    }
                    else
                    {
                        var constant = this.constantsLookup[source.Type.FixedLength.Value];

                        length = $"Constants.{constant.Name}";
                    }

                    info.InteropFullType = interopType;

                    name       += $"[{length}]";
                    interopType = "fixed " + interopType;

                    info.Interop = new TypedDefinition
                    {
                        Name = name,
                        Type = interopType
                    };

                    switch (source.Type.VkName)
                    {
                    case "char":
                        info.Public.Add(new TypedDefinition
                        {
                            Name = source.Name,
                            Type = "string"
                        });

                        info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                        {
                            TargetExpression = getTarget(source.Name),
                            ValueExpression  = StaticCall("Interop.HeapUtil", "MarshalStringFrom", getValue(source.Name), AsIs(length), Literal(true))
                        });
                        break;

                    default:
                        if (memberType == "byte" && source.Name.ToLower().EndsWith("uid"))
                        {
                            info.Public.Add(new TypedDefinition
                            {
                                Name = source.Name,
                                Type = "Guid"
                            });

                            info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = New("Guid", StaticCall("Interop.HeapUtil", "MarshalFrom", getValue(source.Name), AsIs(length)))
                            });
                        }
                        else
                        {
                            info.Public.Add(new TypedDefinition
                            {
                                Name = source.Name,
                                Type = memberType + "[]"
                            });

                            info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = StaticCall("Interop.HeapUtil", "MarshalFrom", getValue(source.Name), AsIs(length))
                            });
                        }

                        info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                        {
                            TargetExpression = getTarget(source.Name),
                            ValueExpression  = getValue(source.Name),
                            Type             = AssignActionType.FixedLengthMarshalTo,
                            LengthExpression = AsIs(length)
                        });
                        break;
                    }
                }
                else
                {
                    var elementType = source.Type.Deref();

                    var marshalling = this.marshallingRules.ApplyFirst(elementType);

                    int count = 1;

                    if (source.Type.FixedLength.Type == FixedLengthType.IntegerLiteral)
                    {
                        count = int.Parse(source.Type.FixedLength.Value);
                    }
                    else
                    {
                        var constant = this.constantsLookup[source.Type.FixedLength.Value];

                        count = int.Parse(constant.Value);
                    }

                    info.InteropFullType = interopType;

                    info.Interop = new TypedDefinition
                    {
                        Name    = name,
                        Type    = interopType,
                        Repeats = count
                    };

                    info.Public.Add(new TypedDefinition
                    {
                        Name = name,
                        Type = memberType + "[]"
                    });

                    string countMemberName = source.Name.TrimEnd('s') + "Count";

                    info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                    {
                        TargetExpression    = getTarget(source.Name),
                        MemberType          = memberType,
                        IsLoop              = true,
                        IsArray             = true,
                        IndexName           = "index",
                        Type                = marshalling.MarshalFromActionType,
                        NullCheckExpression = IsNotEqual(getValue(countMemberName), Literal(0)),
                        LengthExpression    = getValue(countMemberName),
                        ValueExpression     = marshalling.BuildMarshalFromValueExpression(Index(Brackets(AddressOf(Brackets(getValue(source.Name + "_0")))), Variable("index")), context.GetHandle)
                    });
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #10
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            var lenExpressions = new List <(Func <Func <string, Action <ExpressionBuilder> >, Action <ExpressionBuilder> >, bool, bool)>();

            foreach (var otherMember in others)
            {
                if (otherMember.Dimensions != null)
                {
                    foreach (var dimension in otherMember.Dimensions)
                    {
                        if (dimension.Type == LenType.Expression && tokenCheck.Check(dimension.Value, source.VkName))
                        {
                            if (dimension.Value is LenExpressionToken)
                            {
                                lenExpressions.Add((getValue => Coalesce(CoalesceMember(getValue(otherMember.Name), "Length"), Literal(0)), otherMember.NoAutoValidity, otherMember.IsOptional));
                            }
                        }
                    }
                }
                else if (otherMember.Type.FixedLength.Type != FixedLengthType.None && source.VkName == otherMember.VkName.TrimEnd('s') + "Count")
                {
                    lenExpressions.Add((getValue => Coalesce(CoalesceMember(getValue(otherMember.Name), "Length"), Literal(0)), otherMember.NoAutoValidity, otherMember.IsOptional));
                }
            }

            bool isArrayLenMember = lenExpressions.Any() && (source.IsOptional || lenExpressions.Any(x => !x.Item2));

            if (isArrayLenMember)
            {
                var lenExpression = lenExpressions.Any(x => !x.Item2)
                                        ? lenExpressions.FirstOrDefault(x => !x.Item2)
                                        : lenExpressions.First();

                MethodAction assign(Func <string, Action <ExpressionBuilder> > getTarget, Func <string, Action <ExpressionBuilder> > getValue) =>
                new AssignAction
                {
                    TargetExpression = getTarget(source.Name),
                    ValueExpression  = Cast(this.nameLookup.Lookup(source.Type, false), lenExpression.Item1(getValue))
                };

                string typeName = this.nameLookup.Lookup(source.Type, true);

                if (source.IsOptional && lenExpressions.All(x => x.Item2) && lenExpressions.All(x => x.Item3))
                {
                    info.Public.Add(new TypedDefinition
                    {
                        Name         = source.Name,
                        Type         = typeName + "?",
                        DefaultValue = Null
                    });

                    MethodAction optionalAssign(Func <string, Action <ExpressionBuilder> > getTarget, Func <string, Action <ExpressionBuilder> > getValue)
                    {
                        var result = new OptionalAction
                        {
                            NullCheckExpression = IsNotEqual(getValue(source.Name), Null)
                        };

                        result.Actions.Add(new AssignAction
                        {
                            TargetExpression = getTarget(source.Name),
                            ValueExpression  = Member(getValue(source.Name), "Value")
                        });

                        result.ElseActions.Add(assign(getTarget, getValue));

                        return(result);
                    }

                    info.MarshalTo.Add(optionalAssign);
                }
                else
                {
                    info.MarshalTo.Add(assign);
                }

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;
            }

            return(isArrayLenMember);
        }
Пример #11
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            var  lenExpressions    = new List <(Func <Func <string, Action <ExpressionBuilder> >, Action <ExpressionBuilder> >, bool, bool)>();
            bool isLenOfLastMember = false;

            foreach (var otherMember in others)
            {
                bool isLastMember = otherMember.VkName == others.Last().VkName;

                if (otherMember.Dimensions != null)
                {
                    foreach (var dimension in otherMember.Dimensions)
                    {
                        if (dimension.Type == LenType.Expression && tokenCheck.Check(dimension.Value, source.VkName))
                        {
                            if (dimension.Value is LenExpressionToken)
                            {
                                lenExpressions.Add((getValue => StaticCall("Interop.HeapUtil", "GetLength", getValue(otherMember.Name)), otherMember.NoAutoValidity, otherMember.IsOptional));
                                isLenOfLastMember |= isLastMember;
                            }
                        }
                    }
                }
                else if (otherMember.Type.FixedLength.Type != FixedLengthType.None && source.VkName == otherMember.VkName.TrimEnd('s') + "Count")
                {
                    lenExpressions.Add((getValue => StaticCall("Interop.HeapUtil", "GetLength", getValue(otherMember.Name)), otherMember.NoAutoValidity, otherMember.IsOptional));
                    isLenOfLastMember |= isLastMember;
                }
            }

            bool isArrayLenMember = lenExpressions.Any() &&
                                    !(source.VkName == "descriptorCount" && context.VkName == "VkWriteDescriptorSet") &&
                                    !(isLenOfLastMember && context.HasReturnValue && lenExpressions.Count == 1 && !context.IsBatchSingleMethod);

            if (isArrayLenMember)
            {
                string typeName = this.nameLookup.Lookup(source.Type, true);

                info.Interop = new TypedDefinition
                {
                    Name = source.Name,
                    Type = typeName
                };

                info.InteropFullType = typeName;

                if (context.IsBatchSingleMethod && isLenOfLastMember)
                {
                    info.MarshalTo.Add((getTarget, geValue) => new AssignAction
                    {
                        TargetExpression = getTarget(source.Name),
                        ValueExpression  = Literal(1)
                    });
                }
                else
                {
                    var lenExpression = lenExpressions.Any(x => !x.Item2)
                                            ? lenExpressions.First(x => !x.Item2)
                                            : lenExpressions.First();

                    MethodAction assign(Func <string, Action <ExpressionBuilder> > getTarget, Func <string, Action <ExpressionBuilder> > getValue) =>
                    new AssignAction
                    {
                        TargetExpression = getTarget(source.Name),
                        ValueExpression  = Cast(this.nameLookup.Lookup(source.Type, false), lenExpression.Item1(getValue))
                    };

                    if (source.IsOptional && (lenExpressions.All(x => x.Item2 && x.Item3)))
                    {
                        info.Public.Add(new TypedDefinition
                        {
                            Name         = source.Name,
                            Comment      = this.commentGenerator.Lookup(context.VkName, source.VkName),
                            Type         = typeName + "?",
                            DefaultValue = Null
                        });

                        MethodAction optionalAssign(Func <string, Action <ExpressionBuilder> > getTarget, Func <string, Action <ExpressionBuilder> > getValue)
                        {
                            var result = new OptionalAction
                            {
                                CheckExpression = IsNotEqual(getValue(source.Name), Null)
                            };

                            result.Actions.Add(new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = Member(getValue(source.Name), "Value")
                            });

                            result.ElseActions.Add(assign(getTarget, getValue));

                            return(result);
                        }

                        info.MarshalTo.Add(optionalAssign);
                    }
                    else
                    {
                        info.MarshalTo.Add(assign);
                    }
                }
            }

            return(isArrayLenMember);
        }
Пример #12
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (this.patternRules == null)
            {
                this.patternRules = this.provider.GetServices <IMemberPatternRule>();
            }

            string verbInfoPattern = context.MethodVerb + "info";

            if (context.Extension != null)
            {
                verbInfoPattern += context.Extension;
            }

            verbInfoPattern = verbInfoPattern.ToLower();

            if (context.MethodVerb != null && source.Dimensions == null && source.Type.VkName.ToLower().EndsWith(verbInfoPattern))
            {
                var infoTypeData    = this.typeData[source.Type.VkName];
                var interopType     = this.nameLookup.Lookup(source.Type, true);
                var interopBaseType = this.nameLookup.Lookup(source.Type, true, false);

                bool isPointer = source.Type.PointerType.IsPointer();

                info.Interop = new TypedDefinition
                {
                    Name = source.Name.FirstToLower(),
                    Type = interopType
                };

                info.InteropFullType = interopType;

                info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                {
                    ValueExpression  = New(interopBaseType),
                    TargetExpression = getTarget(source.Name),
                    MemberType       = interopBaseType,
                    Type             = isPointer ? AssignActionType.Alloc : AssignActionType.Assign
                });

                foreach (var member in infoTypeData.Members)
                {
                    var subPatternInfo = new MemberPatternInfo();

                    var relativeOthers = others.Select(x =>
                    {
                        if (x.Dimensions?.Any() ?? false)
                        {
                            if (x.Dimensions[0].Value is LenExpressionReference lenRef)
                            {
                                if (lenRef.LeftOperand is LenExpressionToken lenLeftToken &&
                                    lenLeftToken.Value == source.VkName)
                                {
                                    return(new WrappedTypedDeclaration(x, new[] { new MemberLen {
                                                                                      Type = LenType.Expression, Value = lenRef.RightOperand
                                                                                  } }));
                                }
                            }
                        }

                        return(x);
                    });

                    this.patternRules.ApplyFirst(infoTypeData.Members.Concat(relativeOthers), member, new MemberPatternContext(null, true, context.IsBatchSingleMethod, context.ReturnParamsCount, infoTypeData.Extension, context.GetHandle, source.Type.VkName), subPatternInfo);

                    foreach (var subAction in subPatternInfo.MarshalTo)
                    {
                        info.MarshalTo.Add((getTarget, getValue) =>
                        {
                            return(subAction(target => DerefMember(getTarget(source.Name), target), value => getValue(value.FirstToLower())));
                        });
                    }

                    foreach (var lookup in subPatternInfo.HandleLookup)
                    {
                        info.HandleLookup.Add((lookup.Item1, x => lookup.Item2(value => x(value.FirstToLower()))));
                    }

                    info.Public.AddRange(subPatternInfo.Public.Select(x =>
                                                                      new TypedDefinition
                    {
                        Name         = x.Name.FirstToLower(),
                        Comment      = x.Comment,
                        Type         = x.Type,
                        DefaultValue = x.DefaultValue
                    }));
                }

                foreach (var extendStruct in infoTypeData.ExtendTypes)
                {
                    var extendType = this.typeData[extendStruct];

                    string typeNamespace = "";

                    if (extendType.Extension != null)
                    {
                        typeNamespace += "." + string.Join(".", this.namespaceMap.Map(extendType.Extension));
                    }

                    string paramName = extendType.Name.FirstToLower() + extendType.Extension;

                    info.Public.Add(new TypedDefinition
                    {
                        Name         = paramName,
                        Type         = $"SharpVk{typeNamespace}.{extendType.Name}?",
                        Comment      = new[] { "Extension struct" }.ToList(),
                        DefaultValue = Null
                    });


                    info.MarshalTo.Add((getTarget, getValue) =>
                    {
                        var extendMarshalAction = new OptionalAction
                        {
                            CheckExpression = IsNotEqual(Variable(paramName), Null),
                            Priority        = -1
                        };

                        var variableName = (source.Type.VkName + "NextPointer").FirstToLower();

                        extendMarshalAction.Actions.AddRange(new MethodAction[]
                        {
                            new DeclarationAction
                            {
                                MemberType = $"SharpVk.Interop{typeNamespace}.{extendType.Name}*",
                                MemberName = "extensionPointer"
                            },
                            new AssignAction
                            {
                                TargetExpression = Variable("extensionPointer"),
                                ValueExpression  = Member(Variable(paramName), "Value"),
                                MemberType       = $"SharpVk.Interop{typeNamespace}.{extendType.Name}",
                                Type             = AssignActionType.MarshalTo
                            },
                            new AssignAction
                            {
                                TargetExpression = DerefMember(Variable("extensionPointer"), "Next"),
                                ValueExpression  = Variable(variableName)
                            },
                            new AssignAction
                            {
                                ValueExpression  = Variable("extensionPointer"),
                                TargetExpression = Variable(variableName)
                            }
                        });

                        return(extendMarshalAction);
                    });
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #13
0
 /// <summary>
 /// Creates a new instance of the <see cref="ArrayLookupExpression"/> class.
 /// </summary>
 /// <param name="declaration">The array declaration.</param>
 /// <param name="index">The expression for the index of the item being looked up.</param>
 /// <param name="fileName">The name of the file.</param>
 /// <param name="errorToken">The token to report any compiler errors to.</param>
 public ArrayLookupExpression(ITypedDeclaration declaration, IExpression index, string fileName, IToken errorToken) : base(declaration, fileName, errorToken)
 {
     Index = index;
 }
 public WrappedTypedDeclaration(ITypedDeclaration wrappedDeclaration, MemberLen[] dimensions)
 {
     this.wrappedDeclaration = wrappedDeclaration;
     this.Dimensions         = dimensions;
 }
Пример #15
0
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (this.patternRules == null)
            {
                this.patternRules = this.provider.GetServices <IMemberPatternRule>();
            }

            string verbInfoPattern = context.MethodVerb + "info";

            if (context.Extension != null)
            {
                verbInfoPattern += context.Extension;
            }

            verbInfoPattern = verbInfoPattern.ToLower();

            if (context.MethodVerb != null && source.Dimensions == null && source.Type.VkName.ToLower().EndsWith(verbInfoPattern))
            {
                var infoTypeData    = this.typeData[source.Type.VkName];
                var interopType     = this.nameLookup.Lookup(source.Type, true);
                var interopBaseType = this.nameLookup.Lookup(source.Type, true, false);

                bool isPointer = source.Type.PointerType.IsPointer();

                info.Interop = new TypedDefinition
                {
                    Name = source.Name.FirstToLower(),
                    Type = interopType
                };

                info.InteropFullType = interopType;

                info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                {
                    ValueExpression  = New(interopBaseType),
                    TargetExpression = getTarget(source.Name),
                    MemberType       = interopBaseType,
                    Type             = isPointer ? AssignActionType.Alloc : AssignActionType.Assign
                });

                foreach (var member in infoTypeData.Members)
                {
                    var subPatternInfo = new MemberPatternInfo();

                    this.patternRules.ApplyFirst(infoTypeData.Members, member, new MemberPatternContext(null, true, infoTypeData.Extension, context.GetHandle, source.Type.VkName), subPatternInfo);

                    foreach (var subAction in subPatternInfo.MarshalTo)
                    {
                        info.MarshalTo.Add((getTarget, getValue) =>
                        {
                            return(subAction(target => DerefMember(getTarget(source.Name), target), value => getValue(value.FirstToLower())));
                        });
                    }

                    foreach (var lookup in subPatternInfo.HandleLookup)
                    {
                        info.HandleLookup.Add((lookup.Item1, x => lookup.Item2(value => x(value.FirstToLower()))));
                    }

                    info.Public.AddRange(subPatternInfo.Public.Select(x =>
                                                                      new TypedDefinition
                    {
                        Name         = x.Name.FirstToLower(),
                        Comment      = x.Comment,
                        Type         = x.Type,
                        DefaultValue = x.DefaultValue
                    }));
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
                        //var singleValueMarshalling = this.marshallingRules.ApplyFirst(source.Type);

                        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}>?",
                                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")))
                                });
                            }
                        }

                        Action <ExpressionBuilder> lenValue = null;

                        if (source.Dimensions[0].Value is LenExpressionToken lenToken)
                        {
                            lenValue = Variable(others.Single(x => x.VkName == lenToken.Value).Name);
                        }
                        else
                        {
                            lenValue = 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,
                            ValueExpression     = marshalling.BuildMarshalFromValueExpression(Index(getValue(source.Name), Variable("index")), context.GetHandle)
                        });
                        break;
                    }
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #18
0
        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 = "string[]"
                    });



                    info.MarshalTo.Add((getTarget, getValue) =>
                    {
                        var marshalToAction = new OptionalAction
                        {
                            NullCheckExpression = IsNotEqual(getValue(source.Name), Null)
                        };

                        marshalToAction.Actions.Add(new AssignAction
                        {
                            ValueExpression  = StaticCall("Interop.HeapUtil", "MarshalTo", getValue(source.Name)),
                            TargetExpression = getTarget(source.Name),
                            MemberType       = this.nameLookup.Lookup(source.Type, false),
                            Type             = AssignActionType.Assign
                        });

                        return(marshalToAction);
                    });
                }
                else if (source.Dimensions.Length == 1)
                {
                    switch (source.Dimensions[0].Type)
                    {
                    case LenType.NullTerminated:
                        info.Public.Add(new TypedDefinition
                        {
                            Name = source.Name,
                            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());
                        }

                        info.Public.Add(new TypedDefinition
                        {
                            Name = source.Name,
                            Type = marshalling.MemberType + "[]"
                        });

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

                        Action <ExpressionBuilder> lenValue = null;

                        if (source.Dimensions[0].Value is LenExpressionToken lenToken)
                        {
                            lenValue = Variable(others.Single(x => x.VkName == lenToken.Value).Name);
                        }
                        else
                        {
                            lenValue = 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,
                            ValueExpression     = marshalling.BuildMarshalFromValueExpression(Index(getValue(source.Name), Variable("index")), context.GetHandle)
                        });
                        break;
                    }
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Type.FixedLength.Type != FixedLengthType.None)
            {
                string name        = source.Name;
                string memberType  = this.nameLookup.Lookup(source.Type, false);
                string interopType = this.nameLookup.Lookup(source.Type, true);

                if (this.typeData[source.Type.VkName].Pattern == TypePattern.Primitive)
                {
                    string length = "1";

                    if (source.Type.FixedLength.Type == FixedLengthType.IntegerLiteral)
                    {
                        length = source.Type.FixedLength.Value;
                    }
                    else
                    {
                        var constant = this.constantsLookup[source.Type.FixedLength.Value];

                        length = $"Constants.{constant.Name}";
                    }

                    info.InteropFullType = interopType;

                    name       += $"[{length}]";
                    interopType = "fixed " + interopType;

                    info.Interop = new TypedDefinition
                    {
                        Name = name,
                        Type = interopType
                    };

                    switch (source.Type.VkName)
                    {
                    case "char":
                        info.Public.Add(new TypedDefinition
                        {
                            Name    = source.Name,
                            Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                            Type    = "string"
                        });

                        info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                        {
                            TargetExpression = getTarget(source.Name),
                            ValueExpression  = StaticCall("Interop.HeapUtil", "MarshalStringFrom", getValue(source.Name), AsIs(length), Literal(true))
                        });
                        break;

                    default:
                        if (memberType == "byte" && source.Name.ToLower().EndsWith("uid"))
                        {
                            info.Public.Add(new TypedDefinition
                            {
                                Name    = source.Name,
                                Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                                Type    = "Guid"
                            });

                            info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = New("Guid", StaticCall("Interop.HeapUtil", "MarshalFrom", getValue(source.Name), AsIs(length)))
                            });

                            info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = getValue(source.Name),
                                Type             = AssignActionType.FixedLengthMarshalTo,
                                LengthExpression = AsIs(length)
                            });
                        }
                        else if (int.TryParse(length, out int count))
                        {
                            info.Public.Add(new TypedDefinition
                            {
                                Name    = source.Name,
                                Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                                Type    = "(" + string.Join(", ", Enumerable.Repeat(memberType, count)) + ")"
                            });

                            info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                Type             = AssignActionType.Assign,
                                ValueExpression  = NewValueTuple(Enumerable.Range(0, count).Select(x => Index(getValue(source.Name), Literal(x))).ToArray())
                            });

                            for (int index = 0; index < count; index++)
                            {
                                string valueFieldName = "Item" + (index + 1);
                                int    fieldIndex     = index;

                                info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                                {
                                    TargetExpression = Index(getTarget(source.Name), Literal(fieldIndex)),
                                    Type             = AssignActionType.Assign,
                                    ValueExpression  = Member(getValue(source.Name), valueFieldName)
                                });
                            }
                        }
                        else
                        {
                            info.Public.Add(new TypedDefinition
                            {
                                Name    = source.Name,
                                Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                                Type    = memberType + "[]"
                            });

                            info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = StaticCall("Interop.HeapUtil", "MarshalFrom", getValue(source.Name), AsIs(length))
                            });

                            info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(source.Name),
                                ValueExpression  = getValue(source.Name),
                                Type             = AssignActionType.FixedLengthMarshalTo,
                                LengthExpression = AsIs(length)
                            });
                        }
                        break;
                    }
                }
                else
                {
                    var elementType = source.Type.Deref();

                    var marshalling = this.marshallingRules.ApplyFirst(elementType);

                    int count = 1;

                    if (source.Type.FixedLength.Type == FixedLengthType.IntegerLiteral)
                    {
                        count = int.Parse(source.Type.FixedLength.Value);
                    }
                    else
                    {
                        var constant = this.constantsLookup[source.Type.FixedLength.Value];

                        count = int.Parse(constant.Value);
                    }

                    info.InteropFullType = interopType;

                    info.Interop = new TypedDefinition
                    {
                        Name    = name,
                        Type    = interopType,
                        Repeats = count
                    };

                    if (count > 8)
                    {
                        info.Public.Add(new TypedDefinition
                        {
                            Name    = name,
                            Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                            Type    = memberType + "[]"
                        });

                        string countMemberName = source.Name.TrimEnd('s') + "Count";

                        info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                        {
                            TargetExpression    = getTarget(source.Name),
                            MemberType          = memberType,
                            IsLoop              = true,
                            IsArray             = true,
                            IndexName           = "index",
                            Type                = marshalling.MarshalFromActionType,
                            NullCheckExpression = IsNotEqual(getValue(countMemberName), Literal(0)),
                            LengthExpression    = getValue(countMemberName),
                            ValueExpression     = marshalling.BuildMarshalFromValueExpression(Index(Brackets(AddressOf(Brackets(getValue(source.Name + "_0")))), Variable("index")), context.GetHandle)
                        });

                        info.MarshalTo.Add((getTarget, getValue) =>
                        {
                            var marshalToAction = new OptionalAction
                            {
                                CheckExpression = LogicalAnd(IsNotEqual(getValue(source.Name), Null), GreaterThanEqualTo(Member(getValue(source.Name), "Length"), Literal(count)))
                            };

                            for (int index = 0; index < count; index++)
                            {
                                string targetFieldName = source.Name + "_" + index;
                                int valueIndex         = index;

                                marshalToAction.Actions.Add(new AssignAction
                                {
                                    TargetExpression = getTarget(targetFieldName),
                                    Type             = marshalling.MarshalToActionType,
                                    ValueExpression  = marshalling.BuildMarshalToValueExpression(Index(getValue(source.Name), Literal(valueIndex)), context.GetHandle)
                                });
                            }

                            return(marshalToAction);
                        });
                    }
                    else
                    {
                        info.Public.Add(new TypedDefinition
                        {
                            Name    = name,
                            Comment = this.commentGenerator.Lookup(context.VkName, source.VkName),
                            Type    = "(" + string.Join(", ", Enumerable.Repeat(memberType, count)) + ")"
                        });

                        info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                        {
                            TargetExpression = getTarget(source.Name),
                            Type             = AssignActionType.Assign,
                            ValueExpression  = NewValueTuple(Enumerable.Range(0, count).Select(x => getValue(source.Name + "_" + x)).ToArray())
                        });

                        for (int index = 0; index < count; index++)
                        {
                            string targetFieldName = source.Name + "_" + index;
                            string valueFieldName  = "Item" + (index + 1);

                            info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                            {
                                TargetExpression = getTarget(targetFieldName),
                                Type             = marshalling.MarshalToActionType,
                                ValueExpression  = marshalling.BuildMarshalToValueExpression(Member(getValue(source.Name), valueFieldName), context.GetHandle)
                            });
                        }
                    }
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
        public bool Apply(IEnumerable <ITypedDeclaration> others, ITypedDeclaration source, MemberPatternContext context, MemberPatternInfo info)
        {
            if (source.Dimensions != null &&
                source.Dimensions.Length == 1 &&
                source.Dimensions[0].Type == LenType.Expression &&
                context.IsBatchSingleMethod)
            {
                var resultMember = others.Last();
                var resultLen    = resultMember.Dimensions[0].Value;

                if (!this.expressionEqualityCheck.Check(resultLen, source.Dimensions[0].Value))
                {
                    return(false);
                }

                var verbInfoPattern = this.provider.GetServices <IMemberPatternRule>().OfType <VerbInfoMemberPattern>().Single();
                //var verbInfoPatternInfo = new MemberPatternInfo();
                if (verbInfoPattern.Apply(others,
                                          new ParamDeclaration
                {
                    Name = source.Name,
                    VkName = source.VkName,
                    Dimensions = null,
                    IsOptional = false,
                    NoAutoValidity = false,
                    Type = source.Type
                }, context, info))
                {
                }
                else
                {
                    string typeName = this.nameLookup.Lookup(source.Type, true);

                    info.Interop = new TypedDefinition
                    {
                        Name = source.Name,
                        Type = typeName
                    };

                    var marshalling = this.marshallingRules.ApplyFirst(source.Type);

                    info.InteropFullType = marshalling.InteropType.TrimEnd('*') + "*";

                    info.Public.Add(new TypedDefinition
                    {
                        Name         = source.Name,
                        Type         = marshalling.MemberType,
                        Comment      = this.commentGenerator.Lookup(context.VkName, source.VkName),
                        DefaultValue = null
                    });

                    info.MarshalTo.Add((getTarget, getValue) => new AssignAction
                    {
                        Type             = marshalling.MarshalToActionType,
                        MemberType       = marshalling.InteropType,
                        ValueExpression  = marshalling.BuildMarshalToValueExpression(getValue(source.Name), context.GetHandle),
                        TargetExpression = getTarget(source.Name)
                    });

                    info.MarshalFrom.Add((getTarget, getValue) => new AssignAction
                    {
                        TargetExpression    = getTarget(source.Name),
                        MemberType          = marshalling.MemberType,
                        Type                = marshalling.MarshalFromActionType,
                        NullCheckExpression = IsNotEqual(getValue(source.Name), Null),
                        ValueExpression     = marshalling.BuildMarshalFromValueExpression(getValue(source.Name), context.GetHandle)
                    });
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }