Open YawarRaza7349 opened 1 day ago
2.1. With regard to a variable declared in a structure having OPEN scope, this is just an initial suggestion and has to be thought through. Declarations making up the body of a structure should behave (with respect to scoping and ultimate "visibility") just like declarations anywhere. They "denote" an environment, and that environment is packaged up (and potentially given a name) by the fact that the declaration is the body of a structure expression (i.e., occurs in struct <decl> end
). It is quite possible for declarations in a structure body to be shadowed, as in
structure S =
struct
val x = 3
val x = true
end
which results in a structure S that has one component, S.x, of type bool.
2.2. Signature matching can coerce the type of a polymorphic variable declared in the body of a matched structure to be an instance of its polymorphic type in the body. No anomaly here.
2.3 I don't understand your 3rd suggestion about "variables should only refer to identifiers that don't come after a period". An expression of the form S.x
is not a variable occurrence, it is a selection from a structure, which is a different form of expression. The fact that S.x
has been referred to as a "qualified identifier" has perhaps lead to some confusion.
v
in your example will have a single dynamic counterpart. This dynamic counterpart of v
will get bound to different dynamic argument values on different calls (as usual). In your example, the dynamic counterpart of v
will be bound to the value 1 in the first call and to the value 2 in the second call.To be pedantic, it is best to be careful to distinguish the idea of an "identifier" from that of a "variable". A record field label is an example of an identifier that is not a variable. Other identifiers, such as keywords, should be processed and eliminated during parsing and therefore are not a concern when dealing with the abstract, internal representation of programs (or perhaps keywords should not be considered to be identifiers!). There is also the notion of a symbol. For me, a symbol is an internal concrete representation of certain classes of identifiers, such as value variables, data constructors, tycons, type variables, etc.
Variables bound in the local section are also available in the subsequent lines in the local section:
It sounds like you want applied occurrences through a module identifier to refer exactly to the binding occurrence in a struct definition. I agree that it's desirable for scoping to not depend on module-level static semantics, but what about the following:
Do we want one variable,
f
, to have two different types,'a. 'a -> 'a
inside the struct andint -> int
outside the struct?Perhaps, and maybe there are problems with this approach too, but perhaps variables should only refer to identifiers that don't come after a period, and identifiers that do follow a period should instead be treated more like record labels, without the whole ceremony involving environments. After all, structure members don't require any sort of shadowing, do they? Otherwise, if you still wanted them to be variables, you would need to handle the signature ascription example above in some way.
Syntactic variables don't refer to a unique dynamic variable:
There's one syntactic variable,
v
, that refers to two dynamic variables, one assigned to 1 and one assigned to 2.If there is no lexical distinction between tycons and tyvars, then they should be in the same namespace as well. Consider the following hypothetical MsML (I'm using F#-esque angle brackets to avoid confusion in this specific example, not to suggest them for MsML):
You expect the
a
inCA
to refer to the type variable, shadowing the datatype, while theb
inCB
instead refers to the datatype. It makes most sense to think ofb
and botha
s as all being in the same namespace, since you can't tell whether a variable in a type refers to a tycon or a tyvar just by syntactic categories alone, without looking at what's in scope.