示例#1
0
        private IEnumerable <ParamActionDefinition> GenerateParameter(CommandDeclaration command, MethodDefinition newMethod, ParamDeclaration parameter, int parameterIndex, bool isEnumeratePattern, bool isLastParamArray, bool lastParamReturns, List <MethodAction> marshalFromActions, List <MethodAction> marshalMidActions, List <MethodAction> marshalToActions, List <Action <ExpressionBuilder> > marshalledValues, Func <string, Action <ExpressionBuilder> > getHandle, Dictionary <string, Action <ExpressionBuilder> > handleLookup)
        {
            string paramName = parameter.Name;
            var    paramType = typeData[parameter.Type.VkName];

            string GetMarshalledName(string baseName)
            {
                return("marshalled" + baseName.TrimStart('@').FirstToUpper());
            }

            List <ParamActionDefinition> result = new List <ParamActionDefinition>();

            if (parameterIndex >= command.HandleParamsCount)
            {
                if (lastParamReturns && parameterIndex == command.Params.Count() - 2 && isEnumeratePattern)
                {
                    newMethod.MemberActions.Add(new DeclarationAction
                    {
                        MemberType = paramType.Name,
                        MemberName = paramName
                    });

                    marshalledValues.Add(AddressOf(Variable(paramName)));

                    var patternInfo = new MemberPatternInfo();

                    this.memberPatternRules.ApplyFirst(command.Params, command.Params.Last(), new MemberPatternContext(command.Verb, true, command.Extension, getHandle, command.VkName), patternInfo);

                    string marshalledName = GetMarshalledName(patternInfo.Interop.Name);

                    marshalMidActions.Add(new AssignAction
                    {
                        Type             = AssignActionType.Alloc,
                        MemberType       = patternInfo.InteropFullType.TrimEnd('*'),
                        TargetExpression = Variable(marshalledName),
                        LengthExpression = Cast("uint", Variable(paramName))
                    });
                }
                else if (lastParamReturns && parameterIndex == command.Params.Count() - 1)
                {
                    if (isLastParamArray)
                    {
                        var patternInfo = new MemberPatternInfo();

                        this.memberPatternRules.ApplyFirst(command.Params, parameter, new MemberPatternContext(command.Verb, true, command.Extension, getHandle, command.VkName), patternInfo);

                        string marshalledName = GetMarshalledName(patternInfo.Interop.Name);

                        marshalToActions.Add(new DeclarationAction
                        {
                            MemberType = patternInfo.InteropFullType,
                            MemberName = marshalledName
                        });

                        var newMarshalFrom = patternInfo.MarshalFrom.Select(action => action(targetName => Variable("result"), valueName => Variable(GetMarshalledName(valueName)))).ToArray();

                        if (!isEnumeratePattern)
                        {
                            var lengthExpression = newMarshalFrom.OfType <AssignAction>().First(x => x.IsLoop).LengthExpression;

                            marshalToActions.Add(new AssignAction
                            {
                                Type             = AssignActionType.Alloc,
                                MemberType       = patternInfo.InteropFullType.TrimEnd('*'),
                                TargetExpression = Variable(marshalledName),
                                LengthExpression = lengthExpression
                            });
                        }

                        marshalFromActions.AddRange(newMarshalFrom);

                        marshalledValues.Add(Variable(marshalledName));

                        newMethod.ReturnType = patternInfo.ReturnType ?? patternInfo.Public.Single().Type;
                    }
                    else
                    {
                        var patternInfo = new MemberPatternInfo();

                        var effectiveParam = new ParamDeclaration
                        {
                            Name       = parameter.Name,
                            Type       = parameter.Type.Deref(),
                            Dimensions = parameter.Dimensions,
                            VkName     = parameter.VkName
                        };

                        this.memberPatternRules.ApplyFirst(command.Params, effectiveParam, new MemberPatternContext(command.Verb, true, command.Extension, getHandle, command.VkName), patternInfo);

                        string marshalledName = GetMarshalledName(patternInfo.Interop.Name);

                        marshalToActions.Add(new DeclarationAction
                        {
                            MemberType = patternInfo.InteropFullType,
                            MemberName = marshalledName
                        });

                        marshalFromActions.AddRange(patternInfo.MarshalFrom.Select(action => action(targetName => Variable("result"), valueName => Variable(GetMarshalledName(valueName)))));

                        marshalledValues.Add(AddressOf(Variable(marshalledName)));

                        newMethod.ReturnType = patternInfo.Public.Single().Type;
                    }
                }
                else
                {
                    var patternInfo = new MemberPatternInfo();

                    this.memberPatternRules.ApplyFirst(command.Params, parameter, new MemberPatternContext(command.Verb, true, command.Extension, getHandle, command.VkName), patternInfo);

                    var actionList = marshalToActions;

                    Func <string, Action <ExpressionBuilder> > getValue = valueName => Variable(valueName);

                    foreach (var publicMember in patternInfo.Public)
                    {
                        result.Add(new ParamActionDefinition
                        {
                            Param = new ParamDefinition
                            {
                                Name         = publicMember.Name,
                                Comment      = publicMember.Comment,
                                Type         = publicMember.Type,
                                DefaultValue = publicMember.DefaultValue
                            }
                        });
                    }

                    if (patternInfo.MarshalTo.Any())
                    {
                        string marshalledName = patternInfo.Interop.Name;

                        if (patternInfo.Public.Any())
                        {
                            marshalledName = GetMarshalledName(patternInfo.Interop.Name);
                        }

                        var newMarshalToActions = patternInfo.MarshalTo.Select(action => action(targetName => Variable(marshalledName), getValue));

                        var  lastParam         = command.Params.Last();
                        bool isLenForLastParam = lastParamReturns && lastParam.Dimensions != null && lastParam.Dimensions.Any(dimension => dimension.Type == LenType.Expression && this.tokenCheck.Check(dimension.Value, parameter.VkName));

                        if (!isLenForLastParam &&
                            newMarshalToActions.Count() == 1 &&
                            newMarshalToActions.First() is AssignAction newAssignAction &&
                            newAssignAction.Type == AssignActionType.Assign &&
                            !newAssignAction.IsLoop)
                        {
                            marshalledValues.Add(newAssignAction.ValueExpression);
                        }
                        else
                        {
                            marshalToActions.Add(new DeclarationAction
                            {
                                MemberType = patternInfo.InteropFullType,
                                MemberName = marshalledName
                            });

                            marshalledValues.Add(Variable(marshalledName));

                            actionList.AddRange(newMarshalToActions);
                        }
                    }

                    foreach (var lookup in patternInfo.HandleLookup)
                    {
                        handleLookup[lookup.Item1] = lookup.Item2(getValue);
                    }
                }
            }
        public void Execute(IServiceCollection services)
        {
            foreach (var typeItem in this.typeData.Where(x => x.Value.Pattern == TypePattern.MarshalledStruct))
            {
                var type          = typeItem.Value;
                var typeNamespace = new List <string>();

                if (type.Extension != null)
                {
                    typeNamespace.AddRange(this.namespaceMap.Map(type.Extension));
                }

                var publicStruct = new StructDefinition
                {
                    Name       = type.Name,
                    Namespace  = typeNamespace.ToArray(),
                    Comment    = this.commentGenerator.Lookup(typeItem.Key),
                    Methods    = new List <MethodDefinition>(),
                    Properties = new List <MemberDefinition>()
                };

                var marshalToMethod = new MethodDefinition
                {
                    Name         = "MarshalTo",
                    IsUnsafe     = true,
                    ParamActions = new List <ParamActionDefinition>
                    {
                        new ParamActionDefinition
                        {
                            Param = new ParamDefinition
                            {
                                Name = "pointer",
                                Type = this.nameLookup.Lookup(new TypeReference
                                {
                                    VkName      = typeItem.Key,
                                    PointerType = PointerType.Pointer
                                }, true)
                            }
                        }
                    },
                    MemberActions = new List <MethodAction>()
                };


                var marshalFromMethod = new MethodDefinition
                {
                    Name         = "MarshalFrom",
                    ReturnType   = type.Name,
                    IsUnsafe     = true,
                    IsStatic     = true,
                    ParamActions = new List <ParamActionDefinition>
                    {
                        new ParamActionDefinition
                        {
                            Param = new ParamDefinition
                            {
                                Name = "pointer",
                                Type = this.nameLookup.Lookup(new TypeReference
                                {
                                    VkName      = typeItem.Key,
                                    PointerType = PointerType.Pointer
                                }, true)
                            }
                        }
                    },
                    MemberActions = new List <MethodAction>()
                };

                if (!type.IsOutputOnly || (type.Extends?.Any(x => !this.typeData[x].IsOutputOnly) ?? false))
                {
                    publicStruct.Methods.Add(marshalToMethod);
                }

                if (type.IsOutputOnly || (!type.Name.EndsWith("Info") && type.Members.All(this.CanMarshalFrom)))
                {
                    publicStruct.Methods.Add(marshalFromMethod);
                }

                typeNamespace.Insert(0, "Interop");

                var interopStruct = new StructDefinition
                {
                    Name      = type.Name,
                    Namespace = typeNamespace.ToArray(),
                    IsUnsafe  = true,
                    Fields    = new List <MemberDefinition>()
                };

                foreach (var member in type.Members)
                {
                    var patternInfo = new MemberPatternInfo
                    {
                    };

                    this.patternRules.ApplyFirst(type.Members, member, new MemberPatternContext(null, false, false, false, type.Extension, x => Default(this.nameLookup.Lookup(new TypeReference {
                        VkName = x
                    }, false)), typeItem.Key), patternInfo);

                    marshalToMethod.MemberActions.AddRange(patternInfo.MarshalTo.Select(action => action(targetName => DerefMember(Variable("pointer"), targetName), valueName => Member(This, valueName))));
                    marshalFromMethod.MemberActions.AddRange(patternInfo.MarshalFrom.Select(action => action(targetName => Member(Variable("result"), targetName), valueName => DerefMember(Variable("pointer"), valueName))));

                    foreach (var publicMember in patternInfo.Public)
                    {
                        publicStruct.Properties.Add(new MemberDefinition
                        {
                            Name    = publicMember.Name,
                            Type    = publicMember.Type,
                            Comment = this.commentGenerator.Lookup(typeItem.Key, member.VkName)
                        });
                    }

                    if (patternInfo.Interop.Repeats.HasValue)
                    {
                        for (int index = 0; index < patternInfo.Interop.Repeats.Value; index++)
                        {
                            interopStruct.Fields.Add(new MemberDefinition
                            {
                                Name = patternInfo.Interop.Name + "_" + index,
                                Type = patternInfo.Interop.Type
                            });
                        }
                    }
                    else
                    {
                        interopStruct.Fields.Add(new MemberDefinition
                        {
                            Name    = patternInfo.Interop.Name,
                            Type    = patternInfo.Interop.Type,
                            Comment = this.commentGenerator.Lookup(typeItem.Key, member.VkName)
                        });
                    }
                }

                services.AddSingleton(publicStruct);

                services.AddSingleton(interopStruct);
            }
        }