void CompileFunction(XPathFunctionExpr expr) { // In some scenarios, some functions are handled in a special way if (this.CompileFunctionSpecial(expr)) { return; } // Generic function compilation QueryFunction function = expr.Function; // Compile each argument expression first, introducing a typecast where appropriate // Arguments are pushed C style - right to left if (expr.SubExprCount > 0) { XPathExprList paramList = expr.SubExpr; for (int i = paramList.Count - 1; i >= 0; --i) { this.CompileFunctionParam(function, expr.SubExpr, i); } } this.codeBlock.Append(new FunctionCallOpcode(function)); if (1 == this.compiler.nestingLevel && function.TestFlag(QueryFunctionFlag.UsesContextNode)) { this.compiler.SetPushInitialContext(true); } }
private XPathExpr ParseFunctionExpression() { XPathExpr expr; XPathToken token = this.NextToken(XPathTokenID.Function); if (token == null) { return(null); } NodeQName name = this.QualifyName(token.Prefix, token.Name); this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction); XPathExprList args = new XPathExprList(); while ((expr = this.ParseExpression()) != null) { args.Add(expr); if (this.NextToken(XPathTokenID.Comma) == null) { break; } } XPathExpr expr2 = null; if (this.functionLibraries != null) { QueryFunction function = null; for (int i = 0; i < this.functionLibraries.Length; i++) { function = this.functionLibraries[i].Bind(name.Name, name.Namespace, args); if (function != null) { expr2 = new XPathFunctionExpr(function, args); break; } } } if ((expr2 == null) && (this.context != null)) { XPathResultType[] argTypes = new XPathResultType[args.Count]; for (int j = 0; j < args.Count; j++) { argTypes[j] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[j].ReturnType); } string prefix = this.context.LookupPrefix(name.Namespace); IXsltContextFunction function2 = this.context.ResolveFunction(prefix, name.Name, argTypes); if (function2 != null) { expr2 = new XPathXsltFunctionExpr(this.context, function2, args); } } if (expr2 == null) { this.ThrowError(QueryCompileError.UnsupportedFunction); } this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction); return(expr2); }
private bool CompileFunctionSpecial(XPathFunctionExpr expr) { XPathFunction function = expr.Function as XPathFunction; if (((function != null) && (XPathFunctionID.StartsWith == function.ID)) && (XPathExprType.String == expr.SubExpr[1].Type)) { this.CompileFunctionParam(function, expr.SubExpr, 0); this.codeBlock.Append(new StringPrefixOpcode(((XPathStringExpr)expr.SubExpr[1]).String)); return(true); } return(false); }
private void CompileFunction(XPathFunctionExpr expr) { if (!this.CompileFunctionSpecial(expr)) { QueryFunction function = expr.Function; if (expr.SubExprCount > 0) { for (int i = expr.SubExpr.Count - 1; i >= 0; i--) { this.CompileFunctionParam(function, expr.SubExpr, i); } } this.codeBlock.Append(new FunctionCallOpcode(function)); if ((1 == this.compiler.nestingLevel) && function.TestFlag(QueryFunctionFlag.UsesContextNode)) { this.compiler.SetPushInitialContext(true); } } }
// Some functions are compiled with special opcodes to optimize perf in special situations // 1. starts-with(string, literal) bool CompileFunctionSpecial(XPathFunctionExpr expr) { XPathFunction function = expr.Function as XPathFunction; if (null != function) { if (XPathFunctionID.StartsWith == function.ID) { // Does the 2nd parameter start with a string literal? Use a special opcode to handle those.. Fx.Assert(expr.SubExprCount == 2, ""); if (XPathExprType.String == expr.SubExpr[1].Type) { this.CompileFunctionParam(function, expr.SubExpr, 0); this.codeBlock.Append(new StringPrefixOpcode(((XPathStringExpr)expr.SubExpr[1]).String)); return(true); } } } return(false); }
XPathExpr ParseFunctionExpression() { XPathToken functionToken = this.NextToken(XPathTokenID.Function); if (null == functionToken) { return(null); } NodeQName functionName = this.QualifyName(functionToken.Prefix, functionToken.Name); this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction); XPathExprList args = new XPathExprList(); // Read in arguments XPathExpr arg; while (null != (arg = this.ParseExpression())) { args.Add(arg); if (null == this.NextToken(XPathTokenID.Comma)) { break; } } // Bind to the function // Try each library until we can bind the function XPathExpr functionImpl = null; if (null != this.functionLibraries) { QueryFunction fun = null; for (int i = 0; i < this.functionLibraries.Length; ++i) { if (null != (fun = this.functionLibraries[i].Bind(functionName.Name, functionName.Namespace, args))) { functionImpl = new XPathFunctionExpr(fun, args); break; } } } // Try to bind using the XsltContext if (null == functionImpl && this.context != null) { XPathResultType[] argTypes = new XPathResultType[args.Count]; for (int i = 0; i < args.Count; ++i) { argTypes[i] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[i].ReturnType); } string prefix = this.context.LookupPrefix(functionName.Namespace); IXsltContextFunction xsltFun = this.context.ResolveFunction(prefix, functionName.Name, argTypes); if (xsltFun != null) { functionImpl = new XPathXsltFunctionExpr(this.context, xsltFun, args); } } if (null == functionImpl) { this.ThrowError(QueryCompileError.UnsupportedFunction); } this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction); return(functionImpl); }
// Some functions are compiled with special opcodes to optimize perf in special situations // 1. starts-with(string, literal) bool CompileFunctionSpecial(XPathFunctionExpr expr) { XPathFunction function = expr.Function as XPathFunction; if (null != function) { if (XPathFunctionID.StartsWith == function.ID) { // Does the 2nd parameter start with a string literal? Use a special opcode to handle those.. Fx.Assert(expr.SubExprCount == 2, ""); if (XPathExprType.String == expr.SubExpr[1].Type) { this.CompileFunctionParam(function, expr.SubExpr, 0); this.codeBlock.Append(new StringPrefixOpcode(((XPathStringExpr)expr.SubExpr[1]).String)); return true; } } } return false; }
XPathExpr ParseFunctionExpression() { XPathToken functionToken = this.NextToken(XPathTokenID.Function); if (null == functionToken) { return null; } NodeQName functionName = this.QualifyName(functionToken.Prefix, functionToken.Name); this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction); XPathExprList args = new XPathExprList(); // Read in arguments XPathExpr arg; while (null != (arg = this.ParseExpression())) { args.Add(arg); if (null == this.NextToken(XPathTokenID.Comma)) { break; } } // Bind to the function // Try each library until we can bind the function XPathExpr functionImpl = null; if (null != this.functionLibraries) { QueryFunction fun = null; for (int i = 0; i < this.functionLibraries.Length; ++i) { if (null != (fun = this.functionLibraries[i].Bind(functionName.Name, functionName.Namespace, args))) { functionImpl = new XPathFunctionExpr(fun, args); break; } } } // Try to bind using the XsltContext if (null == functionImpl && this.context != null) { XPathResultType[] argTypes = new XPathResultType[args.Count]; for (int i = 0; i < args.Count; ++i) { argTypes[i] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[i].ReturnType); } string prefix = this.context.LookupPrefix(functionName.Namespace); IXsltContextFunction xsltFun = this.context.ResolveFunction(prefix, functionName.Name, argTypes); if (xsltFun != null) { functionImpl = new XPathXsltFunctionExpr(this.context, xsltFun, args); } } if (null == functionImpl) { this.ThrowError(QueryCompileError.UnsupportedFunction); } this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction); return functionImpl; }
private bool CompileFunctionSpecial(XPathFunctionExpr expr) { XPathFunction function = expr.Function as XPathFunction; if (((function != null) && (XPathFunctionID.StartsWith == function.ID)) && (XPathExprType.String == expr.SubExpr[1].Type)) { this.CompileFunctionParam(function, expr.SubExpr, 0); this.codeBlock.Append(new StringPrefixOpcode(((XPathStringExpr) expr.SubExpr[1]).String)); return true; } return false; }
private XPathExpr ParseFunctionExpression() { XPathExpr expr; XPathToken token = this.NextToken(XPathTokenID.Function); if (token == null) { return null; } NodeQName name = this.QualifyName(token.Prefix, token.Name); this.NextToken(XPathTokenID.LParen, QueryCompileError.InvalidFunction); XPathExprList args = new XPathExprList(); while ((expr = this.ParseExpression()) != null) { args.Add(expr); if (this.NextToken(XPathTokenID.Comma) == null) { break; } } XPathExpr expr2 = null; if (this.functionLibraries != null) { QueryFunction function = null; for (int i = 0; i < this.functionLibraries.Length; i++) { function = this.functionLibraries[i].Bind(name.Name, name.Namespace, args); if (function != null) { expr2 = new XPathFunctionExpr(function, args); break; } } } if ((expr2 == null) && (this.context != null)) { XPathResultType[] argTypes = new XPathResultType[args.Count]; for (int j = 0; j < args.Count; j++) { argTypes[j] = XPathXsltFunctionExpr.ConvertTypeToXslt(args[j].ReturnType); } string prefix = this.context.LookupPrefix(name.Namespace); IXsltContextFunction function2 = this.context.ResolveFunction(prefix, name.Name, argTypes); if (function2 != null) { expr2 = new XPathXsltFunctionExpr(this.context, function2, args); } } if (expr2 == null) { this.ThrowError(QueryCompileError.UnsupportedFunction); } this.NextToken(XPathTokenID.RParen, QueryCompileError.InvalidFunction); return expr2; }