2004-08-26 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Thu, 26 Aug 2004 02:27:48 +0000 (02:27 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Thu, 26 Aug 2004 02:27:48 +0000 (02:27 -0000)
* XPath2Expression.cs : in Compiler(), function call's arguments must
  also be compiled.
* XQueryASTCompiler.cs : When function is external, it should not try
  to compile body, and tries to handle it as a native CLI method (I
  don't like this name resolution design very much, so it is likely
  to be redesigned).
* XQueryCliFunction.cs : trivial code comment fix.
* XQueryFunction : added user-specified function call support.
  When CLI function returned null, don't wrap null and just return
  XQueryEmptySequence.
* XQueryFunctionCliImpl.cs : fn:nilled() requires certain node.
  Implemented numeric functions (in the future they might be
  rewritten to avoid boxing).
* XQueryTokenizer.cs : Skip XQuery comment inside default state.
  PI and XML comment are not read correctly.

svn path=/trunk/mcs/; revision=32856

mcs/class/System.XML/System.Xml.Query/ChangeLog
mcs/class/System.XML/System.Xml.Query/XPath2Expression.cs
mcs/class/System.XML/System.Xml.Query/XQueryASTCompiler.cs
mcs/class/System.XML/System.Xml.Query/XQueryCliFunction.cs
mcs/class/System.XML/System.Xml.Query/XQueryFunction.cs
mcs/class/System.XML/System.Xml.Query/XQueryFunctionCliImpl.cs
mcs/class/System.XML/System.Xml.Query/XQueryTokenizer.cs

index 9cae11d280502522a296749b522f55c71465348e..3b8acfd39131a5507baf0e7701ab5227d753e242 100644 (file)
@@ -1,3 +1,21 @@
+2004-08-26  Atsushi Enomoto <atsushi@ximian.com>
+
+       * XPath2Expression.cs : in Compiler(), function call's arguments must
+         also be compiled.
+       * XQueryASTCompiler.cs : When function is external, it should not try
+         to compile body, and tries to handle it as a native CLI method (I
+         don't like this name resolution design very much, so it is likely
+         to be redesigned).
+       * XQueryCliFunction.cs : trivial code comment fix.
+       * XQueryFunction : added user-specified function call support.
+         When CLI function returned null, don't wrap null and just return
+         XQueryEmptySequence.
+       * XQueryFunctionCliImpl.cs : fn:nilled() requires certain node.
+         Implemented numeric functions (in the future they might be
+         rewritten to avoid boxing).
+       * XQueryTokenizer.cs : Skip XQuery comment inside default state.
+         PI and XML comment are not read correctly.
+
 2004-08-25  Atsushi Enomoto <atsushi@ximian.com>
 
        * XPath2Expression.cs :
index 43d07ecfb9975d77f7d5e865814f3430eb8fa608..542c55b315275728258709d203809090607698c6 100755 (executable)
@@ -2158,7 +2158,7 @@ namespace Mono.Xml.XPath2
 #region CompileAndEvaluate
 
        // It is instantiated per function call expression.
-       // (e.g. the example below contains 3 FunctionCallExpression instances:
+       // (e.g. the example below contains 4 FunctionCallExpression instances:
        // "replace(node-name (node-before(/*)), 'foo', node-name($var))"
        internal class CustomFunctionCallExpr : FunctionCallExprBase
        {
@@ -2189,6 +2189,8 @@ namespace Mono.Xml.XPath2
                internal override ExprSingle CompileCore (XQueryASTCompiler compiler)
                {
                        CheckArguments (compiler);
+                       for (int i = 0; i < Args.Count; i++)
+                               Args [i] = Args [i].Compile (compiler);
                        return this;
                }
 
index 2d0b5e6437c698b25f85b6fe3c88135a1697b719..54befce0819935b0b0d3e26a4d8c462d6ef41ab5 100755 (executable)
@@ -153,7 +153,8 @@ namespace Mono.Xml.XPath2
                        if (main != null)
                                main.QueryBody.CheckReference (this);
                        foreach (FunctionDeclaration func in module.Prolog.Functions.Values) {
-                               func.FunctionBody.CheckReference (this);
+                               if (!func.External)
+                                       func.FunctionBody.CheckReference (this);
                                CheckSchemaType (func.ReturnType);
                                foreach (XQueryFunctionArgument param in func.Parameters)
                                        CheckSchemaType (param.Type);
@@ -225,6 +226,8 @@ namespace Mono.Xml.XPath2
 
                private XQueryFunction CompileFunction (FunctionDeclaration func)
                {
+                       if (func.External)
+                               return XQueryFunction.FromQName (func.Name);
                        return new XQueryUserFunction (func.Name, func.Parameters.ToArray (), func.FunctionBody.Expr, func.ReturnType);
                }
 
index 7c81f65237bae41a4374482da8e6bfaef0d5d6f3..3f2fe0f22d7ad020a09c2c9e4b5a44102323a80e 100755 (executable)
@@ -46,7 +46,7 @@ namespace Mono.Xml.XPath2
        // Ideas:\r
        // declare function namespace cli = "http://mono-project.com/xquery/function/cli"\r
        // declare variable v = cli:invoke (cli:new (Microsoft.CSharp:CSharpCodeProvider), CreateCompiler);\r
-       // declare variable v2 = System:Math.Abs (0.5);\r
+       // declare variable v2 = System.Math:Abs (0.5);\r
        //\r
 \r
        public class XQueryCliFunction : XQueryFunction\r
index 590321d099bf7b10e9bc364f37830b73b49d54f3..7f9c15e1b72244a42fb0dbb3db7f22629cbd09f2 100755 (executable)
@@ -160,6 +160,12 @@ namespace Mono.Xml.XPath2
                                );
                }
 
+               internal static XQueryCliFunction FromQName (XmlQualifiedName qname)
+               {
+                       return XQueryCliFunction.CreateFromMethodInfo (
+                               qname, FindNamedMethods (Type.GetType (qname.Namespace), qname.Name));
+               }
+
                private static bool FilterImpl (MemberInfo m, object filterCriteria)
                {
                        return m.Name == filterCriteria.ToString ();
@@ -242,6 +248,8 @@ namespace Mono.Xml.XPath2
                        for (int i = 0; i < args.Count; i++)
                                instParams [i] = Args [i].Type.ToRuntimeType (args [i].Evaluate (iter));
                        object o = Invoke (iter.Context, instParams);
+                       if (o == null)
+                               return new XPathEmptySequence (iter);
                        if (o is XPathSequence)
                                return (XPathSequence) o;
                        XPathItem item = o as XPathItem;
index a210d835640b582760f382227648b46b86692f39..8011cc963e1dc133e27bf7d5940785a18cbf7d47 100755 (executable)
@@ -95,7 +95,7 @@ namespace Mono.Xml.XPath2
                public static XmlQualifiedName FnNodeName (XPathNavigator arg)
                {
                        if (arg == null)
-                               return XmlQualifiedName.Empty;
+                               return null;
 
                        return arg.LocalName == String.Empty ?
                                XmlQualifiedName.Empty :
@@ -105,7 +105,7 @@ namespace Mono.Xml.XPath2
                public static bool FnNilled (XPathNavigator arg)
                {
                        if (arg == null)
-                               return false;
+                               throw new XmlQueryException ("Function nilled() does not allow empty sequence parameter.");
 
                        IXmlSchemaInfo info = arg.NodeType == XPathNodeType.Element ? arg.SchemaInfo : null;
                        return info != null && info.IsNil;
@@ -119,17 +119,23 @@ namespace Mono.Xml.XPath2
                        return FnString (item);
                }
 
+               [MonoTODO]
                public static string FnString (object arg)
                {
+                       if (arg == null)
+                               return String.Empty;
                        XPathNavigator nav = arg as XPathNavigator;
                        if (nav != null)
                                return nav.Value;
+                       // FIXME: it should be exactly the same as "arg cast as xs:string"
                        XPathItem item = ToItem (arg);
                        return item != null ? XQueryConvert.ItemToString (item) : null;
                }
 
+               [MonoTODO]
                public static XPathAtomicValue FnData (object arg)
                {
+                       // FIXME: parameter should be object []
                        XPathNavigator nav = arg as XPathNavigator;
                        if (nav != null) {
                                XmlSchemaType st = nav.SchemaInfo != null ? nav.SchemaInfo.SchemaType : null;
@@ -172,31 +178,66 @@ namespace Mono.Xml.XPath2
                // Numeric Operation
 
                [MonoTODO]
-               public static object FnAbs (ValueType arg)
-               {
-                       throw new NotImplementedException ();
+               public static object FnAbs (object arg)
+               {
+                       if (arg is int)
+                               return System.Math.Abs ((int) arg);
+                       if (arg is long)
+                               return System.Math.Abs ((long) arg);
+                       else if (arg is decimal)
+                               return System.Math.Abs ((decimal) arg);
+                       else if (arg is double)
+                               return System.Math.Abs ((double) arg);
+                       else if (arg is float)
+                               return System.Math.Abs ((float) arg);
+                       else if (arg is short)
+                               return System.Math.Abs ((short) arg);
+                       else if (arg is uint || arg is ulong || arg is ushort)
+                               return arg;
+                       return null;
                }
 
                [MonoTODO]
-               public static object FnCeiling (ValueType arg)
+               public static object FnCeiling (object arg)
                {
-                       throw new NotImplementedException ();
+                       if (arg is decimal) {
+                               decimal d = (decimal) arg;
+                               decimal d2 = Decimal.Floor (d);
+                               return d2 != d ? d2 + 1 : d2;
+                       }
+                       else if (arg is double || arg is float)
+                               return System.Math.Ceiling ((double) arg);
+                       else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+                               return arg;
+                       return null;
                }
 
                [MonoTODO]
-               public static object FnFloor (ValueType arg)
+               public static object FnFloor (object arg)
                {
-                       throw new NotImplementedException ();
+                       if (arg is decimal)
+                               return Decimal.Floor ((decimal) arg);
+                       else if (arg is double || arg is float)
+                               return System.Math.Floor ((double) arg);
+                       else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+                               return arg;
+                       return null;
                }
 
                [MonoTODO]
-               public static object FnRound (ValueType arg)
+               public static object FnRound (object arg)
                {
-                       throw new NotImplementedException ();
+                       if (arg is decimal)
+                               return Decimal.Round ((decimal) arg, 0);
+                       else if (arg is double || arg is float)
+                               return System.Math.Round ((double) arg);
+                       else if (arg is int || arg is long || arg is short || arg is uint || arg is ulong || arg is ushort)
+                               return arg;
+                       return null;
                }
 
                [MonoTODO]
-               public static object FnRoundHalfToEven (ValueType arg)
+               public static object FnRoundHalfToEven (object arg)
                {
                        throw new NotImplementedException ();
                }
@@ -500,10 +541,11 @@ namespace Mono.Xml.XPath2
                        return FnNumber (ctx.CurrentItem);
                }
 
-               public static double FnNumber (XPathItem item)
+               public static double FnNumber (object arg)
                {
-                       if (item == null)
+                       if (arg == null)
                                throw new XmlQueryException ("Context item could not be ndetermined during number() evaluation.");
+                       XPathItem item = ToItem (arg);
                        return XQueryConvert.ItemToDouble (item);
                }
 
index e51c7b499efd7191cdbc14a962f1fd711f10e4df..eb514fe4015f62a4d19b9a3ba5b142777216318d 100755 (executable)
@@ -212,15 +212,33 @@ namespace Mono.Xml.XQuery.Parser
                        }
                }
 
+               private int ParseXQueryComment ()
+               {
+                       while (true) {
+                               int c = ReadChar ();
+                               if (c < 0)
+                                       throw Error ("Unexpected end of query text inside XML processing instruction content");
+                               if (c == ':') {
+                                       if (PeekChar () == ')') {
+                                               ReadChar ();
+                                               tokenValue = CreateValueString ();
+                                               return Token.XML_PI_TO_END;
+                                       }
+                                       else
+                                               AddValueChar (':');
+                               }
+                               else
+                                       AddValueChar ((char) c);
+                       }
+               }
+
                private int ParseXmlPIContent ()
                {
-                       // FIXME: handle ??> correctly
                        while (true) {
-                               int c = PeekChar ();
+                               int c = ReadChar ();
                                if (c < 0)
                                        throw Error ("Unexpected end of query text inside XML processing instruction content");
                                if (c == '?') {
-                                       ReadChar ();
                                        if (PeekChar () == '>') {
                                                ReadChar ();
                                                tokenValue = CreateValueString ();
@@ -238,11 +256,10 @@ namespace Mono.Xml.XQuery.Parser
                {
                        // FIXME: handle ---> correctly
                        while (true) {
-                               int c = PeekChar ();
+                               int c = ReadChar ();
                                if (c < 0)
                                        throw Error ("Unexpected end of query text inside XML comment content");
                                if (c == '-') {
-                                       ReadChar ();
                                        if (PeekChar () == '-') {
                                                ReadChar ();
                                                if (PeekChar () == '>') {
@@ -265,7 +282,7 @@ namespace Mono.Xml.XQuery.Parser
                {
                        // FIXME: handle ]]]> correctly
                        while (true) {
-                               int c = PeekChar ();
+                               int c = ReadChar ();
                                if (c < 0)
                                        throw Error ("Unexpected end of query text inside XML CDATA section content");
                                if (c == ']') {
@@ -421,7 +438,8 @@ namespace Mono.Xml.XQuery.Parser
                                                ReadChar ();
                                                return Token.PRAGMA_OPEN;
                                        }
-                                       return Token.OPEN_PAREN_COLON;
+                                       ParseXQueryComment ();
+                                       return ParseToken (); // start again
                                }
                                return Token.OPEN_PAREN;
                        case ')':