[Bug 1705] [FS] technical: 5.2 Module Declaration: cyclical imports

http://www.w3.org/Bugs/Public/show_bug.cgi?id=1705





------- Comment #23 from simeon@us.ibm.com  2006-10-27 20:19 -------
Here is a much more detailed proposal to address that bug. Unfortunately, it
does not fully address the very last comment from Michael Dyck for which there
is a serious roadblock. (see comment 4 in the proposal overview).

Suggestions and comments would be very much appreciated.

- Jerome


Proposal Overview
=================

High-level characteristics of the proposal:

 (1) it separates the context building for modules in two parts one
part deals with the context internal to a module, and the context
being exported for a set of modules in the same namespace.
 (2) it breaks the circularity for recursive modules.
 (3) it address the issue with forward variable references by
sorting them appropriately.
 (4) it only partially deals with the issue raised by Michael Dyck
about possible conflicts between declarations in multiple prologs. In
fact there is a very serious road block here, as I think the only way
to deal with it would be to keep track of the specific static
environment *per* variable. This makes things increadibly messy to
specific.

Here is a concrete variant of Michael Dyck's example which shows the
problem:

        module        namespace L1 = "http://www.example.com/foo";
        import module namespace L2 = "http://www.example.com/foo";
        declare boundary-space preserve;
        declare variable $L1:s1 = $L2:s2;
        declare variable $L1:d1 = <a>  { "Hello" }  </a>;
        --------
        module        namespace L2 = "http://www.example.com/foo";
        import module namespace L1 = "http://www.example.com/foo";
        declare boundary-space strip;
        declare variable $L2:d2 = $L1:d1;
        declare variable $L2:s2 = <a>  { "World!" }  </a>;

The point of the example is that you need to do two things at the same
time: (i) re-order the variable to remove forward references, (ii)
keep track of the environment *on a per variable basis*.  This last
bit is the road-block as it is again a pretty fundamental departure
from the formalization approach we have taken throughout the FS
documents. Fixing it will requires a lot of surgical hacking on top of
the already complex proposal below.


Detailed Proposal
=================

In what follows 'SCP' means static context processing.

Changes to judgments
--------------------

*** Replace the judgment:

  statEnv1 |- PrologDecl1 =>stat statEnv2

by two new judgments:

  statEnv1 ; AnyURI |- PrologDecl1 =>stat statEnv2
working only over "setters"
and
  statEnv1 ; statEnv2 |- PrologDecl1 =>stat statEnv3 ; statEnv4
working over variable and function declarations, where the first
environment on each side is the local module environment, and the
second environment is the environment being exported.

The addition of the URI in the first judgment is to prevent module
import of a module in the same namespace. Breaking the recursion.


*** Replace the judgment:

  statEnv1 |- PrologDeclList =>stat statEnv2 with PrologDeclList1

By two distinct judgments:
  statEnv1 |- PrologDeclList =>prestat statEnv2 with PrologDeclList1

which is used to pre-process the declarations for a given prolog,
extending the environment with the "setters" but not the variable and
function declarations, and returning all of the prolog normalized.

and
  statEnvn ; statEnvDefault; AnyURI |- PrologDeclList0 =>stat statEnv0

which processes the prolog's variable and functions declarations,
returning the exportable context.


*** Add the new judgment:

  PrologDeclList1' ... PrologDeclListn' preprocess as PrologDeclList0

Which takes a set of *core* prolog declarations, and reorders the
variable declarations so that they do not depend on forward
references. Because they have already been normalized, the rest of the
prolog should not be necessary for evaluation. [[[ WARNING. There is a
very serious road block here as I think that property is not true for
many properties in the static context. That means that the only way to
deal with this is to keep a different static environment for each
variable declarations which is pretty much a nightmare. ]]]


Changes to the introduction of Section 5
----------------------------------------

*** Replace the static context processing rule by the following rules,
distinguishing between the 'setters and declarations' from the
variable and function declarations. The purpose of those rules is
twofold. First build the internal static environment for a given
module. Second, they completely normalize the declarations for that
module based on that local environment.


------------------------------------------
statEnv ; AnyURI |- =>prestat statEnv with

PrologDecl != VariableDecl or FunctionDecl or OptionDecl
[PrologDecl]_PrologDecl  == PrologDecl1
statEnv1 ; AnyURI |- PrologDecl1 =>stat statEnv2
statEnv2 ; AnyURI |- PrologDeclList =>prestat statEnv3 with PrologDeclList1
---------------------------------------------------------------------------
statEnv1 ; AnyURI |- PrologDecl ;
      PrologDeclList =>prestat statEnv3 with PrologDecl1 ; PrologDeclList1

PrologDecl = VariableDecl or FunctionDecl or OptionDecl
[PrologDecl]_PrologDecl  == PrologDecl1
statEnv1 ; AnyURI |- PrologDeclList =>prestat statEnv1 with PrologDeclList1
---------------------------------------------------------------------------
statEnv1 ; AnyURI |- PrologDecl ;
      PrologDeclList =>prestat statEnv1 with PrologDecl1 ; PrologDeclList1


*** Add the following rules, which processes only variable and
function declarations for the purpose of constructing the "exported"
static environment.

-----------------------------------------------
statEnv1 ; statEnv2 ; AnyURI |- =>stat statEnv2


PrologDecl != VariableDecl or FunctionDecl or OptionDecl
statEnv1 ; statEnv2 ; AnyURI |- PrologDeclList =>stat statEnv3
-------------------------------------------------------------------------
statEnv1 ; statEnv2 ; AnyURI |- ProgDecl; PrologDeclList =>stat statEnv3

PrologDecl = VariableDecl or FunctionDecl or OptionDecl
statEnv1 ; statEnv2 ; AnyURI |- PrologDecl1 =>stat statEnv3 ; statEnv4
statEnv3 ; statEnv4 ; AnyURI |- PrologDeclList =>stat statEnv5
--------------------------------------------------------------------------
statEnv1 ; statEnv2 ; AnyURI |- PrologDecl; PrologDeclList =>stat statEnv5


Changes to Section 5.2 Module Declaration
-----------------------------------------

*** Replace the existing SCP rule by:

AnyURI  is target namespace of modules Module1 ... Modulen
Module1 = module namespace NCName1 = URILiteral; PrologDeclList1
...
Modulen = module namespace NCName1 = URILiteral; PrologDeclListn
dynEnv |- URILiteral has atomic value AnyURI
statEnvDefault ; AnyURI |- declare namespace NCName = URILiteral;
                   PrologDeclList1 =>prestat statEnv1 with PrologDeclList1'
...
statEnvn-1 ; AnyURI |- declare namespace NCName = URILiteral;
                   PrologDeclListn =>prestat statEnvn with PrologDeclListn'
PrologDeclList1' ... PrologDeclListn' preprocess as PrologDeclList0
statEnvn ; statEnvDefault; AnyURI |- PrologDeclList0 =>stat statEnv0
-------------------------------------------------------------------------------
AnyURI =>module_statEnv statEnvn0


Changes to Sections
    5.3 Boundary-space Declaration
    5.4 Default Collation Declaration
    5.5 Base URI Declaration
    5.6 Construction Declaration
    5.7 Ordering Mode Declaration
    5.8 Empty Order Declaration
    5.9 Copy-Namespaces Declaration
    5.10 Schema Import
    5.12 Namespace Declaration
    5.13 Default Namespace Declaration
--------------------------------------

*** In SCP, simply replace the use of:

  statEnv1 |- PrologDecl1 =>stat statEnv2
by
  statEnv1 ; AnyURI |- PrologDecl1 =>stat statEnv2


Changes to Section 5.11 Module Import
-------------------------------------

*** In SCP, replace the rule:

  AnyURI1 =>module_statEnv statEnv1
  ...
  AnyURI1 =>module_statEnv statEnvn
  statEnv extended with static environment statEnv1
              yields statEnv1' for uri AnyURI
  ...
  statEnvn-1 extended with static environment statEnvn
              yields statEnvn' for uri AnyURI
  ----------------------------------------------------------------
  statEnv |-  import module AnyURI1 LocationHints? =>stat statEnvn

By:

  AnyURI0 != AnyURI1
  AnyURI1 =>module_statEnv statEnv1
  statEnv extended with static environment statEnv1
              yields statEnv2 for uri AnyURI1
  -------------------------------------------------------------------------
  statEnv ; AnyURI0 |- import module AnyURI1 LocationHints? =>stat statEnv2

and

  AnyURI0 = AnyURI1
  ------------------------------------------------------------------------
  statEnv ; AnyURI0 |- import module AnyURI1 LocationHints? =>stat statEnv

Note that the module does not import its own context within itself
anymore. (see the corresponding treatment at the beginning of the
proposal).


Replace the rule:

  dynEnv |- URILiteral1 has atomic value AnyURI1
  AnyURI1 =>module_statEnv statEnv1
  ...
  AnyURI1 =>module_statEnv statEnvn
  statEnv extended with static environment statEnv1
             yields statEnv1' for uri AnyURI
  ...
  statEnvn-1 extended with static environment statEnvn
             yields statEnvn' for uri AnyURI
  statEnv' = statEnvn' + namespace(NCName => (passive, AnyURI))
  -------------------------------------------------------------
  statEnv |-  import module namespace NCName = URILiteral1
  LocationHints? =>stat statEnvn'

By the rule:

  dynEnv |- URILiteral1 has atomic value AnyURI1
  AnyURI0 != AnyURI1
  AnyURI1 =>module_statEnv statEnv1
  statEnv extended with static environment statEnv1
              yields statEnv2 for uri AnyURI1
  statEnv3 = statEnvn2 + namespace(NCName => (passive, AnyURI1))
  -----------------------------------------------------------------
  statEnv ; AnyURI0 |- import module namespace NCName = URILiteral1
  LocationHints? =>stat statEnv3

and
  dynEnv |- URILiteral1 has atomic value AnyURI1
  AnyURI0 = AnyURI1
  statEnv1 = statEnv + namespace(NCName => (passive, AnyURI1))
  -----------------------------------------------------------------
  statEnv ; AnyURI0 |- import module namespace NCName = URILiteral1
  LocationHints? =>stat statEnv1


Changes to Section 5.14 Variable Declaration
--------------------------------------------

In SCP, change the rule:

  statEnv |- VarName of var expands to Variable
  statEnv |- Expr : Type
  statEnv1 = statEnv + varType(Variable => Type)
  ------------------------------------------------------------
  statEnv |- declare variable $VarName := Expr =>stat statEnv1

by:

  statEnv1 |- VarName of var expands to Variable
  statEnv1 |- Expr : Type
  statEnv3 = statEnv1 + varType(Variable => Type)
  statEnv4 = statEnv2 + varType(Variable => Type)
  -------------------------------------------------------
  statEnv1; statEnv2 |- declare variable $VarName := Expr
                            =>stat statEnv3;statEnv4

Note that both environments are extended by the variable type, but
that the expression is statically typed in statEnv1 which is the local
environment for that module.

Similarly, change the rule:

  statEnv  |-  VarName of var expands to Variable
  Type = [SequenceType]sequencetype
  statEnv |-  Expr : Type2
  statEnv |-  Type2 <: Type
  statEnv1 = statEnv + varType( Variable => Type)
  ----------------------------------------------------------------------------
  statEnv |- declare variable $VarName as SequenceType := Expr =>stat statEnv2

to:

  statEnv1 |-  VarName of var expands to Variable
  Type = [SequenceType]sequencetype
  statEnv1 |-  Expr : Type2
  statEnv1 |-  Type2 <: Type
  statEnv3 = statEnv1 + varType( Variable => Type)
  statEnv4 = statEnv2 + varType( Variable => Type)
  -----------------------------------------------------------------------
  statEnv1; statEnv2 |- declare variable $VarName as SequenceType := Expr
        =>stat statEnv3;statEnv4


Changes to Section 5.15 Function Declaration
--------------------------------------------

In SCP, similar change as for variables. I.e.,
for every rule:

-- Replace: statEnv |- FunctionDecl =>stat statEnv1
by: statEnv1;statEnv2 |- FunctionDecl =>stat statEnv3;statEnv4

-- Replace: statEnv by: statEnv1 above the line.
-- Replace: statEnv1 = statEnv + funcType(expanded-QName => FunctionSig)
by the two lines:
statEnv3 = statEnv1 + funcType(expanded-QName => FunctionSig)
statEnv4 = statEnv2 + funcType(expanded-QName => FunctionSig)

Received on Friday, 27 October 2006 20:19:19 UTC