← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~zorba-coders/zorba/markos-scratch into lp:zorba

 

Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/markos-scratch into lp:zorba.

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/markos-scratch/+merge/88172

types-related optimization for the general comparison operator
-- 
https://code.launchpad.net/~zorba-coders/zorba/markos-scratch/+merge/88172
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/runtime/booleans/BooleanImpl.cpp'
--- src/runtime/booleans/BooleanImpl.cpp	2012-01-10 10:52:15 +0000
+++ src/runtime/booleans/BooleanImpl.cpp	2012-01-11 10:33:29 +0000
@@ -750,65 +750,63 @@
 void CompareIterator::generalCasting(
     const QueryLoc& loc,
     const TypeManager* tm,
-    store::Item_t& aItem0,
-    store::Item_t& aItem1,
+    store::Item_t& item0,
+    store::Item_t& item1,
     store::Item_t& castItem0,
     store::Item_t& castItem1)
 {
-  RootTypeManager& rtm = GENV_TYPESYSTEM;
-
-  xqtref_t type0 = tm->create_value_type(aItem0);
-  xqtref_t type1 = tm->create_value_type(aItem1);
-
-  if (TypeOps::is_subtype(tm, *type0, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
+  store::SchemaTypeCode type0 = item0->getTypeCode();
+  store::SchemaTypeCode type1 = item1->getTypeCode();
+
+  if (TypeOps::is_subtype(type0, store::XS_UNTYPED_ATOMIC))
   {
-    if (TypeOps::is_numeric(tm, *type1))
+    if (TypeOps::is_numeric(type1))
     {
-      GenericCast::castToAtomic(castItem0, aItem0, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
+      GenericCast::castToAtomic(castItem0, item0, store::XS_DOUBLE, tm, NULL, loc);
 
-      GenericCast::promote(castItem1, aItem1, &*rtm.DOUBLE_TYPE_ONE, tm, loc);
-    }
-    else if (TypeOps::is_subtype(tm, *type1, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
-    {
-      GenericCast::castToAtomic(castItem0, aItem0, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
-      GenericCast::castToAtomic(castItem1, aItem1, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
-    }
-    else if (TypeOps::is_subtype(tm, *type1, *rtm.STRING_TYPE_ONE))
-    {
-      GenericCast::castToAtomic(castItem0, aItem0, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
-      castItem1.transfer(aItem1);
+      GenericCast::promote(castItem1, item1, store::XS_DOUBLE, tm, loc);
+    }
+    else if (TypeOps::is_subtype(type1, store::XS_UNTYPED_ATOMIC))
+    {
+      GenericCast::castToAtomic(castItem0, item0, store::XS_STRING, tm, NULL, loc);
+      GenericCast::castToAtomic(castItem1, item1, store::XS_STRING, tm, NULL, loc);
+    }
+    else if (TypeOps::is_subtype(type1, store::XS_STRING))
+    {
+      GenericCast::castToAtomic(castItem0, item0, store::XS_STRING, tm, NULL, loc);
+      castItem1.transfer(item1);
     }
     else
     {
-      GenericCast::castToAtomic(castItem0, aItem0, &*type1, tm, NULL, loc);
-      castItem1.transfer(aItem1);
+      GenericCast::castToAtomic(castItem0, item0, type1, tm, NULL, loc);
+      castItem1.transfer(item1);
     }
   }
-  else if (TypeOps::is_subtype(tm, *type1, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
+  else if (TypeOps::is_subtype(type1, store::XS_UNTYPED_ATOMIC))
   {
-    if (TypeOps::is_numeric(tm, *type0))
+    if (TypeOps::is_numeric(type0))
     {
-      GenericCast::castToAtomic(castItem1, aItem1, &*rtm.DOUBLE_TYPE_ONE, tm, NULL, loc);
-      GenericCast::promote(castItem0, aItem0, &*rtm.DOUBLE_TYPE_ONE, tm, loc);
+      GenericCast::castToAtomic(castItem1, item1, store::XS_DOUBLE, tm, NULL, loc);
+      GenericCast::promote(castItem0, item0, store::XS_DOUBLE, tm, loc);
     }
-    else if (TypeOps::is_subtype(tm, *type0, *rtm.STRING_TYPE_ONE))
+    else if (TypeOps::is_subtype(type0, store::XS_STRING))
     {
-      GenericCast::castToAtomic(castItem1, aItem1, &*rtm.STRING_TYPE_ONE, tm, NULL, loc);
-      castItem0.transfer(aItem0);
+      GenericCast::castToAtomic(castItem1, item1, store::XS_STRING, tm, NULL, loc);
+      castItem0.transfer(item0);
     }
     else
     {
-      GenericCast::castToAtomic(castItem1, aItem1, &*type0, tm, NULL, loc);
-      castItem0.transfer(aItem0);
+      GenericCast::castToAtomic(castItem1, item1, type0, tm, NULL, loc);
+      castItem0.transfer(item0);
     }
   }
   else
   {
-    if (!GenericCast::promote(castItem0, aItem0, &*type1, tm, loc))
-      castItem0.transfer(aItem0);
+    if (!GenericCast::promote(castItem0, item0, type1, tm, loc))
+      castItem0.transfer(item0);
 
-    if (!GenericCast::promote(castItem1, aItem1, &*type0, tm, loc))
-      castItem1.transfer(aItem1);
+    if (!GenericCast::promote(castItem1, item1, type0, tm, loc))
+      castItem1.transfer(item1);
   }
 }
 

=== modified file 'src/types/casting.cpp'
--- src/types/casting.cpp	2012-01-10 10:52:15 +0000
+++ src/types/casting.cpp	2012-01-11 10:33:29 +0000
@@ -34,6 +34,7 @@
 #include "store/api/item_factory.h"
 #include "store/api/item.h"
 #include "store/api/store.h"
+#include "store/api/xs_type_codes.h"
 
 #include "types/typeops.h"
 #include "types/typemanagerimpl.h"
@@ -65,18 +66,64 @@
 
 struct ErrorInfo
 {
-  const XQType   * theSourceType;
-  const XQType   * theTargetType;
-  const QueryLoc & theLoc;
+  const XQType          * theSourceType;
+  const XQType          * theTargetType;
+  store::SchemaTypeCode   theSourceTypeCode;
+  store::SchemaTypeCode   theTargetTypeCode;
+  const QueryLoc        & theLoc;
+
+  ErrorInfo(
+      const XQType* source,
+      const XQType* target,
+      const QueryLoc& loc)
+    :
+    theSourceType(source),
+    theTargetType(target),
+    theLoc(loc)
+  {
+    assert(source != NULL && target != NULL);
+  }
+
+  ErrorInfo(
+      store::SchemaTypeCode source,
+      store::SchemaTypeCode target,
+      const QueryLoc& loc)
+    :
+    theSourceType(NULL),
+    theTargetType(NULL),
+    theSourceTypeCode(source),
+    theTargetTypeCode(target),
+    theLoc(loc)
+  {
+  }
 };
 
 
-#define TYPE_EXCEPTION( ERROR_CODE, ERROR_INFO )  \
-  XQUERY_EXCEPTION(ERROR_CODE,                    \
-  ERROR_PARAMS(*(ERROR_INFO).theSourceType,       \
-               ZED( NoCastTo_34o ),               \
-               *(ERROR_INFO).theTargetType ),     \
-  ERROR_LOC(ERROR_INFO.theLoc) )
+void throwTypeException(const Diagnostic& errcode, const ErrorInfo& info)
+{              
+  if (info.theSourceType)
+  {                      
+    throw XQUERY_EXCEPTION_VAR(errcode,
+    ERROR_PARAMS(*info.theSourceType, ZED(NoCastTo_34o), *info.theTargetType),
+    ERROR_LOC(info.theLoc));
+  }                                           
+  else                                        
+  {
+    TypeManager& tm = GENV_TYPESYSTEM;
+                                     
+    xqtref_t sourceType =
+    tm.create_builtin_atomic_type(info.theSourceTypeCode,
+                                  TypeConstants::QUANT_ONE);
+
+    xqtref_t targetType =
+    tm.create_builtin_atomic_type(info.theTargetTypeCode,
+                                  TypeConstants::QUANT_ONE);
+
+    throw XQUERY_EXCEPTION_VAR(errcode,
+    ERROR_PARAMS(*sourceType, ZED(NoCastTo_34o), *targetType),
+    ERROR_LOC(info.theLoc));    
+  }                                           
+}
 
 
 /*******************************************************************************
@@ -149,7 +196,8 @@
   }
   catch (std::invalid_argument const&) 
   {
-    throw TYPE_EXCEPTION(err::FORG0001, aErrorInfo);
+    throwTypeException(err::FORG0001, aErrorInfo);
+    return NULL;
   }
   catch ( std::range_error const& ) 
   {
@@ -167,7 +215,8 @@
   }
   catch (std::invalid_argument const& ) 
   {
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException(err::FORG0001, aErrorInfo);
+    return NULL;
   }
   catch (std::range_error const& ) 
   {
@@ -185,7 +234,8 @@
   }
   catch ( std::exception const& ) 
   {
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
+    return NULL;
   }
 }
 
@@ -199,11 +249,13 @@
   }
   catch ( std::invalid_argument const& ) 
   {
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
+    return NULL;
   }
   catch ( std::range_error const& ) 
   {
-    throw TYPE_EXCEPTION( err::FOAR0002, aErrorInfo );
+    throwTypeException( err::FOAR0002, aErrorInfo );
+    return NULL;
   }
 }
 
@@ -216,7 +268,8 @@
   if (0 == (err = Duration::parseDuration(strval.c_str(), strval.size(), d)))
     return aFactory->createDuration(result, &d);
 
-  throw TYPE_EXCEPTION(err::FORG0001, aErrorInfo);
+  throwTypeException(err::FORG0001, aErrorInfo);
+  return NULL;
 }
 
 
@@ -228,7 +281,8 @@
   if (0 == (err = Duration::parseYearMonthDuration(strval.c_str(), strval.size(), d)))
     return aFactory->createYearMonthDuration(result, &d);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -240,7 +294,8 @@
   if (0 == (err = Duration::parseDayTimeDuration(strval.c_str(), strval.size(), d)))
     return aFactory->createDayTimeDuration(result, &d);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -250,7 +305,8 @@
   if (0 == DateTime::parseDateTime(strval.c_str(), strval.size(), dt))
     return aFactory->createDateTime(result, &dt);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -260,7 +316,8 @@
   if (0 == DateTime::parseTime(strval.c_str(), strval.size(), t))
     return aFactory->createTime(result, &t);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -270,7 +327,8 @@
   if (0 == DateTime::parseDate(strval.c_str(), strval.size(), d))
     return aFactory->createDate(result, &d);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -280,7 +338,8 @@
   if (0 == DateTime::parseGYearMonth(strval.c_str(), strval.size(), ym))
     return aFactory->createGYearMonth(result, &ym);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -290,7 +349,8 @@
   if (0 == DateTime::parseGYear(strval.c_str(), strval.size(), y))
     return aFactory->createGYear(result, &y);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -300,7 +360,8 @@
   if (0 == DateTime::parseGMonthDay(strval.c_str(), strval.size(), md))
     return aFactory->createGMonthDay(result, &md);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -310,7 +371,8 @@
   if (0 == DateTime::parseGDay(strval.c_str(), strval.size(), d))
     return aFactory->createGDay(result, &d);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -320,7 +382,8 @@
   if (0 == DateTime::parseGMonth(strval.c_str(), strval.size(), m))
     return aFactory->createGMonth(result, &m);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -357,14 +420,15 @@
   }
   else
   {
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
+    return NULL;
   }
 
   pos = str - strval.c_str();
   ascii::skip_whitespace(strval.c_str(), len, &pos);
 
   if (pos != len)
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
 
   return aFactory->createBoolean(result, lRetValue);
 }
@@ -376,7 +440,8 @@
   if (xs_base64Binary::parseString(strval, n))
     return aFactory->createBase64Binary(result, n);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -386,7 +451,8 @@
   if (xs_hexBinary::parseString(strval, n))
     return aFactory->createHexBinary(result, n);
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -414,7 +480,7 @@
   zstring::size_type lidx = strval.rfind(":", strval.size(), 1);
 
   if (idx != lidx)
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
 
   zstring nsuri;
   zstring prefix;
@@ -434,7 +500,7 @@
     prefix = strval.substr(0, idx);
 
     if (!GenericCast::instance()->castableToNCName(prefix))
-      throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+      throwTypeException( err::FORG0001, aErrorInfo );
 
     if (nsCtx)
     {
@@ -446,7 +512,7 @@
   }
 
   if (!GenericCast::instance()->castableToNCName(local))
-    throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+    throwTypeException( err::FORG0001, aErrorInfo );
 
   return aFactory->createQName(result, nsuri, prefix, local);
 }
@@ -667,7 +733,8 @@
   }
   catch ( std::exception const& /*e*/ ) 
   {
-    throw TYPE_EXCEPTION( err::FOCA0002, aErrorInfo );
+    throwTypeException( err::FOCA0002, aErrorInfo );
+    return NULL;
   }
 }
 
@@ -680,7 +747,8 @@
   }
   catch ( std::exception const& ) 
   {
-    throw TYPE_EXCEPTION( err::FOCA0002, aErrorInfo );
+    throwTypeException( err::FOCA0002, aErrorInfo );
+    return NULL;
   }
 }
 
@@ -721,7 +789,8 @@
   }
   catch ( std::exception const& ) 
   {
-    throw TYPE_EXCEPTION( err::FOCA0002, aErrorInfo );
+    throwTypeException(err::FOCA0002, aErrorInfo);
+    return NULL;
   }
 }
 
@@ -734,7 +803,8 @@
   }
   catch ( std::exception const& ) 
   {
-    throw TYPE_EXCEPTION( err::FOCA0002, aErrorInfo );
+    throwTypeException( err::FOCA0002, aErrorInfo );
+    return NULL;
   }
 }
 
@@ -1351,7 +1421,8 @@
     ZORBA_ASSERT(false);
   }
 
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -1503,7 +1574,8 @@
   default:
     ZORBA_ASSERT (false);
   }
-  throw TYPE_EXCEPTION( err::FORG0001, aErrorInfo );
+  throwTypeException( err::FORG0001, aErrorInfo );
+  return NULL;
 }
 
 
@@ -1676,7 +1748,7 @@
 bool GenericCast::castToAtomic(
     store::Item_t& result,
     zstring& str,
-    const XQType* aTargetType,
+    const XQType* targetType,
     const TypeManager* tm,
     namespace_context* aNsCtx,
     const QueryLoc& loc)
@@ -1686,24 +1758,24 @@
 
   const XQType* sourceType = rtm.STRING_TYPE_ONE.getp();
 
-  ErrorInfo lErrorInfo = {&*sourceType, aTargetType, loc};
+  ErrorInfo lErrorInfo(sourceType, targetType, loc);
 
-  if (!TypeOps::is_atomic(tm, *aTargetType))
-    RAISE_ERROR(err::XPST0051, loc, ERROR_PARAMS(aTargetType));
+  if (!TypeOps::is_atomic(tm, *targetType))
+    RAISE_ERROR(err::XPST0051, loc, ERROR_PARAMS(targetType));
 
 #ifndef ZORBA_NO_XMLSCHEMA
-  if (aTargetType->type_kind() == XQType::USER_DEFINED_KIND)
+  if (targetType->type_kind() == XQType::USER_DEFINED_KIND)
   {
     store::Item_t baseItem;
 
     bool success = tm->getSchema()->parseUserAtomicTypes(str,
-                                                         aTargetType,
+                                                         targetType,
                                                          baseItem,
                                                          aNsCtx,
                                                          loc);
     if (success)
     {
-      const UserDefinedXQType* udt = static_cast<const UserDefinedXQType*>(aTargetType);
+      const UserDefinedXQType* udt = static_cast<const UserDefinedXQType*>(targetType);
       store::Item_t typeName = udt->get_qname();
 
       GENV_ITEMFACTORY->createUserTypedAtomicItem(result, baseItem, typeName);
@@ -1716,7 +1788,7 @@
 
   store::Item_t lItem;
   ATOMIC_CODE_T sourceTypeCode = store::XS_STRING;
-  ATOMIC_CODE_T targetTypeCode = TypeOps::get_atomic_type_code(*aTargetType);
+  ATOMIC_CODE_T targetTypeCode = TypeOps::get_atomic_type_code(*targetType);
   bool valid = true;
 
   if (theMapping[sourceTypeCode] == theMapping[targetTypeCode])
@@ -1728,7 +1800,7 @@
     CastFunc lCastFunc = theCastMatrix[theMapping[sourceTypeCode]]
                                       [theMapping[targetTypeCode]];
     if (lCastFunc == 0)
-      throw TYPE_EXCEPTION(err::XPTY0004, lErrorInfo);
+      throwTypeException(err::XPTY0004, lErrorInfo);
 
     valid = (*lCastFunc)(result,
                          lItem,
@@ -1788,7 +1860,7 @@
   // std::cout << "\t\t  tgtType: " << aTargetType->get_qname()->getLocalName()->c_str()
   //           << " @ " << aTargetType->get_qname()->getNamespace()->c_str() << "\n";
 
-  ErrorInfo errorInfo = {&*sourceType, targetType, loc};
+  ErrorInfo errorInfo(sourceType.getp(), targetType, loc);
 
   if (!TypeOps::is_atomic(tm, *targetType))
     RAISE_ERROR(err::XPST0051, loc, ERROR_PARAMS(targetType));
@@ -1820,18 +1892,18 @@
   }
 
   if (sourceTypeCode == store::XS_ANY_ATOMIC)
-    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+    throwTypeException(err::XPTY0004, errorInfo);
 
   if (targetTypeCode == store::XS_NCNAME &&
       sourceTypeCode != store::XS_STRING &&
       sourceTypeCode != store::XS_NCNAME &&
       sourceTypeCode != store::XS_UNTYPED_ATOMIC)
-    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+    throwTypeException(err::XPTY0004, errorInfo);
 
   CastFunc castFunc = theCastMatrix[theMapping[sourceTypeCode]]
                                     [theMapping[targetTypeCode]];
   if (castFunc == 0)
-    throw TYPE_EXCEPTION(err::XPTY0004, errorInfo);
+    throwTypeException(err::XPTY0004, errorInfo);
 
   if (theMapping[sourceTypeCode] == theMapping[store::XS_STRING])
   {
@@ -1865,6 +1937,87 @@
 
 
 /*******************************************************************************
+  Cast, if possible, a given atomic item SI to an atomic item TI of a given 
+  type TT. If the cast is not allowed, the method raises an error. If the cast
+  is not possible, the method may raise an error or return false (TODO fix 
+  this!). Otherwise, it returns true.
+********************************************************************************/
+bool GenericCast::castToAtomic(
+    store::Item_t&        result,
+    store::Item_t&        item,
+    store::SchemaTypeCode targetType,
+    const TypeManager*    tm,
+    namespace_context*    nsCtx,
+    const QueryLoc&       loc)
+{
+  RootTypeManager& rtm = GENV_TYPESYSTEM;
+  store::ItemFactory* factory = GENV_ITEMFACTORY;
+  zstring sourceString;
+
+  ZORBA_ASSERT(item->isAtomic());
+
+  store::SchemaTypeCode sourceType = item->getTypeCode();
+
+  ErrorInfo errorInfo(sourceType, targetType, loc);
+
+  if (sourceType == targetType)
+  {
+    result.transfer(item);
+    return true;
+  }
+
+  if (targetType == store::XS_NOTATION ||
+      targetType == store::XS_ANY_ATOMIC)
+  {
+    RAISE_ERROR(err::XPST0080, loc, ERROR_PARAMS(*errorInfo.theTargetType));
+  }
+
+  if (sourceType == store::XS_ANY_ATOMIC)
+    throwTypeException(err::XPTY0004, errorInfo);
+
+  if (targetType == store::XS_NCNAME &&
+      sourceType != store::XS_STRING &&
+      sourceType != store::XS_NCNAME &&
+      sourceType != store::XS_UNTYPED_ATOMIC)
+    throwTypeException(err::XPTY0004, errorInfo);
+
+  CastFunc castFunc = theCastMatrix[theMapping[sourceType]]
+                                    [theMapping[targetType]];
+  if (castFunc == 0)
+    throwTypeException(err::XPTY0004, errorInfo);
+
+  if (theMapping[sourceType] == theMapping[store::XS_STRING])
+  {
+    item->getStringValue2(sourceString);
+  }
+
+  bool valid = (*castFunc)(result,
+                           item,
+                           sourceString,
+                           factory,
+                           nsCtx,
+                           errorInfo);
+
+  DownCastFunc downCastFunc = theDownCastMatrix[theMapping[targetType]];
+
+  if (downCastFunc != 0 &&
+      targetType != store::XS_STRING &&
+      targetType != store::XS_INTEGER)
+  {
+    valid = (*downCastFunc)(result,
+                            &*result,
+                            rtm,
+                            targetType,
+                            factory,
+                            errorInfo);
+  }
+
+  assert(valid);
+  return valid;
+}
+
+
+/*******************************************************************************
 
 ********************************************************************************/
 void castToUserDefinedType(
@@ -1874,7 +2027,7 @@
     const XQType* aTargetType,
     const QueryLoc& loc)
 {
-  ErrorInfo lErrorInfo = {aSourceType, aTargetType, loc};
+  ErrorInfo lErrorInfo(aSourceType, aTargetType, loc);
 
   // std::cout << "-castToUserDefinedType: " << aItem.getp()->getStringValue()->c_str()
   //           << " srcType: " << aSourceType->get_qname()->getLocalName()->c_str()
@@ -1889,7 +2042,7 @@
   if (aSourceType->type_kind() != XQType::ATOMIC_TYPE_KIND ||
       (TypeOps::get_atomic_type_code(*aSourceType) != store::XS_STRING))
   {
-    throw TYPE_EXCEPTION(err::FORG0001, lErrorInfo);
+    throwTypeException(err::FORG0001, lErrorInfo);
   }
 
   const UserDefinedXQType* udt = static_cast<const UserDefinedXQType*>(aTargetType);
@@ -1973,17 +2126,11 @@
   else if (!TypeOps::is_subtype(tm, *sourceType, *rtm.STRING_TYPE_ONE) &&
            !TypeOps::is_equal(tm, *sourceType, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
   {
-    throw XQUERY_EXCEPTION(
-      err::XPTY0004,
-      ERROR_PARAMS(
-        ZED( BadType_23o ), *sourceType,
-        ZED( NoCastTo_45o ), "QName"
-      ),
-      ERROR_LOC( loc )
-    );
+    RAISE_ERROR(err::XPTY0004, loc,
+    ERROR_PARAMS(ZED(BadType_23o), *sourceType, ZED(NoCastTo_45o), "QName"));
   }
 
-  ErrorInfo errorInfo = { sourceType.getp(), rtm.QNAME_TYPE_ONE.getp(), loc };
+  ErrorInfo errorInfo(sourceType.getp(), rtm.QNAME_TYPE_ONE.getp(), loc);
 
   zstring strval;
   item->getStringValue2(strval);
@@ -1992,7 +2139,7 @@
   zstring::size_type idx = strval.find(":");
   zstring::size_type lidx = strval.rfind(":", strval.size(), 1);
   if (idx != lidx)
-    throw TYPE_EXCEPTION( err::FORG0001, errorInfo );
+    throwTypeException(err::FORG0001, errorInfo);
 
   zstring prefix;
   zstring nsuri;
@@ -2012,19 +2159,19 @@
     prefix = strval.substr(0, idx);
 
     if (!GenericCast::instance()->castableToNCName(prefix))
-      throw TYPE_EXCEPTION( err::FORG0001, errorInfo );
+      throwTypeException(err::FORG0001, errorInfo);
 
     if (nsCtx)
     {
       if (!nsCtx->findBinding(prefix, nsuri))
-        throw XQUERY_EXCEPTION( err::FONS0004, ERROR_PARAMS( prefix ) );
+        throw XQUERY_EXCEPTION(err::FONS0004, ERROR_PARAMS(prefix));
     }
 
     local = strval.substr(idx + 1);
   }
 
   if (!GenericCast::instance()->castableToNCName(local.c_str()))
-    throw TYPE_EXCEPTION( err::FORG0001, errorInfo );
+    throwTypeException(err::FORG0001, errorInfo );
 
   return GENV_ITEMFACTORY->createQName(result, nsuri, prefix, local);
 }
@@ -2450,6 +2597,62 @@
 }
 
 
+/*******************************************************************************
+
+********************************************************************************/
+bool GenericCast::promote(
+    store::Item_t& result,
+    store::Item_t& item,
+    store::SchemaTypeCode targetType,
+    const TypeManager* tm,
+    const QueryLoc& loc)
+{
+  assert(item->isAtomic());
+
+  store::SchemaTypeCode itemType = item->getTypeCode();
+
+  if (TypeOps::is_subtype(itemType, targetType))
+  {
+    result.transfer(item);
+    return result != NULL;
+  }
+
+  if (TypeOps::is_subtype(itemType, store::XS_UNTYPED_ATOMIC) &&
+      ! TypeOps::is_subtype(targetType, store::XS_QNAME))
+  {
+    // untyped --> target type
+    return castToAtomic(result, item, targetType, tm, NULL, loc);
+  }
+  else if (TypeOps::is_subtype(targetType, store::XS_FLOAT))
+  {
+    // decimal --> xs:float
+    if (TypeOps::is_subtype(itemType, store::XS_DECIMAL))
+    {
+      return castToAtomic(result, item, targetType, tm, NULL, loc);
+    }
+  }
+  else if (TypeOps::is_subtype(targetType, store::XS_DOUBLE))
+  {
+    // Decimal/Float --> xs:double
+    if (TypeOps::is_subtype(itemType, store::XS_DECIMAL) ||
+        TypeOps::is_subtype(itemType, store::XS_FLOAT))
+    {
+      return castToAtomic(result, item, targetType, tm, NULL, loc);
+    }
+  }
+  else if (TypeOps::is_subtype(targetType, store::XS_STRING))
+  {
+    // URI --> xs:String Promotion
+    if (TypeOps::is_subtype(itemType, store::XS_ANY_URI))
+    {
+      return castToAtomic(result, item, store::XS_STRING, tm, NULL, loc);
+    }
+  }
+
+  return false;
+}
+
+
 #undef ATOMIC_TYPE
 
 

=== modified file 'src/types/casting.h'
--- src/types/casting.h	2012-01-10 10:52:15 +0000
+++ src/types/casting.h	2012-01-11 10:33:29 +0000
@@ -66,16 +66,23 @@
   
   /**
    * Promotes the passed item to the passed target type.
-   * @param aItem
-   * @param aTargetType
+   * @param item
+   * @param targetType
    * @return 0 if promotion is not possible else promoted item
    *         if the item type is a subtype of the target type, then
    *         the passed item is returned
    */
   static bool promote(
         store::Item_t& result,
-        store::Item_t& aItem,
-        const XQType* aTargetType,
+        store::Item_t& item,
+        const XQType* targetType,
+        const TypeManager* tm,
+        const QueryLoc& loc);
+
+  static bool promote(
+        store::Item_t& result,
+        store::Item_t& item,
+        store::SchemaTypeCode targetType,
         const TypeManager* tm,
         const QueryLoc& loc);
 
@@ -97,10 +104,23 @@
    */
   static bool castToAtomic(
         store::Item_t& result,
-        store::Item_t& aItem, 
-        const XQType* aTargetType,
-        const TypeManager* tm, 
-        namespace_context* aNCtx,
+        store::Item_t& item, 
+        const XQType* targetType,
+        const TypeManager* tm, 
+        namespace_context* nameCtx,
+        const QueryLoc& loc);
+
+  /**
+   * Executes the casting of the passed item. If the passed item has the same
+   * type or a subtype of the passed targetType, the passed item is directly
+   * returned.
+   */
+  static bool castToAtomic(
+        store::Item_t& result,
+        store::Item_t& item, 
+        store::SchemaTypeCode targetType,
+        const TypeManager* tm, 
+        namespace_context* nameCtx,
         const QueryLoc& loc);
 
   static bool castToSimple(

=== modified file 'src/types/typeops.cpp'
--- src/types/typeops.cpp	2012-01-10 13:54:05 +0000
+++ src/types/typeops.cpp	2012-01-11 10:33:29 +0000
@@ -288,6 +288,15 @@
 /*******************************************************************************
 
 ********************************************************************************/
+bool TypeOps::is_numeric(store::SchemaTypeCode type)
+{
+  return store::XS_FLOAT <= type && type <= store::XS_POSITIVE_INTEGER;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
 bool TypeOps::is_numeric(const TypeManager* tm, const XQType& type)
 {
   CHECK_IN_SCOPE(tm, type, QueryLoc::null);

=== modified file 'src/types/typeops.h'
--- src/types/typeops.h	2012-01-10 13:54:05 +0000
+++ src/types/typeops.h	2012-01-11 10:33:29 +0000
@@ -134,6 +134,12 @@
    * numeric type (xs:decimal, xs:double, or xs:float)
    */
   static bool is_numeric(const TypeManager* tm, const XQType& type);
+
+  /**
+   * Returns true is the given sequence type is a subtype of an atomic builtin
+   * numeric type (xs:decimal, xs:double, or xs:float)
+   */
+  static bool is_numeric(store::SchemaTypeCode type);
  
   /**
    * Returns true is the given sequence type is a subtype of an atomic builtin
@@ -164,7 +170,7 @@
   /*
    * Returns true if _subtype_ is a subtype of _supertype_, false otherwise.
    */
-  bool is_subtype(
+  static bool is_subtype(
         store::SchemaTypeCode subtype,
         store::SchemaTypeCode supertype);
 


Follow ups