Subject: Re: [sv-ac] revised local variable proposal
From: John Havlicek (john.havlicek@motorola.com)
Date: Mon Mar 17 2003 - 11:54:59 PST
Erich:
First, let me say that I really appreciate your giving these
definitions careful scrutiny. I think we are converging on the
"right" ones.
In the case of "&&" and "intersect", I agree with you. If x
exists before the fork and is resampled in exactly one of the
branches, then x should be visible after the join and should
yield the resampled value. If x exists before the fork and
is not resampled in either thread, then x should also be visable
after the join, with the same value that it had at the fork.
As I indicated in my response to Jay, I am trying to make sure
that if a local variable is visible, then it has been sampled.
This is why I do not want to let a new local variable that
is introduced in only one branch of an "||" to be referenced later
in the sequence. If a local variable exists before an "||" and
is resampled in one or both branches, then it should still be legal
to reference it after the "||".
I want to make sure that the conditions for where in a sequence a
local variable is visible are static.
Best regards,
John H.
> John,
>
> OK, I understand now - but now I'm uncomfortable with your definition =
> for &&, specifically for variables preceding the fork.
>
> You say the following:
>
> =3D=3D=3D
> iii) In the case of "and" and "intersect", the symmetric difference of =
> the local=20
> variables that were introduced in the two joining threads passes =
> on past the=20
> join. In other words, each thread passes on its new local =
> variables that do=20
> not appear as new local variables in the other thread. A Local =
> variable that
> existed at the fork [i.e., at the start of the "and" or =
> "intersect"] of
> the two threads is passed on provided that it was not overwritten =
> in either
> of the joining threads. Since only the difference of the new =
> variables is=20
> passed on, the two joining threads are merged into one thread at =
> the join.
> =3D=3D=3D
>
> I think the 3rd sentence should say "A Local variable that existed at =
> the fork ... is passed on provided that it was not overwritten in BOTH =
> of the joining threads." I say this because if it is overwritten in =
> one thread only, and both threads succeed (defn of &&), then its value =
> at the join is well-defined, and in fact that variable is part of the =
> symmetric difference of the variables (not necessarily new) introduced =
> in the two threads.
>
> Regards,
>
> Erich
>
> -------------------------------------------
> Erich Marschner, Cadence Design Systems
> Senior Architect, Advanced Verification
> Phone: +1 410 750 6995 Email: erichm@cadence.com
> Vmail: +1 410 872 4369 Email: erichm@comcast.net=20
>
> | -----Original Message-----
> | From: John Havlicek [mailto:john.havlicek@motorola.com]
> | Sent: Monday, March 17, 2003 11:18 AM
> | To: Erich Marschner
> | Cc: john.havlicek@motorola.com
> | Subject: Re: [sv-ac] revised local variable proposal
> | =20
> | =20
> | Hi Erich:
> | =20
> | According to the rule
> | =20
> | All succeeding threads out of "or" branches continue as =
> separate
> | threads after the join, carrying with them their version of the =
>
> | local variables.
> | =20
> | in your example, both branches of the "||" would carry their=20
> | own values
> | of the local variable x. Therefore, the value compared to data2
> | could be different in the two threads. Each thread would=20
> | individually
> | either match or not match.
> | =20
> | This is what I mean by saying the "||" does not really join. In
> | the case that both branches match at the same time, they are=20
> | not required
> | to have consistent assignments to the local variables.
> | =20
> | Best regards,
> | =20
> | John Havlicek
> | =20
> | > John,
> | >=20
> | > | Do you want to take this discussion to the sv-ac reflector? =
> =3D20
> | > | Others may be wondering the same things.
> | >=20
> | > Feel free to cc: this to sv-ac whenever you think it appropriate.
> | >=20
> | > | The proposal says that=3D20
> | > | =3D20
> | > | All succeeding threads out of "or" branches continue=20
> | as separate=3D20
> | > | threads after the join, carrying with them their=20
> | version of the =3D
> | > local=3D20
> | > | variables.
> | > | =3D20
> | > | [I think "their version" should be "their versions".]
> | > | =3D20
> | > | So, you might say that the "||" threads don't really=20
> | join. Because =3D
> | > the "||"
> | > | does not guarantee that both branches will succeed, it=20
> | cannot be a =3D
> | > true=3D20
> | > | join. I think this is definitely the right intuitive thread =
> =3D
> | > semantics for=3D20
> | > | matching a sequence when there are local variables=20
> | sampled in the =3D
> | > branches=3D20
> | > | of an "||" subsequence. =3D20
> | >=20
> | > But || allows both branches to succeed, so there is a=20
> | question about =3D
> | > what *value* will be associated with a variable name that=20
> | is sampled on =3D
> | > both branches. In your example:
> | >=20
> | > sequence s6 =3D3D (
> | > (
> | > (a ; (int x =3D3D data, int y=20
> | =3D3D data1) =3D
> | > b; c)
> | > ||
> | > (d; (int x =3D3D data) =
> (e=3D3D=3D3Dx))
> | > ) ;
> | > (x=3D3D=3D3Ddata2)
> | > );
> | > // legal since x is in the intersection
> | >=20
> | > one can expect x to have the same value in both branches,=20
> | because in =3D
> | > both branches it is sampled in the same cycle. But if the=20
> | example were =3D
> | > changed slightly, to=3D20
> | >=20
> | > sequence s6 =3D3D (
> | > (
> | > (a ; (int x =3D3D data, int y=20
> | =3D3D data1) =3D
> | > b; c)
> | > ||
> | > ((int x =3D3D data) d; d2; =
> (e=3D3D=3D3Dx))
> | > ) ;
> | > (x=3D3D=3D3Ddata2)
> | > );
> | > // legal since x is in the intersection
> | >=20
> | > then the two samples of x occur at different cycles, and=20
> | therefore the =3D
> | > two instances of x may have different values, so what is=20
> | the value of x =3D
> | > when it is compared to data2? Is it the last assignment=20
> | to x in either =3D
> | > branch of the ||? If so, does that mean that an=20
> | assignment on one =3D
> | > branch of the || is also visible to the other branch? =20
> | (That is, in the =3D
> | > second example above, when we evaluate (e=3D3D=3D3Dx) in the=20
> | second branch, =3D
> | > do we compare e to the value sampled in the first cycle of=20
> | the second =3D
> | > branch, or to the value sampled in the second cycle of the first =
> =3D
> | > branch?
> | >=20
> | > Regards,
> | >=20
> | > Erich
> | >=20
> | > -------------------------------------------
> | > Erich Marschner, Cadence Design Systems
> | > Senior Architect, Advanced Verification
> | > Phone: +1 410 750 6995 Email: erichm@cadence.com
> | > Vmail: +1 410 872 4369 Email: erichm@comcast.net=3D20
> | >=20
> | > | -----Original Message-----
> | > | From: John Havlicek [mailto:john.havlicek@motorola.com]
> | > | Sent: Friday, March 14, 2003 10:31 AM
> | > | To: Erich Marschner
> | > | Cc: john.havlicek@motorola.com
> | > | Subject: Re: [sv-ac] revised local variable proposal
> | > | =3D20
> | > | =3D20
> | > | Hi Erich:
> | > | =3D20
> | > | >=3D20
> | > | > John,
> | > | >=3D20
> | > | > You define which variable *names* remain visible after a=3D20
> | > | join, but I =3D3D
> | > | > don't see (or perhaps I missed) a definition of the=3D20
> | > | *value* of each =3D3D
> | > | > such variable. For example, consider=3D3D20
> | > | >=3D20
> | > | > ... a; ( (b (int x =3D3D3Ddata); c) || (b; c (int=20
> | x =3D3D3D=3D20
> | > | data)) ); =3D3D
> | > | > x=3D3D3D=3D3D3D1;
> | > | >=3D20
> | > | > Clearly both branches of the '||' will match - but which=3D20
> | > | value of data =3D3D
> | > | > will be associated with x in the last cycle?
> | > | =3D20
> | > | The proposal says that=3D20
> | > | =3D20
> | > | All succeeding threads out of "or" branches continue=20
> | as separate=3D20
> | > | threads after the join, carrying with them their =
> version=3D20
> | > | of the local=3D20
> | > | variables.
> | > | =3D20
> | > | [I think "their version" should be "their versions".]
> | > | =3D20
> | > | So, you might say that the "||" threads don't really join. =20
> | > | Because the "||"
> | > | does not guarantee that both branches will succeed, it=3D20
> | > | cannot be a true=3D20
> | > | join. I think this is definitely the right intuitive =
> thread=3D20
> | > | semantics for=3D20
> | > | matching a sequence when there are local variables sampled=3D20
> | > | in the branches=3D20
> | > | of an "||" subsequence. =3D20
> | > | =3D20
> | > | If the complexity of implementing this semantics is too=20
> | high, then =3D
> | > we
> | > | could consider making sampling of local variables in=3D20
> | > | branches of an "||"
> | > | either undefined or illegal. However, as I said in DWG=3D20
> | > | yesterday (and=3D20
> | > | discussed in follow-up e-mail), removing the complexity =
> for=3D20
> | > | "||" does not=3D20
> | > | address the complexity of supporting sampling at=3D20
> | > | non-deterministic points,
> | > | which can be expressed using unbounded repetition.
> | > | =3D20
> | > | >=3D20
> | > | > Also, for and/intersect, shouldn't it be the union of=3D20
> | > | newly introduced =3D3D
> | > | > variables, not the symmetric difference? (And then the=3D20
> | > | above question =3D3D
> | > | > applies here also.)
> | > | =3D20
> | > | Here, I think the symmetric difference is appropriate. =20
> | Unlike "||",
> | > | the "&&" and "intersect" operators produce true joins. =20
> | My goal with =3D
> | >=20
> | > | this rule was that later references to a local variable=20
> | sampled in a =3D
> | >=20
> | > | branch of such an operator should be unambiguous. If the=3D20
> | > | new variable=3D20
> | > | appears in one or the other branch, but not both, then I=3D20
> | > | know exactly=3D20
> | > | where it came from. But if the varible appears in both=3D20
> | > | branches, then=3D20
> | > | I have a collision, and I don't know which value to use=20
> | in the later =3D
> | >=20
> | > | reference.
> | > | =3D20
> | > | Do you want to take this discussion to the sv-ac reflector? =
> =3D20
> | > | Others may
> | > | be wondering the same things.
> | > | =3D20
> | > | Best regards,
> | > | =3D20
> | > | John H.
> | > | =3D20
> | > | >=3D20
> | > | > Regards,
> | > | >=3D20
> | > | > Erich
> | > | >=3D20
> | > | > -------------------------------------------
> | > | > Erich Marschner, Cadence Design Systems
> | > | > Senior Architect, Advanced Verification
> | > | > Phone: +1 410 750 6995 Email: erichm@cadence.com
> | > | > Vmail: +1 410 872 4369 Email: erichm@comcast.net=3D3D20
> | > | >=3D20
> | > | > | -----Original Message-----
> | > | > | From: John Havlicek [mailto:john.havlicek@motorola.com]
> | > | > | Sent: Thursday, March 13, 2003 6:50 PM
> | > | > | To: sv-ac@eda.org
> | > | > | Subject: [sv-ac] revised local variable proposal
> | > | > | =3D3D20
> | > | > | =3D3D20
> | > | > | All:
> | > | > | =3D3D20
> | > | > | Below is a revision of the local variable proposal I=3D20
> | > | sent last week.
> | > | > | =3D3D20
> | > | > | I have deleted the capability of getting local=20
> | variables out of
> | > | > | named sequences through hierarchical references=20
> | because it =3D
> | > seems
> | > | > | to be a fringe feature that adds complexity to the =3D
> | > semantics=3D3D20
> | > | > | out of proportion to the benefit provided.
> | > | > | =3D3D20
> | > | > | I have also changed the syntax to allow local=20
> | variables to =3D
> | > be=3D3D20
> | > | > | attached either to the beginning or to the end of a =3D3D
> | > | > sequence_element.
> | > | > | This makes the definition of the sampling point=3D20
> | > | convenient for the
> | > | > | user without adding any semantic complexity.
> | > | > | =3D3D20
> | > | > | Best regards,
> | > | > | =3D3D20
> | > | > | John Havlicek
> | > | > | =3D3D20
> | > | > | =3D3D
> | > | >=3D20
> | > | =3D
> | >=20
> | =
> =3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D=
> 3D3D=3D3D3D=3D
> | 3D3D=3D3D3D=3D3D=3D
> | > 3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D
> | > | 3D=3D3D3D=3D3D3D=3D3D3D=3D3D
> | > | >=3D20
> | > | =3D
> | >=20
> | =
> =3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D=
> 3D3D=3D3D3D=3D
> | 3D3D=3D3D3D=3D3D=3D
> | > 3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D
> | > | 3D=3D3D3D=3D3D3D=3D3D3D=3D3D
> | > | > =3D
> | >=20
> | =
> =3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D3D3D=3D=
> 3D3D=3D3D3D=3D
> | 3D3D=3D3D3D=3D3D=3D
> | > 3D=3D3D3D=3D3D3D=3D3D3D
> | > | > | =3D3D20
> | > | > | DISCUSSION:
> | > | > | =3D3D20
> | > | > | The local (i.e., dynamic) variables described in=20
> | LRM 0.80=3D3D20
> | > | > | are severely=3D3D20
> | > | > | restricted by the strict scoping rules. Since=20
> | nesting of=3D3D20
> | > | > | implications
> | > | > | has been eliminated, it is no longer possible to=20
> | attach=3D3D20
> | > | > | local variables
> | > | > | to the desired sampling point withing the lhs of an=3D3D20
> | > | > | implication. There
> | > | > | has never been a mechanism for publishing local=3D20
> | > | variables outside of
> | > | > | a named subsequence or an instance thereof.
> | > | > | =3D3D20
> | > | > | This proposal attempts to overcome these=20
> | limitations of=3D3D20
> | > | > | local variables
> | > | > | without separating the declaration of a local variable =3D
> | > from=3D3D20
> | > | > | the sampling
> | > | > | point. The basic idea is to use a "forward flow"=3D20
> | > | semantics for=3D3D20
> | > | > | local variables. Intuitively, once a local=20
> | variable is=3D3D20
> | > | > | sampled, it can
> | > | > | be referenced at that or any later point of a=20
> | sequence or=3D3D20
> | > | > | implication.
> | > | > | The definition and sampling of a local variable can =
> be=3D3D20
> | > | > | attached to the=3D3D20
> | > | > | beginning or to the end of a sequence element.
> | > | > | =3D3D20
> | > | > | Thus, one can write a sequence like=3D3D20
> | > | > | =3D3D20
> | > | > | (a; !a (int x =3D3D3D data_in); !b*[0:inf]; b &&=3D20
> | > | (data_out =3D3D3D=3D3D3D x))
> | > | > | =3D3D20
> | > | > | or an implication like
> | > | > | =3D3D20
> | > | > | (a; !a (int x =3D3D3D data_in)) =3D3D3D>=20
> | (!b*[0:inf]; b &&=3D20
> | > | (data_out =3D3D
> | > | > =3D3D3D=3D3D3D x))
> | > | > | =3D3D20
> | > | > | and understand that the value sampled into x is=20
> | available=3D3D20
> | > | > | "further to the=3D3D20
> | > | > | right" in the sequence or implication.
> | > | > | =3D3D20
> | > | > | Furthermore, one can write local variables on repeated =3D
> | > sequences
> | > | > | and accomplish accumulation of values, as in=3D3D20
> | > | > | =3D3D20
> | > | > | (int x =3D3D3D 0) ((!a*[0:inf]; a (int x =3D3D3D=3D20
> | > | x+data))*[4]; b; c=3D3D20
> | > | > | && (data_out =3D3D3D=3D3D3D x))
> | > | > | =3D3D20
> | > | > | The challenge that comes with the forward flow=20
> | semantics is to
> | > | > | define which local variables are visible after a join=3D20
> | > | ("or", "and",
> | > | > | "intersect"). The motivating principle in this=20
> | proposal is =3D
> | > that
> | > | > | local variables which are guaranteed to exist after =
> the=3D20
> | > | join without
> | > | > | collision can flow on, while other local variables=20
> | will be lost
> | > | > | after the join.
> | > | > | =3D3D20
> | > | > | =3D3D20
> | > | > | PROPOSAL:
> | > | > | =3D3D20
> | > | > | This feature allows one to declare local variables=20
> | and use them
> | > | > | anywhere subsequent in the property or sequence =
> without=3D20
> | > | > | using the strict=3D3D20
> | > | > | scoping of 0.80 LRM. =3D3D20
> | > | > | =3D3D20
> | > | > | SYNTAX:
> | > | > | =3D3D20
> | > | > | BNF
> | > | > | =3D3D20
> | > | > | sequence_element ::=3D3D3D
> | > | > | "sequence_element as currently defined"
> | > | > | | `('var_decl`)' sequence_element
> | > | > | | sequence_element `('var_decl`)'
> | > | > | =3D3D20
> | > | > | SEMANTICS:
> | > | > | =3D3D20
> | > | > | 1) The declaration and assignment point of the =
> local=3D3D20
> | > | > | variables is the same.=3D3D20
> | > | > | For example,
> | > | > | =3D3D20
> | > | > | sequence s1 =3D3D3D (a ; b (int x =3D3D3D data); =
> =3D
> | > (c=3D3D3D=3D3D3Dx));
> | > | > | =3D3D20
> | > | > | 2) There is no explicit scoping of variables=20
> | related to=3D3D20
> | > | > | subsequences. Once=3D3D20
> | > | > | declared, the variable is available until the end of =
> =3D
> | > the=3D3D20
> | > | > | sequence or property.=3D3D20
> | > | > | For example,
> | > | > | =3D3D20
> | > | > | property p1 =3D3D3D ((a ; b (int x =3D3D3D=20
> | data); c) =3D3D3D>=3D20
> | > | (d=3D3D3D=3D3D3Dx));
> | > | > | =3D3D20
> | > | > | 3) The local variable may be used as initializer for =3D
> | > another=3D3D20
> | > | > | local variable=3D3D20
> | > | > | declared later in the sequence. For example,
> | > | > | =3D3D20
> | > | > | property p2 =3D3D3D ((a ; b (int x =3D3D3D=20
> | data); c) =3D3D3D>=3D20
> | > | (1; d (int=3D3D20
> | > | > | x1 =3D3D3D x + data1); e=3D3D3D=3D3D3Dx1));
> | > | > | =3D3D20
> | > | > | 4) If a local variable is redeclared with the same=20
> | name=3D3D20
> | > | > | later in the sequence,=3D3D20
> | > | > | then the later version of the variable shadows =
> the=3D3D20
> | > | > | previous declaration.=3D3D20
> | > | > | Any reference after the redeclaraion in the=20
> | sequence to=3D3D20
> | > | > | the variable will be=3D3D20
> | > | > | accessing the later declaration. Also, rhs of =
> the=3D3D20
> | > | > | initialization of a variable
> | > | > | may reference a local variable with the same=20
> | name, in=3D3D20
> | > | > | which case, the previous
> | > | > | version of the variable will be used to=20
> | initialize the=3D3D20
> | > | > | declaration. For example,
> | > | > | =3D3D20
> | > | > | property p3 =3D3D3D ((a ; b (int x =3D3D3D=20
> | data); c) =3D3D3D>=3D20
> | > | (1; d (int=3D3D20
> | > | > | x =3D3D3D x + data1); e=3D3D3D=3D3D3Dx));
> | > | > | =3D3D20
> | > | > | 5) There are special considerations on declaring=20
> | and using=3D3D20
> | > | > | local variables in=3D3D20
> | > | > | parallel branches ("or", "and" and "intersect").=3D3D20
> | > | > | =3D3D20
> | > | > | i) Variables declared on parallel threads cannot =
> be=3D3D20
> | > | > | accessed in sibling threads.=3D3D20
> | > | > | For example,
> | > | > | =3D3D20
> | > | > | sequence s4 =3D3D3D ((a ; (int x =3D3D3D=20
> | data) b; c) or =3D
> | > (d;=3D3D20
> | > | > | (e=3D3D3D=3D3D3Dx))); // this is illegal
> | > | > | =3D3D20
> | > | > | ii) In the case of "or", it is the intersection=20
> | of the=3D3D20
> | > | > | variables (names)
> | > | > | that passes on past the join. All succeeding=20
> | threads=3D3D20
> | > | > | out of "or" branches
> | > | > | continue as separate threads after the join, =3D
> | > carrying=3D3D20
> | > | > | with them their=3D3D20
> | > | > | version of the local variables. For example,
> | > | > | =3D3D20
> | > | > | sequence s5 =3D3D3D (=3D3D20
> | > | > | (
> | > | > | (a ; (int x =3D3D3D=20
> | data, int y =3D
> | > =3D3D3D=3D3D20
> | > | > | data1) b; c)=3D3D20
> | > | > | ||=3D3D20
> | > | > | (d; (int x =3D3D3D data) =3D
> | > (e=3D3D3D=3D3D3Dx))
> | > | > | ) ;=3D3D20
> | > | > | (y=3D3D3D=3D3D3Ddata2)=3D3D20
> | > | > | );=3D3D20
> | > | > | // illegal since y is not in =
> the=3D20
> | > | intersection
> | > | > | =3D3D20
> | > | > | sequence s6 =3D3D3D (=3D3D20
> | > | > | (
> | > | > | (a ; (int x =3D3D3D=20
> | data, int y =3D
> | > =3D3D3D=3D3D20
> | > | > | data1) b; c)=3D3D20
> | > | > | ||=3D3D20
> | > | > | (d; (int x =3D3D3D data) =3D
> | > (e=3D3D3D=3D3D3Dx))
> | > | > | ) ;=3D3D20
> | > | > | (x=3D3D3D=3D3D3Ddata2)=3D3D20
> | > | > | );=3D3D20
> | > | > | // legal since x is in the=20
> | intersection
> | > | > | =3D3D20
> | > | > | iii) In the case of "and" and "intersect", the=20
> | symmetric=3D3D20
> | > | > | difference of the local=3D3D20
> | > | > | variables that were introduced in the two=20
> | joining=3D3D20
> | > | > | threads passes on past the=3D3D20
> | > | > | join. In other words, each thread passes on=20
> | its new=3D3D20
> | > | > | local variables that do=3D3D20
> | > | > | not appear as new local variables in the other =3D
> | > thread.=3D3D20
> | > | > | A Local variable that
> | > | > | existed at the fork [i.e., at the start of=20
> | the "and"=3D3D20
> | > | > | or "intersect"] of
> | > | > | the two threads is passed on provided that it was =
> =3D
> | > not=3D3D20
> | > | > | overwritten in either
> | > | > | of the joining threads. Since only the difference =
> =3D
> | > of=3D3D20
> | > | > | the new variables is=3D3D20
> | > | > | passed on, the two joining threads are merged into =
> =3D
> | > one=3D3D20
> | > | > | thread at the join.
> | > | > | =3D3D20
> | > | > | sequence s7 =3D3D3D (=3D3D20
> | > | > | (
> | > | > | (a ; (int x =3D3D3D=20
> | data, int y =3D
> | > =3D3D3D=3D3D20
> | > | > | data1) b; c)=3D3D20
> | > | > | &&
> | > | > | (d; (int x =3D3D3D data) =3D
> | > (e=3D3D3D=3D3D3Dx))
> | > | > | ) ;=3D3D20
> | > | > | (x=3D3D3D=3D3D3Ddata2)=3D3D20
> | > | > | );=3D3D20
> | > | > | // illegal since x common to both =
> =3D
> | > threads
> | > | > | =3D3D20
> | > | > | sequence s8 =3D3D3D (=3D3D20
> | > | > | (
> | > | > | (a ; (int x =3D3D3D=20
> | data, int y =3D
> | > =3D3D3D=3D3D20
> | > | > | data1) b; c)=3D3D20
> | > | > | &&=3D3D20
> | > | > | (d; (int x =3D3D3D data) =3D
> | > (e=3D3D3D=3D3D3Dx))
> | > | > | ) ;=3D3D20
> | > | > | (y=3D3D3D=3D3D3Ddata2)=3D3D20
> | > | > | );=3D3D20
> | > | > | // legal since y is in the=20
> | difference
> | > | > | =3D3D20
> | > | > | =3D3D20
> | > | > | iv) The intersection and difference of the sets=20
> | of names=3D3D20
> | > | > | should be computed=3D3D20
> | > | > | statically at compile time.
> | > | > | =3D3D20
> | > | =3D20
> | =20
This archive was generated by hypermail 2b28 : Mon Mar 17 2003 - 11:56:52 PST