diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-10-12 22:29:47 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2020-10-12 22:29:47 -0400 |
| commit | 7583529c468fcbbc5b99eca6fd36785305c51114 (patch) | |
| tree | 4d0561709b366149c50ac582c26933c4bb1c5aca /spec | |
| parent | e416644a9b0837425d016f64ff04100c25dc813e (diff) | |
Add import and export scoping rules
Diffstat (limited to 'spec')
| -rw-r--r-- | spec/scope.md | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/spec/scope.md b/spec/scope.md index b015f463..7af09957 100644 --- a/spec/scope.md +++ b/spec/scope.md @@ -10,7 +10,7 @@ A running BQN program manipulates variables during its [execution](evaluate.md), In this section the concept of an identifier's definition, a possibly different instance of that identifier, is specified. The definition determines when identifiers refer to the "same thing". In concrete terms, identifiers with the same definition all manipulate the same variable in a particular instance of the definition's containing scope. -A *scope* is a `PROGRAM`, `brSub`, `FCase`, `FMain`, `_mCase`, `_mMain`, `_cCase_`, or `_cMain_` node as defined by the BQN [grammar](grammar.md). An *identifier instance* is an `s`, `F`, `_m`, or `_c_` node; its *containing scope* is the "smallest" scope that contains it—the scope that contains the identifier but not any other scopes containing the identifier. An identifier instance is *defined* when it is contained in the left hand side of an `←` assignment expression, that is, the leftmost component of one of the four grammatical rules with `ASGN`, provided that the `ASGN` node is `"←"`, or in a scope header, that is, a component immediately preceding `":"`. Each identifier instance in a valid BQN program corresponds to exactly one such defined identifier, called its *definition*, and two instances are considered to refer to the same identifier if they have the same definition. +A *scope* is a `PROGRAM`, `brSub`, `FCase`, `FMain`, `_mCase`, `_mMain`, `_cCase_`, `_cMain_`, or `brNS` node as defined by the BQN [grammar](grammar.md). An *identifier instance* is an `s`, `F`, `_m`, or `_c_` node; its *containing scope* is the "smallest" scope that contains it—the scope that contains the identifier but not any other scopes containing the identifier. An identifier instance is *defined* when it is contained in the left hand side of an `←` assignment expression, that is, the leftmost component of one of the five grammatical rules with `ASGN`, provided that the `ASGN` node is `"←"` or `"⇐"`, or in a scope header, that is, a component immediately preceding `":"`. Each identifier instance in a valid BQN program corresponds to exactly one such defined identifier, called its *definition*, and two instances are considered to refer to the same identifier if they have the same definition. Two identifier instances have the *same name* if their tokens, as strings, match after removing all underscores `_` and ignoring case (so that the letters a to z are equal to their uppercase equivalents A to Z for this comparison). However, instances with the same name are not necessarily the same identifier, as they must also have the same definition. A defined identifier is a *potential definition* of another identifier instance if the two have the same name, and either: - The defined identifier's containing scope contains the other identifier's containing scope, or @@ -18,14 +18,20 @@ Two identifier instances have the *same name* if their tokens, as strings, match - The two identifiers are the same instance (a defined variable is its own definition). The definition for an identifier is chosen from the potential definitions based on their containing scopes: it is the one whose containing scope does not contain or match the containing scope of any other potential definition. If for any identifier there is no definition, then the program is not valid and results in an error. This can occur if the identifier has no potential definition, and also if two potential definitions appear in the same scope. In fact, under this scheme it is never valid to make two definitions with the same name at the top level of a single scope, because both definitions would be potential definitions for the one that comes second in program order. Both definitions have the same containing scope, and any potential definition must contain or match this scope, so no potential definition can be selected. -The definition of *program order* for identifier tokens follows the order of BQN [execution](evaluate.md). It corresponds to the order of a particular traversal of the abstract syntax tree for a program. To find the relative ordering of two identifiers in a program, we consider the highest-depth node that they both belong to; in this node they must occur in different components, or that component would be a higher-depth node containing both of them. In most nodes, the program order goes from right to left: components further to the left come earlier in program order. The exceptions are `PROGRAM`, `BODY`, `list`, `subject` (for stranding), and body case (`FCase`, `_mCase`, `_cCase_`, `FMain`, `_mMain`, `_cMain_`, `brSub`, `BrFunc`, `_brMod1`, and `_brMod2_`) nodes, in which program order goes in the opposite order, from left to right (some assignment target nodes also contain lists or strands, but their ordering is irrelevant because if two identifiers with the same name appear in such a list, then it can't be a definition). +The definition of *program order* for identifier tokens follows the order of BQN [execution](evaluate.md). It corresponds to the order of a particular traversal of the abstract syntax tree for a program. To find the relative ordering of two identifiers in a program, we consider the highest-depth node that they both belong to; in this node they must occur in different components, or that component would be a higher-depth node containing both of them. In most nodes, the program order goes from right to left: components further to the left come earlier in program order. The exceptions are `PROGRAM`, `BODY`, `NS_BODY`, `list`, `subject` (for stranding), and body case (`FCase`, `_mCase`, `_cCase_`, `FMain`, `_mMain`, `_cMain_`, `brSub`, `BrFunc`, `_brMod1`, and `_brMod2_`) nodes, in which program order goes in the opposite order, from left to right (some assignment target nodes also contain lists or strands, but their ordering is irrelevant because if two identifiers with the same name appear in such a list, then it can't be a definition). -## Special names +### Special names Special names such as `𝕩` or `𝕣` refer to variables, but have no definition and do not use scoping. Instead, they always refer to the immediately enclosing scope, and are defined automatically when the block is evaluated. The six special names are `𝕨𝕩𝕗𝕘𝕤𝕣`, and the tokens `𝕎𝕏𝔽𝔾𝕊`, `_𝕣`, and `_𝕣_` are alternate spellings of these names as described in the [tokenization rules](token.md). Special names may be modified with `↩` assignment but cannot appear as the target of other kinds of assignment. Two special names represent the same identifier if they are the same name and appear in the same body. The initial value these names have is defined by the [evaluation rules](evaluate.md); the grammar for blocks ensures that all special names used in a block will be defined (possibly as the special value `·` in the case of `𝕨`). +### Imports and exports + +The names to be used in an `IMPORT`, that is, `LHS_NAME` terms in an `NS_VAR` or `nsLHS`, are variable references inside that `IMPORT`'s `brNS` term. If they appear without an accompanying `lhs "⇐"` term (in `NS_VAR`), then this is in addition to their role as identifiers within the actual enclosing scope, which works like any other assignment. These references behave as though they are at the end of the `brNS` term, that is, they "see" all definitions in the block. However, they must refer to identifiers that are *exported* by that block; references to any other variable cause an error much like references that have no definition. + +An identifier is exported if the `ASGN` node in its definition is `"⇐"`, or if it appears anywhere in an `EXPORT` term. An identifier can only be exported in the scope where it is defined, and not in a containing scope. An `EXPORT` term that includes an identifier from such a scope causes an error. + ## Variables A *variable* is an entity that permits two operations: it can be *set* to a particular value, and its *value* can be obtained, resulting in the last value it was set to. When either operation is performed it is referred to as *accessing* the variable. |
