示例#1
0
        CodeMemberMethod GenerateCallMethod(XPathFunctionInfo[] functions, int minArgs, int maxArgs, CodeExpression processorRef, CodeMemberMethod initializeMethod)
        {
            XPathFunctionInfo mostParameters = functions.OrderByDescending(f => f.Parameters.Count).First();
            XPathModuleInfo   module         = mostParameters.Module;

            var argsParam = new CodeParameterDeclarationExpression(typeof(IXdmEnumerator[]), "arguments");

            var callMethod = new CodeMemberMethod {
                Name       = "Call",
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                ReturnType = new CodeTypeReference(typeof(IXdmEnumerator)),
                Parameters =
                {
                    argsParam,
                    new CodeParameterDeclarationExpression(typeof(DynamicContext), "context")
                }
            };

            var argumentsRef = new CodeVariableReferenceExpression(callMethod.Parameters[0].Name);

            CodeExpression moduleRef;

            if (module.TypeIsStatic)
            {
                moduleRef = new CodeTypeReferenceExpression(module.Type);
            }
            else
            {
                var moduleVar = new CodeVariableDeclarationStatement {
                    Name           = "module",
                    Type           = new CodeTypeReference(module.Type),
                    InitExpression = new CodeObjectCreateExpression(module.Type)
                };

                callMethod.Statements.Add(moduleVar);

                moduleRef = new CodeVariableReferenceExpression(moduleVar.Name);

                if (initializeMethod != null)
                {
                    callMethod.Statements.Add(new CodeMethodInvokeExpression {
                        Method     = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), initializeMethod.Name),
                        Parameters = { moduleRef }
                    });
                }
            }

            CodeStatementCollection currentBlock = callMethod.Statements;
            var paramRef = new List <CodeExpression>();

            for (int pos = 0; pos <= maxArgs; pos++)
            {
                if (pos > 0)
                {
                    XPathSequenceType paramInfo = mostParameters.Parameters[pos - 1].Type;

                    var paramVar = new CodeVariableDeclarationStatement {
                        Name           = "p" + pos,
                        Type           = new CodeTypeReference(paramInfo.ClrType),
                        InitExpression = TransformInput(argumentsRef, pos, paramInfo)
                    };

                    currentBlock.Add(paramVar);

                    paramRef.Add(new CodeVariableReferenceExpression(paramVar.Name));
                }

                if (pos >= minArgs)
                {
                    XPathFunctionInfo fn = functions[pos - minArgs];

                    CodeConditionStatement ifElse = null;

                    if (minArgs != maxArgs &&
                        pos < maxArgs)
                    {
                        ifElse = new CodeConditionStatement {
                            Condition = new CodeBinaryOperatorExpression {
                                Left     = new CodePropertyReferenceExpression(argumentsRef, "Length"),
                                Operator = CodeBinaryOperatorType.ValueEquality,
                                Right    = new CodePrimitiveExpression(pos)
                            }
                        };

                        currentBlock.Add(ifElse);
                        currentBlock = ifElse.TrueStatements;
                    }

                    var functionInvoke = new CodeMethodInvokeExpression {
                        Method = new CodeMethodReferenceExpression(moduleRef, fn.Method.Name)
                    };

                    functionInvoke.Parameters.AddRange(paramRef.ToArray());

                    CodeExpression returnExpr;

                    if (!fn.ReturnType.IsEmptySequence)
                    {
                        returnExpr = TransformOutput(functionInvoke, fn.ReturnType, processorRef);
                    }
                    else
                    {
                        currentBlock.Add(functionInvoke);

                        returnExpr = new CodePropertyReferenceExpression {
                            PropertyName = "INSTANCE",
                            TargetObject = new CodeTypeReferenceExpression(typeof(EmptyEnumerator))
                        };
                    }

                    currentBlock.Add(new CodeMethodReturnStatement(returnExpr));

                    if (ifElse != null)
                    {
                        currentBlock = ifElse.FalseStatements;
                    }
                }
            }

            return(callMethod);
        }
示例#2
0
        static CodeMemberMethod GenerateFunction(XPathFunctionInfo function, CodeExpression moduleExpr)
        {
            string name = function.Name;

            MemberAttributes methodAttributes = MemberAttributes.Public;

            if (name.Contains('-'))
            {
                name             = name.Replace('-', '_');
                methodAttributes = MemberAttributes.Family;
            }

            methodAttributes |= MemberAttributes.Final;

            Type procReturnType = GetReturnType(function.ReturnType);

            var codeMethod = new CodeMemberMethod {
                Name       = name,
                Attributes = methodAttributes,
                ReturnType = new CodeTypeReference(procReturnType),
            };

            var methodInvoke = new CodeMethodInvokeExpression {
                Method = new CodeMethodReferenceExpression {
                    MethodName   = function.Method.Name,
                    TargetObject = moduleExpr
                }
            };

            for (int i = 0; i < function.Parameters.Count; i++)
            {
                XPathSequenceType paramTypeInfo = function.Parameters[i].Type;

                Type procParamType = GetParameterType(paramTypeInfo);

                var paramDecl = new CodeParameterDeclarationExpression {
                    Name = "p" + i.ToStringInvariant(),
                    Type = new CodeTypeReference(procParamType)
                };

                codeMethod.Parameters.Add(paramDecl);

                var            paramVarExpr = new CodeVariableReferenceExpression(paramDecl.Name);
                CodeExpression argExpr      = GetArgumentExpression(paramTypeInfo, procParamType, paramVarExpr);

                methodInvoke.Parameters.Add(argExpr);
            }

            CodeVariableReferenceExpression resultVarExpr = null;

            if (function.ReturnType.ClrType == typeof(void))
            {
                codeMethod.Statements.Add(new CodeExpressionStatement(methodInvoke));
            }
            else
            {
                var resultVarDecl = new CodeVariableDeclarationStatement {
                    Name           = "result",
                    InitExpression = methodInvoke,
                    Type           = new CodeTypeReference(function.Method.ReturnType)
                };

                codeMethod.Statements.Add(resultVarDecl);

                resultVarExpr = new CodeVariableReferenceExpression(resultVarDecl.Name);
            }

            CodeExpression returnExpr = GetReturnExpression(function.ReturnType, resultVarExpr);

            codeMethod.Statements.Add(new CodeMethodReturnStatement(returnExpr));

            return(codeMethod);
        }
示例#3
0
        Tuple <CodeTypeDeclaration, CodeTypeDeclaration> GenerateFunctionType(XPathFunctionInfo[] functions)
        {
            XPathFunctionInfo first           = functions.First();
            XPathFunctionInfo leastParameters = functions.OrderBy(f => f.Parameters.Count).First();
            XPathFunctionInfo mostParameters  = functions.OrderByDescending(f => f.Parameters.Count).First();
            XPathModuleInfo   module          = first.Module;
            int minArgs = leastParameters.Parameters.Count;
            int maxArgs = mostParameters.Parameters.Count;

            CodeExpression thisRef = new CodeThisReferenceExpression();

            var processorField = new CodeMemberField {
                Name = "_processor",
                Type = new CodeTypeReference(typeof(SaxonProcessor))
            };

            var funcNameField = new CodeMemberField {
                Name           = "_FunctionName",
                Type           = new CodeTypeReference(typeof(QName)),
                InitExpression = new CodeObjectCreateExpression(
                    typeof(QName),
                    new CodePrimitiveExpression(module.Namespace),
                    new CodePrimitiveExpression(first.Name)
                    )
            };

            var argTypesField = new CodeMemberField {
                Name           = "_ArgumentTypes",
                Type           = new CodeTypeReference(typeof(XdmSequenceType[])),
                InitExpression = new CodeArrayCreateExpression(
                    typeof(XdmSequenceType),
                    mostParameters.Parameters.Select(p =>
                                                     new CodeObjectCreateExpression(
                                                         typeof(XdmSequenceType),
                                                         GetXdmItemTypeExpression(p.Type.ItemType),
                                                         new CodePrimitiveExpression(GetOcurrenceIndicator(p.Type.Cardinality))
                                                         )).ToArray()
                    )
            };

            var resultTypesField = new CodeMemberField {
                Name = "_resultTypes",
                Type = new CodeTypeReference(typeof(XdmSequenceType[]))
            };

            var resultTypesFieldInit = new CodeArrayCreateExpression {
                CreateType = resultTypesField.Type,
                Size       = functions.Length
            };

            for (int i = 0; i < functions.Length; i++)
            {
                XPathFunctionInfo function = functions[i];

                resultTypesFieldInit.Initializers.Add(

                    // Using item()? instead of empty-sequence()

                    (function.ReturnType.IsEmptySequence) ?

                    new CodeObjectCreateExpression(
                        typeof(XdmSequenceType),
                        new CodeFieldReferenceExpression(
                            new CodeTypeReferenceExpression(typeof(XdmAnyItemType)),
                            "Instance"
                            ),
                        new CodePrimitiveExpression(GetOcurrenceIndicator(XPathSequenceCardinality.ZeroOrOne))
                        )

                  : new CodeObjectCreateExpression(
                        typeof(XdmSequenceType),
                        GetXdmItemTypeExpression(function.ReturnType.ItemType),
                        new CodePrimitiveExpression(GetOcurrenceIndicator(function.ReturnType.Cardinality))
                        )
                    );
            }

            resultTypesField.InitExpression = resultTypesFieldInit;

            var defClass = new CodeTypeDeclaration {
                Name       = first.Method.Name + "Function",
                Attributes = MemberAttributes.Public,
                BaseTypes  = { typeof(ExtensionFunctionDefinition) },
                Members    =
                {
                    processorField,
                    funcNameField,
                    argTypesField,
                    resultTypesField,
                    new CodeConstructor {
                        Attributes = MemberAttributes.Public,
                        Parameters =
                        {
                            new CodeParameterDeclarationExpression(processorField.Type,            "processor")
                        },
                        Statements =
                        {
                            new CodeAssignStatement(
                                new CodeFieldReferenceExpression(thisRef, processorField.Name),
                                new CodeVariableReferenceExpression("processor")
                                )
                        }
                    },
                    new CodeMemberProperty {
                        Name          = "FunctionName",
                        Type          = funcNameField.Type,
                        Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                        HasGet        = true,
                        GetStatements =
                        {
                            new CodeMethodReturnStatement(new CodeFieldReferenceExpression(thisRef,funcNameField.Name))
                        }
                    },
                    new CodeMemberProperty {
                        Name          = "ArgumentTypes",
                        Type          = argTypesField.Type,
                        Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                        HasGet        = true,
                        GetStatements =
                        {
                            new CodeMethodReturnStatement(new CodeFieldReferenceExpression(thisRef,argTypesField.Name))
                        }
                    },
                    new CodeMemberProperty {
                        Name          = "MaximumNumberOfArguments",
                        Type          = new CodeTypeReference(typeof(int)),
                        Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                        HasGet        = true,
                        GetStatements =
                        {
                            new CodeMethodReturnStatement(new CodePrimitiveExpression(maxArgs))
                        }
                    },
                    new CodeMemberProperty {
                        Name          = "MinimumNumberOfArguments",
                        Type          = new CodeTypeReference(typeof(int)),
                        Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                        HasGet        = true,
                        GetStatements =
                        {
                            new CodeMethodReturnStatement(new CodePrimitiveExpression(minArgs))
                        }
                    },
                    GenerateResultTypeMethod(thisRef,                                              resultTypesField)
                }
            };

            if (first.HasSideEffects)
            {
                defClass.Members.Add(new CodeMemberProperty {
                    Name          = "HasSideEffects",
                    Type          = new CodeTypeReference(typeof(bool)),
                    Attributes    = MemberAttributes.Public | MemberAttributes.Override,
                    HasGet        = true,
                    GetStatements =
                    {
                        new CodeMethodReturnStatement(new CodePrimitiveExpression(true))
                    }
                });
            }

            var callClass = new CodeTypeDeclaration {
                Name       = defClass.Name + "Call",
                Attributes = MemberAttributes.Assembly,
                BaseTypes  =
                {
                    new CodeTypeReference(typeof(ExtensionFunctionCall))
                },
                Members =
                {
                    processorField,
                    new CodeConstructor {
                        Attributes = MemberAttributes.Public,
                        Parameters =
                        {
                            new CodeParameterDeclarationExpression(processorField.Type,"processor")
                        },
                        Statements =
                        {
                            new CodeAssignStatement(
                                new CodeFieldReferenceExpression(thisRef, processorField.Name),
                                new CodeVariableReferenceExpression("processor")
                                )
                        }
                    }
                }
            };

            CodeMemberMethod initializeMethod = null;

            if (!module.TypeIsStatic &&
                module.Dependencies.Count > 0)
            {
                CodeExpression staticBaseUriExpr = null;

                if (module.Dependencies.Any(d => d.Type == typeof(XmlResolver)))
                {
                    var staticBaseUriField = new CodeMemberField {
                        Name = "_staticBaseUri",
                        Type = new CodeTypeReference(typeof(Uri))
                    };

                    callClass.Members.Add(staticBaseUriField);

                    var staticContextParam = new CodeParameterDeclarationExpression(typeof(StaticContext), "context");

                    staticBaseUriExpr = new CodeFieldReferenceExpression(thisRef, staticBaseUriField.Name);

                    callClass.Members.Add(new CodeMemberMethod {
                        Name       = "SupplyStaticContext",
                        Attributes = MemberAttributes.Public | MemberAttributes.Override,
                        Parameters =
                        {
                            staticContextParam
                        },
                        Statements =
                        {
                            new CodeAssignStatement {
                                Left  = staticBaseUriExpr,
                                Right = new CodePropertyReferenceExpression{
                                    PropertyName = "BaseUri",
                                    TargetObject = new CodeVariableReferenceExpression(staticContextParam.Name)
                                }
                            }
                        }
                    });
                }

                initializeMethod = GenerateInitialize(module, new CodeFieldReferenceExpression(thisRef, processorField.Name), staticBaseUriExpr);

                callClass.Members.Add(initializeMethod);
            }

            callClass.Members.Add(GenerateCallMethod(functions, minArgs, maxArgs, new CodeFieldReferenceExpression(thisRef, processorField.Name), initializeMethod));

            defClass.Members.Add(
                new CodeMemberMethod {
                Name       = "MakeFunctionCall",
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                ReturnType = new CodeTypeReference(typeof(ExtensionFunctionCall)),
                Statements =
                {
                    new CodeMethodReturnStatement(
                        new CodeObjectCreateExpression(
                            callClass.Name,
                            new CodeFieldReferenceExpression(thisRef, processorField.Name)
                            )
                        )
                }
            }
                );

            return(Tuple.Create(defClass, callClass));
        }