Subject: [netmod] submodules

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 01 Dec 2008 15:03:19 +0100

Hi,

is this allowed or is it considered a circular include?

module M {
  ...
  include S1;
  include S2;
  ...
}

submodule S1 {
  belongs-to M;
  include S2;
  ...
}

submodule S2 {
  belongs-to M;
  ...
}

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

_______________________________________________
netmod mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/netmod

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 01 Dec 2008 16:19:58 +0100 (CET)

> is this allowed or is it considered a circular include?

This is allowed.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 01 Dec 2008 17:12:59 +0100

> > is this allowed or is it considered a circular include?

But the main module gets the definitions from S1 twice. Why is this
different from the case of a shorter circle, namely when S2 also
includes S1? This is explicitly forbidden in the draft.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Mon, 01 Dec 2008 09:31:04 -0800

> includes S1? This is explicitly forbidden in the draft.

It is different because no include loops are created.
The compiler has to be clever enough to detect loops
across N files, and not generate output for duplicate
sub-module includes.  I doubt any PL or DML ever created permits
include or import loops.

Although not intuitive, a submodule nested 1000 layers
deep (S1 inc S2 inc S3...) generates the same top-level
objects and typedefs as if the definitions were in the
main module.  There is no object hierarchy created or implied
by the submodule hierarchy.  Submodules are merely containers
of definitions, allowing DM designers to decouple the module
namespace from the physical file.  The coupling can be 1:N
instead of 1:1, if so desired.

> Lada

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 01 Dec 2008 20:21:11 +0100

> It is different because no include loops are created.

So this is not include loop

    +----<-----+
    |          |
    M <- S1 <- S2

while this is (where S0 is another submodule)?

    +----<------+
    |           |
    S0 <- S1 <- S2

What's the difference? Main module M in the first case gets even more
stuff from the submodules than S0 in the second case.

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Mon, 01 Dec 2008 11:41:51 -0800

> So this is not include loop

there is no loop here

> stuff from the submodules than S0 in the second case.

module M {
   ...
   include S0;
   include S1;
   include S2;
   ...
}

submodule S0 {
   belongs-to M;
   include S1;
   include S2;
   ...
}

submodule S1 {
   belongs-to M;
   include S2;
   ...
}

submodule S2 {
   belongs-to M;
   ...
}

This is fine.
 From a module perspective, M, S0, S1, S2, and S3
are all at the same 'level'.  The hierarchy of
include-stmts only makes symbols visible in the
including file, it does not redefine them over and over.

This would cause an include loop between S1 <--> S2:

submodule S2 {
   belongs-to M;
   include S1;   // illegal
   ...
}

Andy

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 01 Dec 2008 21:09:00 +0100

> including file, it does not redefine them over and over.

I see, so when a (sub)module tries to look-up a symbol, there may be
multiple include chains that lead to it, provided they end up at the
same definition in the same submodule. But can the compiler then
discover an error when two include chains in fact give two different
definitions of the same symbol?

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Mon, 01 Dec 2008 12:24:36 -0800

> definitions of the same symbol?

You can discover all duplicates by compiling the main module.
If you forget the "include subX" in the main module, then
those symbols will not be exported to other modules.

Andy

---

From: Andy Bierman <[email-masked]>
Date: Mon, 01 Dec 2008 12:28:19 -0800

> those symbols will not be exported to other modules.

I meant if submodule 'X' is not included anywhere,
not included directly.

E.g.,  M <-- S0 <-- S1 <-- SX

SX will be exported even though M does not include it directly.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 01 Dec 2008 21:28:25 +0100 (CET)

> those symbols will not be exported to other modules.

I don't think this should be allowed:

  module M {
    inlcude S1;
    ...
  }

  submodule S1 {
    belongs-to M;
    include S2;
    ...
  }

  submodule S2 {
    belongs-to M; // (*)
    ...
  }

You can argue that (*) is wrong - S2 claims it belongs to M, but M
does not include it.

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Mon, 01 Dec 2008 21:31:05 +0100 (CET)

> SX will be exported even though M does not include it directly.

Ah.  Yes, I agree.  Forget my other email.  M does not have to list
all submodules recursively.

/martin

---

From: Ladislav Lhotka <[email-masked]>
Date: Mon, 01 Dec 2008 21:40:39 +0100

> all submodules recursively.

So maybe the draft could say it explicitly that the inclusion of
definitions (symbols) from submodules is transitive. 

Lada

-- 
Ladislav Lhotka, CESNET
PGP Key ID: E74E8C0C

---

From: Andy Bierman <[email-masked]>
Date: Mon, 01 Dec 2008 12:50:31 -0800

> You can argue that (*) is wrong - S2 claims it belongs to M, but M

When you compile S2 you do not know if M includes it or not.
Since belongs-to-stmt was changed to avoid the compiler looking
at the main module (for the prefix), it seems strange to
make the compiler read the main module looking for an include-stmt.

This check is not needed, because another module importing M
will flag the missing definition if an include-stmt is missing from M.

IMO, this is valid YANG because submodules are not really nested
at the object level, but they are nested at the abstraction level.
Since M <-- S1 <-- S2, no submodule is 'orphaned'.

Whatever submodules get included down the tree (S2 here)
are visible to outside modules.  This allows S1 or S2 to expand
over time and be further fragmented into more submodules.

In my code, a stack of 'breadcrumb' records keeps track of loops,
and a Q of back-ptr records keeps a list of all includes in M,
so extra re-compiles of submodules are avoided, and the
same Q provides an external search path through all the
submodules.

Andy