Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/import-cycles 
into lp:zorba.

Commit message:
Implemented resolution of module-import cycles according to the W3C XQuery 3.0 
spec

Requested reviews:
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/import-cycles/+merge/162924

Implemented resolution of module-import cycles according to the W3C XQuery 3.0 
spec
-- 
https://code.launchpad.net/~zorba-coders/zorba/import-cycles/+merge/162924
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2013-05-07 22:46:58 +0000
+++ ChangeLog	2013-05-08 03:46:36 +0000
@@ -24,6 +24,7 @@
   * Added xqxq:variable-value function.
   * Added canonicalize function to modules/xml.
   * Added support for xs:dateTimeStamp type from XMLSchema 1.1, bug #924754.
+  * Implemented resolution of module-import cycles according to the W3C XQuery 3.0 spec.
   * Added uri:parse() and uri:serialize() functions to URI module for
     parsing URI into components and forming URIs from components.
   * Added support for the standardized require-feature and prohibit-feature

=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp	2013-04-25 20:41:11 +0000
+++ src/api/dynamiccontextimpl.cpp	2013-05-08 03:46:36 +0000
@@ -257,7 +257,7 @@
     catch (ZorbaException const& e)
     {
       // Normally, we should be throwing an exception if the variable has not
-      // been declared inside the xquery program, but this cases many failures
+      // been declared inside the xquery program, but this causes many failures
       // with the w3c XQTS.
       if (e.diagnostic() == err::XPST0008)
       {

=== modified file 'src/compiler/parsetree/parsenodes.h'
--- src/compiler/parsetree/parsenodes.h	2013-03-23 13:10:33 +0000
+++ src/compiler/parsetree/parsenodes.h	2013-05-08 03:46:36 +0000
@@ -421,9 +421,9 @@
     rchandle<SIND_DeclList>,
     rchandle<VFO_DeclList>);
 
-  rchandle<SIND_DeclList> get_sind_list() const { return sind_list_h; }
+  SIND_DeclList* get_sind_list() const { return sind_list_h.getp(); }
 
-  rchandle<VFO_DeclList> get_vfo_list() const { return vfo_list_h; }
+  VFO_DeclList* get_vfo_list() const { return vfo_list_h.getp(); }
 
   // returns true if the value was NULL before the call
   bool set_sind_list(SIND_DeclList* list);
@@ -454,6 +454,16 @@
   void push_back(rchandle<parsenode> decl);
 
   void accept(parsenode_visitor&) const;
+
+  const std::vector<rchandle<parsenode> >& getDecls() const
+  {
+    return theDecls;
+  }
+
+  const std::vector<rchandle<parsenode> >& getModuleImports() const
+  {
+    return theModuleImports;
+  }
 };
 
 
@@ -892,7 +902,7 @@
     :
     parsenode(loc),
     theInitExpr(expr),
-    theIsExternal(false)
+    theIsExternal(true)
   {
   }
 

=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp	2013-05-06 05:34:01 +0000
+++ src/compiler/translator/translator.cpp	2013-05-08 03:46:36 +0000
@@ -443,16 +443,16 @@
   ----------------
   In non-DEBUGGER mode, this stack remains empty.
 
-  export_sctx :
-  -------------
+  theExportSctx :
+  ---------------
 
-  In case this is a library module translator, export_sctx is populated with
+  In case this is a library module translator, theExportSctx is populated with
   the variable, function, and xqddf declarations that are exported by the
   module, i.e., the var, udf, and xqddf declarations that appear in the prolog
-  of this module. The export_sctx is created by the importing module, populated
+  of this module. TheExportSctx is created by the importing module, populated
   by the imported module, and then merged by the importing module into its own
-  sctx. export_sctx is "shared" between importing and imported modules via the
-  theModulesInfo->mod_sctx_map. export_sctx is needed because module import is
+  sctx. theExportSctx is "shared" between importing and imported modules via the
+  theModulesInfo->mod_sctx_map. theExportSctx is needed because module import is
   not transitive: If M1 imports M2 and M2 imports M3, then M3's declarations
   must be seen by M2, but not by M1. This means, that the regular root sctx
   S2 of M2 will contain the decls from both M2 and M3. So, M1 should not import
@@ -648,7 +648,7 @@
 
   std::stack<csize>                      theSctxIdStack;
 
-  static_context                       * export_sctx;
+  static_context                       * theExportSctx;
 
   rchandle<namespace_context>            theNSCtx;
 
@@ -739,7 +739,7 @@
   theCurrSctxId(rootSctxId),
   theRootSctx(rootSctx),
   theSctx(rootSctx),
-  export_sctx(NULL),
+  theExportSctx(NULL),
   theNSCtx(new namespace_context(theSctx)),
   thePrintDepth(0),
   theScopeDepth(0),
@@ -788,6 +788,12 @@
 }
 
 
+bool isRootTranslator() const
+{
+  return theRootTranslator == this;
+}
+
+
 const store::Item_t& getDotItemVarName() const
 {
   return theRootTranslator->theDotItemVarName;
@@ -972,7 +978,7 @@
 *******************************************************************************/
 inline bool inLibraryModule()
 {
-  return export_sctx != NULL;
+  return theExportSctx != NULL;
 }
 
 
@@ -1377,7 +1383,7 @@
   Create a binding between the given (function qname item, arity) pair and the
   given function object. The binding is created in (a) the current sctx of this
   module, (b) the query-level sctx that gathers all declaration of functions and
-  variables from all modules, and (c) the export_sctx (if any). Raise error if
+  variables from all modules, and (c) the theExportSctx (if any). Raise error if
   such a binding exists already in any of these sctxs.
 ********************************************************************************/
 void bind_fn(
@@ -1389,9 +1395,9 @@
 
   theModulesInfo->theGlobalSctx->bind_fn(f, nargs, loc);
 
-  if (export_sctx != NULL)
+  if (theExportSctx != NULL)
   {
-    export_sctx->bind_fn(f, nargs, loc);
+    theExportSctx->bind_fn(f, nargs, loc);
   }
 }
 
@@ -2481,7 +2487,9 @@
 
   if (v.get_encoding() != "utf-8" &&
       !utf8::match_whole(v.get_encoding(), "^[A-Za-z]([A-Za-z0-9._]|[-])*$"))
+  {
     RAISE_ERROR(err::XQST0087, loc, ERROR_PARAMS(v.get_encoding()));
+  }
 
   std::string versionStr = v.get_version().str();
 
@@ -2717,6 +2725,12 @@
   bind_var(theModulesInfo->theDotPosVar, theRootSctx);
   bind_var(theModulesInfo->theDotSizeVar, theRootSctx);
 
+  if (v.get_version_decl() == NULL)
+  {
+    theRootSctx->
+    set_xquery_version(theRootTranslator->theRootSctx->xquery_version());
+  }
+
   return no_state;
 }
 
@@ -2788,7 +2802,7 @@
   found = theModulesInfo->mod_sctx_map.get(uri, lTmpCtx);
   ZORBA_ASSERT(found);
 
-  export_sctx = lTmpCtx;
+  theExportSctx = lTmpCtx;
 }
 
 
@@ -2820,12 +2834,82 @@
 void* begin_visit(const Prolog& v)
 {
   TRACE_VISIT();
-  return no_state;
+
+  if (theSctx->xquery_version() >= StaticContextConsts::xquery_version_3_0)
+  {
+    SIND_DeclList* sindList = v.get_sind_list();
+    VFO_DeclList* vfoList = v.get_vfo_list();
+
+    std::vector<rchandle<parsenode> >::const_iterator ite;
+    std::vector<rchandle<parsenode> >::const_iterator end;
+
+    // Process SIND declarations, except from module imports
+    if (sindList)
+    {
+      ite = sindList->getDecls().begin();
+      end = sindList->getDecls().end();
+
+      for (; ite != end; ++ite)
+      {
+        (*ite)->accept(*this);
+      }
+
+      ite = sindList->getModuleImports().begin();
+      end = sindList->getModuleImports().end();
+
+      for (; ite != end; ++ite)
+      {
+        ModuleImport* modImport = static_cast<ModuleImport*>((*ite).getp());
+
+        // Create a ModuleVersion based on the input namespace URI.
+        const ModuleVersion modVer(modImport->get_uri());
+
+        // targetNS is the target ns *without* any version-declaration fragment.
+        zstring targetNS = modVer.namespace_uri();
+        zstring pfx = modImport->get_prefix();
+
+        bindModuleImportPrefix(targetNS, pfx, modImport->get_location());
+      }
+    }
+
+    // process VFO decls, except UDF bodies and var initializer exprs
+    if (vfoList)
+      preprocessVFOList(*vfoList);
+
+    // Process module imports
+    if (sindList)
+    {
+      ite = sindList->getModuleImports().begin();
+      end = sindList->getModuleImports().end();
+
+      for (; ite != end; ++ite)
+      {
+        (*ite)->accept(*this);
+      }
+    }
+
+    //
+    if (vfoList)
+      vfoList->accept(*this);
+    
+    return NULL;
+  }
+  else
+  {
+    return no_state;
+  }
 }
 
 void end_visit(const Prolog& v, void* /*visit_state*/)
 {
-  TRACE_VISIT_OUT();
+  if (theSctx->xquery_version() >= StaticContextConsts::xquery_version_3_0)
+  {
+    ZORBA_ASSERT(false);
+  }
+  else
+  {
+    TRACE_VISIT_OUT();
+  }
 }
 
 
@@ -2834,13 +2918,27 @@
 ********************************************************************************/
 void* begin_visit(const SIND_DeclList& v)
 {
-  TRACE_VISIT();
-  return no_state;
+  if (theSctx->xquery_version() >= StaticContextConsts::xquery_version_3_0)
+  {
+    ZORBA_ASSERT(false);
+  }
+  else
+  {
+    TRACE_VISIT();
+    return no_state;
+  }
 }
 
 void end_visit(const SIND_DeclList& v, void* /*visit_state*/)
 {
-  TRACE_VISIT_OUT();
+  if (theSctx->xquery_version() >= StaticContextConsts::xquery_version_3_0)
+  {
+    ZORBA_ASSERT(false);
+  }
+  else
+  {
+    TRACE_VISIT_OUT();
+  }
 }
 
 
@@ -3193,48 +3291,12 @@
   // Create a ModuleVersion based on the input namespace URI.
   const ModuleVersion modVer(v.get_uri());
 
-  // targetNS is the target namespace *without* any
-  // version-declaration fragment.
-  zstring const targetNS = modVer.namespace_uri();
-  zstring const pfx = (!v.get_prefix().empty()) ? v.get_prefix() : "";
-
-  if (static_context::is_reserved_module(targetNS))
-  {
-    RAISE_ERROR(zerr::ZXQP0016_RESERVED_MODULE_TARGET_NAMESPACE, loc,
-    ERROR_PARAMS(targetNS));
-  }
-
-  // The namespace prefix specified in a module import must not be xml or xmlns
-  // [err:XQST0070]
-  if (!pfx.empty() && (pfx == "xml" || pfx == "xmlns"))
-  {
-    RAISE_ERROR(err::XQST0070, loc, ERROR_PARAMS(pfx, ZED(NoRebindPrefix)));
-  }
-
-  // The first URILiteral in a module import must be of nonzero length
-  // [err:XQST0088]
-  if (targetNS.empty())
-    throw XQUERY_EXCEPTION(err::XQST0088, ERROR_LOC(loc));
-
-  // It is a static error [err:XQST0047] if more than one module import in a
-  // Prolog specifies the same target namespace. Note: by checking this here,
-  // we disallow importing two different versions of the same module from
-  // within a single module. It is not clear how we could support that anyway,
-  // since after import, they would both have the same namespace URI, and hence
-  // any references to that namespace would be ambiguous.
-  if (! theImportedModules.insert(targetNS.str()).second)
-    RAISE_ERROR(err::XQST0047, loc, ERROR_PARAMS(targetNS));
-
-  // The namespace prefix specified in a module import must not be the same as
-  // any namespace prefix bound in the same module by another module import,
-  // a schema import, a namespace declaration, or a module declaration with a
-  // different target namespace [err:XQST0033].
-  if (! pfx.empty() &&
-      ! (pfx == theModulePrefix &&
-         targetNS == theModuleNamespace))
-  {
-    theSctx->bind_ns(pfx, targetNS, loc);
-  }
+  // targetNS is the target ns *without* any version-declaration fragment.
+  zstring targetNS = modVer.namespace_uri();
+  zstring pfx = v.get_prefix();
+
+  if (theSctx->xquery_version() < StaticContextConsts::xquery_version_3_0)
+    bindModuleImportPrefix(targetNS, pfx, loc);
 
   const URILiteralList* atlist = v.get_at_list();
 
@@ -3311,6 +3373,7 @@
     // the skipped module, an XQST0093 error will be raised when the translator
     // tries to process that var or function reference.
     std::map<zstring, zstring> modulesStack = theModulesStack;
+
 #if 0
     std::map<zstring, zstring>::iterator ite = modulesStack.begin();
     std::map<zstring, zstring>::iterator end = modulesStack.end();
@@ -3320,9 +3383,20 @@
     }
     std::cout << std::endl;
 #endif
+
     if (! modulesStack.insert(std::pair<zstring, zstring>(compURI, targetNS)).second)
     {
       theHaveModuleImportCycle = true;
+
+      if (theSctx->xquery_version() >= StaticContextConsts::xquery_version_3_0)
+      {
+        static_context_t importedSctx = NULL;
+        bool found = theModulesInfo->mod_sctx_map.get(compURI, importedSctx);
+        ZORBA_ASSERT(found);
+
+        theSctx->import_module(importedSctx, loc);
+      }
+
       return;
     }
 
@@ -3333,8 +3407,7 @@
 
     // Check whether we have already imported a module component from
     // the current uri. If so, check that the target ns of what we
-    // imported before is the same as what we are trying to import
-    // now.
+    // imported before is the same as what we are trying to import now.
     if (theModulesInfo->mod_ns_map.get(compURI, importedNS))
     {
       if (importedNS != targetNS)
@@ -3362,8 +3435,8 @@
       try
       {
         resource = theSctx->resolve_uri(compModVer.versioned_uri(),
-                                         internal::EntityData::MODULE,
-                                         lErrorMessage);
+                                        internal::EntityData::MODULE,
+                                        lErrorMessage);
 
         streamResource = dynamic_cast<internal::StreamResource*>(resource.get());
       }
@@ -3412,9 +3485,8 @@
       importedSctx = independentSctx->create_child_context();
       importedSctx->set_module_namespace(targetNS);
 
-      // Register the imported_sctx in theModulesInfo->mod_sctx_map so
-      // that it is accessible by both the importing and the imported
-      // modules.
+      // Register the imported_sctx in theModulesInfo->mod_sctx_map so that
+      // it is accessible by both the importing and the imported modules.
       theModulesInfo->mod_sctx_map.put(compURI, importedSctx);
 
       // Parse the imported module. fileURL is information only - it is used
@@ -3438,14 +3510,10 @@
       // Also make sure that the imported module is a library module
       LibraryModule* mod_ast = dynamic_cast<LibraryModule *>(&*ast);
       if (mod_ast == NULL)
-        throw XQUERY_EXCEPTION(
-          err::XQST0059,
-          ERROR_PARAMS(
-            ZED( XQST0059_SpecificationMessage ),
-            targetNS, compURI
-          ),
-          ERROR_LOC( loc )
-        );
+      {
+        RAISE_ERROR(err::XQST0059, loc,
+        ERROR_PARAMS(ZED(XQST0059_SpecificationMessage), targetNS, compURI));
+      }
 
       importedNS = mod_ast->get_decl()->get_target_namespace().str();
 
@@ -3453,14 +3521,10 @@
         throw XQUERY_EXCEPTION(err::XQST0088, ERROR_LOC(loc));
 
       if (importedNS != targetNS)
-        throw XQUERY_EXCEPTION(
-          err::XQST0059,
-          ERROR_PARAMS(
-            ZED( XQST0059_SpecificationMessage ),
-            targetNS, compURI
-          ),
-          ERROR_LOC( loc )
-        );
+      {
+        RAISE_ERROR(err::XQST0059, loc,
+        ERROR_PARAMS(ZED(XQST0059_SpecificationMessage), targetNS, compURI));
+      }
 
       // translate the imported module
       translate_aux(theRootTranslator,
@@ -3492,6 +3556,7 @@
         {
           lImportedVersion = "0.0";
         }
+
         ModuleVersion lImportedModVer(compURI, lImportedVersion);
         if (! lImportedModVer.is_valid_version())
         {
@@ -3532,6 +3597,51 @@
 }
 
 
+void bindModuleImportPrefix(
+    const zstring& targetNS,
+    const zstring& pfx,
+    const QueryLoc& loc)
+{
+  if (static_context::is_reserved_module(targetNS))
+  {
+    RAISE_ERROR(zerr::ZXQP0016_RESERVED_MODULE_TARGET_NAMESPACE, loc,
+    ERROR_PARAMS(targetNS));
+  }
+
+  // The namespace prefix specified in a module import must not be xml or xmlns
+  // [err:XQST0070]
+  if (!pfx.empty() && (pfx == "xml" || pfx == "xmlns"))
+  {
+    RAISE_ERROR(err::XQST0070, loc, ERROR_PARAMS(pfx, ZED(NoRebindPrefix)));
+  }
+
+  // The first URILiteral in a module import must be of nonzero length
+  // [err:XQST0088]
+  if (targetNS.empty())
+    throw XQUERY_EXCEPTION(err::XQST0088, ERROR_LOC(loc));
+
+  // It is a static error [err:XQST0047] if more than one module import in a
+  // Prolog specifies the same target namespace. Note: by checking this here,
+  // we disallow importing two different versions of the same module from
+  // within a single module. It is not clear how we could support that anyway,
+  // since after import, they would both have the same namespace URI, and hence
+  // any references to that namespace would be ambiguous.
+  if (!theImportedModules.insert(targetNS.str()).second)
+    RAISE_ERROR(err::XQST0047, loc, ERROR_PARAMS(targetNS));
+
+  // The namespace prefix specified in a module import must not be the same as
+  // any namespace prefix bound in the same module by another module import,
+  // a schema import, a namespace declaration, or a module declaration with a
+  // different target namespace [err:XQST0033].
+  if (! pfx.empty() &&
+      ! (pfx == theModulePrefix &&
+         targetNS == theModuleNamespace))
+  {
+    theSctx->bind_ns(pfx, targetNS, loc);
+  }
+}
+
+
 /*******************************************************************************
   VFO_DeclList ::= VFO_Decl Separator | VFO_DeclList VFO_Decl Separator
 
@@ -3547,11 +3657,22 @@
 {
   TRACE_VISIT();
 
+  if (theSctx->xquery_version() < StaticContextConsts::xquery_version_3_0)
+    preprocessVFOList(v);
+
+  return no_state;
+}
+
+
+void preprocessVFOList(const VFO_DeclList& v)
+{
+  const QueryLoc& loc = v.get_location();
+
   TypeManager* tm = CTX_TM;
 
-  // Function declaration translation must be done in two passes because of
-  // mutually recursive functions and also because the defining expr of a declared
-  // var may reference a function that is declared after the var. So, here's the
+  // Translation of the VFO list must be done in two passes because of mutually
+  // recursive functions and also because the defining expr of a declared var
+  // may reference a function that is declared after the var. So, here's the
   // 1st pass; it translates
   //  (1) the annotations of variable and function declarations
   //  (2) the type declarations for the params and return value of functions
@@ -3586,27 +3707,28 @@
       else
       {
         expand_no_default_qname(qnameItem, lQName, loc);
+
         if (qnameItem->getPrefix().empty() && qnameItem->getNamespace().empty())
         {
           RAISE_ERROR(err::XPST0081, loc, ERROR_PARAMS(qnameItem->getStringValue()));
         }
       }
 
-      if (qnameItem->getNamespace() == static_context::XQUERY_NS
-          &&
-          qnameItem->getLocalName() != "require-feature"
-          &&
+      if (qnameItem->getNamespace() == static_context::XQUERY_NS &&
+          qnameItem->getLocalName() != "require-feature" &&
           qnameItem->getLocalName() != "prohibit-feature")
       {
-        RAISE_ERROR(err::XQST0123, loc, ERROR_PARAMS(ZED(UnrecognizedXQueryOption), qnameItem->getLocalName()));
+        RAISE_ERROR(err::XQST0123, loc,
+        ERROR_PARAMS(ZED(UnrecognizedXQueryOption), qnameItem->getLocalName()));
       }
 
       if (qnameItem->getNamespace() == static_context::ZORBA_OPTION_FEATURE_NS &&
           value == "http-uri-resolution")
       {
         RAISE_ERROR(zerr::ZXQP0061_DISABLE_HTTP_OPTION_IN_QUERY, loc,
-                    ERROR_PARAMS(value));
+        ERROR_PARAMS(value));
       }
+
       theSctx->bind_option(qnameItem, value, opt_decl->get_location());
 
       if (qnameItem->getNamespace() == static_context::ZORBA_OPTION_OPTIM_NS &&
@@ -3656,11 +3778,6 @@
       AnnotationListParsenode* annotations = var_decl->get_annotations();
       if (annotations)
       {
-        if (theSctx->xquery_version() < StaticContextConsts::xquery_version_3_0)
-        {
-          RAISE_ERROR(err::XPST0003, loc, ERROR_PARAMS(ZED(XPST0003_Annotations)));
-        }
-
         annotations->accept(*this);
 
         if (theAnnotations)
@@ -3707,8 +3824,8 @@
       bind_var(ve, theModulesInfo->theGlobalSctx);
 
       // If this is a library module, register the var in the exported sctx as well.
-      if (export_sctx != NULL)
-        bind_var(ve, export_sctx);
+      if (theExportSctx != NULL)
+        bind_var(ve, theExportSctx);
 
       continue;
     }
@@ -3924,8 +4041,6 @@
   }
 
   check_xquery_feature_options(loc);
-
-  return no_state;
 }
 
 
@@ -4583,8 +4698,8 @@
     bind_var(ve, theModulesInfo->theGlobalSctx);
 
     // If this is a library module, register the var in the exported sctx as well.
-    if (export_sctx != NULL)
-      bind_var(ve, export_sctx);
+    if (theExportSctx != NULL)
+      bind_var(ve, theExportSctx);
   }
 
   xqtref_t declaredType;
@@ -4912,8 +5027,8 @@
 
   theSctx->bind_collection(lColl, loc);
 
-  assert(export_sctx);
-  export_sctx->bind_collection(lColl, loc);
+  assert(theExportSctx);
+  theExportSctx->bind_collection(lColl, loc);
 
   // Create an IC to check that the cardinality of the collection matches its
   // declared type.
@@ -5026,8 +5141,8 @@
   theSctx->bind_index(index, loc);
 
   // If this is a library module, register the index in the exported sctx as well.
-  if (export_sctx != NULL)
-    export_sctx->bind_index(index, loc);
+  if (theExportSctx != NULL)
+    theExportSctx->bind_index(index, loc);
 }
 
 
@@ -6078,8 +6193,8 @@
   theSctx->bind_ic(vic, loc);
 
   // if this is a library module, register in exported module as well
-  if (export_sctx != NULL)
-    export_sctx->bind_ic(vic, loc);
+  if (theExportSctx != NULL)
+    theExportSctx->bind_ic(vic, loc);
 }
 
 

=== modified file 'src/context/dynamic_context.cpp'
--- src/context/dynamic_context.cpp	2013-03-21 19:33:22 +0000
+++ src/context/dynamic_context.cpp	2013-05-08 03:46:36 +0000
@@ -114,6 +114,7 @@
   }
 
   theState = other.theState;
+  theIsExternal = other.theIsExternal;
 }
 
 
@@ -281,7 +282,6 @@
 
       char * envVar = new char[size+1];
 
-
       WideCharToMultiByte( CP_ACP,
                            WC_NO_BEST_FIT_CHARS|WC_COMPOSITECHECK|WC_DEFAULTCHAR,
                            envVarsSTR,
@@ -291,7 +291,6 @@
                            NULL,
                            NULL);
 
-
       zstring envVarZS(envVar);
 
       int eqPos = envVarZS.find_first_of("=");
@@ -407,7 +406,7 @@
 ********************************************************************************/
 void dynamic_context::add_variable(ulong varid, store::Iterator_t& value)
 {
-  declare_variable(varid);
+  declare_variable(varid, false);
   set_variable(varid, NULL, QueryLoc::null, value);
 }
 
@@ -417,7 +416,7 @@
 ********************************************************************************/
 void dynamic_context::add_variable(ulong varid, store::Item_t& value)
 {
-  declare_variable(varid);
+  declare_variable(varid, false);
   set_variable(varid, NULL, QueryLoc::null, value);
 }
 
@@ -425,7 +424,7 @@
 /*******************************************************************************
 
 ********************************************************************************/
-void dynamic_context::declare_variable(ulong varid)
+void dynamic_context::declare_variable(ulong varid, bool external)
 {
   assert(varid > 0);
 
@@ -434,6 +433,8 @@
 
   if (theVarValues[varid].theState == VarValue::undeclared)
     theVarValues[varid].theState = VarValue::declared;
+
+  theVarValues[varid].theIsExternal = external;
 }
 
 
@@ -593,19 +594,37 @@
       theVarValues[varid].theState == VarValue::undeclared)
   {
     zstring varName = static_context::var_name(varname.getp());
-    RAISE_ERROR(err::XPDY0002, loc,
-    ERROR_PARAMS(ZED(XPDY0002_VariableUndeclared_2), varName));
-  }
 
-  if (theVarValues[varid].theState == VarValue::declared)
-  {
-    zstring varName = static_context::var_name(varname.getp());
-    RAISE_ERROR(err::XPDY0002, loc,
-    ERROR_PARAMS(ZED(XPDY0002_VariableHasNoValue_2), varName));
+    if (varid >= theVarValues.size() ||
+        theVarValues[varid].theIsExternal ||
+        varid == IDVAR_CONTEXT_ITEM)
+    {
+      RAISE_ERROR(err::XPDY0002, loc,
+      ERROR_PARAMS(ZED(XPDY0002_VariableUndeclared_2), varName));
+    }
+    else
+    {
+      RAISE_ERROR(err::XQDY0054, loc, ERROR_PARAMS(varName));
+    }
   }
 
   const VarValue& var = theVarValues[varid];
 
+  if (var.theState == VarValue::declared)
+  {
+    zstring varName = static_context::var_name(varname.getp());
+
+    if (var.theIsExternal)
+    {
+      RAISE_ERROR(err::XPDY0002, loc,
+      ERROR_PARAMS(ZED(XPDY0002_VariableHasNoValue_2), varName));
+    }
+    else
+    {
+      RAISE_ERROR(err::XQDY0054, loc, ERROR_PARAMS(varName));
+    }
+  }
+
   if (var.theState == VarValue::item)
     itemValue = var.theValue.item;
   else

=== modified file 'src/context/dynamic_context.h'
--- src/context/dynamic_context.h	2013-03-21 19:33:22 +0000
+++ src/context/dynamic_context.h	2013-05-08 03:46:36 +0000
@@ -82,8 +82,9 @@
     }           theValue;
 
     ValueState  theState;
+    bool        theIsExternal;
 
-    VarValue() : theState(undeclared)
+    VarValue() : theState(undeclared), theIsExternal(false)
     {
       theValue.item = NULL;
     }
@@ -118,7 +119,7 @@
 
   ITEM_PTR_HASH_MAP(store::Index_t, IndexMap);
 
-  typedef std::map<const zstring,const zstring> EnvVarMap;
+  typedef std::map<const zstring, const zstring> EnvVarMap;
 
 protected:
   dynamic_context            * theParent;
@@ -131,7 +132,7 @@
 
   std::vector<VarValue>        theVarValues;
 
-  mutable ValueMap                   * keymap;
+  mutable ValueMap           * keymap;
 
   IndexMap                   * theAvailableIndices;
 
@@ -177,27 +178,27 @@
 
   long get_implicit_timezone() const;
 
-  void set_locale( locale::iso639_1::type lang,
-                   locale::iso3166_1::type country ) {
+  void set_locale(
+      locale::iso639_1::type lang,
+      locale::iso3166_1::type country)
+  {
     theLang = lang;
     theCountry = country;
   }
 
-  void get_locale( locale::iso639_1::type *lang,
-                   locale::iso3166_1::type *country ) {
+  void get_locale(
+      locale::iso639_1::type* lang,
+      locale::iso3166_1::type* country)
+  {
     if ( lang )
       *lang = theLang;
     if ( country )
       *country = theCountry;
   }
 
-  void set_calendar( time::calendar::type calendar ) {
-    theCalendar = calendar;
-  }
+  void set_calendar(time::calendar::type calendar) { theCalendar = calendar; }
 
-  time::calendar::type get_calendar() const {
-    return theCalendar;
-  }
+  time::calendar::type get_calendar() const { return theCalendar; }
 
   const std::vector<VarValue>& get_variables() const { return theVarValues; }
 
@@ -205,7 +206,7 @@
 
   void add_variable(ulong varid, store::Iterator_t& value);
 
-  void declare_variable(ulong varid);
+  void declare_variable(ulong varid, bool external);
 
   void set_variable(
       ulong varid,
@@ -224,7 +225,6 @@
       const store::Item_t& varname,
       const QueryLoc& loc);
 
-
   void get_variable(
         ulong varid,
         const store::Item_t& varname,
@@ -306,7 +306,7 @@
     return theParent == NULL ? false : theParent->context_value(key, val);
   }
 
-  bool context_value(const std::string& key, dctx_value_t& val, ValueMap **map)
+  bool context_value(const std::string& key, dctx_value_t& val, ValueMap** map)
   {
     if (lookup_once (key, val))
     {

=== modified file 'src/runtime/core/var_iterators.cpp'
--- src/runtime/core/var_iterators.cpp	2013-03-17 13:55:28 +0000
+++ src/runtime/core/var_iterators.cpp	2013-05-08 03:46:36 +0000
@@ -98,7 +98,7 @@
 
   if (!theIsExternal || !dctx->exists_variable(theVarId))
   {
-    dctx->declare_variable(theVarId);
+    dctx->declare_variable(theVarId, theIsExternal);
 
     if (!theChildren.empty())
     {

=== modified file 'src/runtime/indexing/doc_indexer.cpp'
--- src/runtime/indexing/doc_indexer.cpp	2013-02-07 17:24:36 +0000
+++ src/runtime/indexing/doc_indexer.cpp	2013-05-08 03:46:36 +0000
@@ -69,7 +69,7 @@
 
     theDctx = static_cast<PlanWrapper*>(thePlanWrapper.getp())->dctx();
 
-    theDctx->declare_variable(theNodeVarId);
+    theDctx->declare_variable(theNodeVarId, false);
 
     thePlanWrapper->open();
   }

=== modified file 'test/fots/CMakeLists.txt'
--- test/fots/CMakeLists.txt	2013-05-06 22:58:11 +0000
+++ test/fots/CMakeLists.txt	2013-05-08 03:46:36 +0000
@@ -145,6 +145,7 @@
 EXPECTED_FOTS_FAILURE (DISPUTED prod-OptionDecl.serialization Serialization-032 21868)
 EXPECTED_FOTS_FAILURE (DISPUTED fn-id K2-SeqIDFunc-11 21414)
 EXPECTED_FOTS_FAILURE (DISPUTED fn-id K2-SeqIDFunc-12 21414)
+EXPECTED_FOTS_FAILURE (DISPUTED prod-VarDecl.external K2-ExternalVariablesWith-22 21960)
 
 # Next three possibly unique to old RQ machine, but they need to be
 # marked for the RQ to pass.
@@ -296,7 +297,6 @@
 EXPECTED_FOTS_FAILURE (prod-ModuleImport module-URIs-18 0)
 EXPECTED_FOTS_FAILURE (prod-ModuleImport modules-collide-var-001 0)
 EXPECTED_FOTS_FAILURE (prod-ModuleImport modules-collide-fn-001 0)
-EXPECTED_FOTS_FAILURE (prod-ModuleImport errata8-002a 0)
 EXPECTED_FOTS_FAILURE (prod-OrderByClause orderBy40 0)
 EXPECTED_FOTS_FAILURE (prod-OrderByClause orderBy41 0)
 EXPECTED_FOTS_FAILURE (prod-OrderByClause orderBy49 0)
@@ -342,7 +342,6 @@
 EXPECTED_FOTS_FAILURE (prod-ValidateExpr validate-as-104 0)
 EXPECTED_FOTS_FAILURE (prod-ValidateExpr validate-as-105 0)
 EXPECTED_FOTS_FAILURE (prod-ValidateExpr validate-as-106 0)
-EXPECTED_FOTS_FAILURE (prod-VarDecl.external K2-ExternalVariablesWith-22 0)
 EXPECTED_FOTS_FAILURE (prod-VersionDecl VersionDecl-v1-processor-and-v3-query 0)
 EXPECTED_FOTS_FAILURE (prod-VersionDecl version_declaration-023-v3 0)
 EXPECTED_FOTS_FAILURE (xs-anyURI cbcl-anyURI-002 0)

-- 
Mailing list: https://launchpad.net/~zorba-coders
Post to     : zorba-coders@lists.launchpad.net
Unsubscribe : https://launchpad.net/~zorba-coders
More help   : https://help.launchpad.net/ListHelp

Reply via email to