aboutsummaryrefslogtreecommitdiff
path: root/docs/spec/scope.html
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2021-08-11 17:21:31 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2021-08-11 17:25:04 -0400
commit2afb23928e1984d475cc460e1672e8f6fa0e4dbe (patch)
treeebd2cc514294d30b6fa4b36c2ee638326f06ef72 /docs/spec/scope.html
parenteac61ca02074c218667754d5f4ef562e780bae85 (diff)
Allow clicking on header to get fragment link
Diffstat (limited to 'docs/spec/scope.html')
-rw-r--r--docs/spec/scope.html12
1 files changed, 6 insertions, 6 deletions
diff --git a/docs/spec/scope.html b/docs/spec/scope.html
index be592157..5576f6c8 100644
--- a/docs/spec/scope.html
+++ b/docs/spec/scope.html
@@ -4,10 +4,10 @@
<title>Specification: BQN variable scoping</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-variable-scoping">Specification: BQN variable scoping</h1>
+<h1 id="specification-bqn-variable-scoping"><a class="header" href="#specification-bqn-variable-scoping">Specification: BQN variable scoping</a></h1>
<p>BQN uses lexical scoping for variables, where scopes correspond roughly to blocks, or pairs of curly braces separated by semicolons. At the top level in a scope, new variables are visible only after they are defined, but in the scopes it contains, all variables defined in that scope are visible. This system is specified more precisely below.</p>
<p>A running BQN program manipulates variables during its <a href="evaluate.html">execution</a>, but it is important to distinguish these variables from the identifiers that refer to them. As defined in the <a href="token.html">tokenization rules</a>, an identifier is a particular kind of token found in a program's source code. The lexical scoping rules in this page define which identifiers are considered the same; these identifiers will refer to the same variables when the program is run. While each variable has only one identifier, an identifier can refer to any number of variables because a new variable is created for that identifier each time its containing scope is instantiated (that is, each time the contents of the block are evaluated).</p>
-<h2 id="identifier-equivalence-with-lexical-scoping">Identifier equivalence with lexical scoping</h2>
+<h2 id="identifier-equivalence-with-lexical-scoping"><a class="header" href="#identifier-equivalence-with-lexical-scoping">Identifier equivalence with lexical scoping</a></h2>
<p>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 &quot;same thing&quot;. In concrete terms, identifiers with the same definition all manipulate the same variable in a particular instance of the definition's containing scope.</p>
<p>A <em>scope</em> is a <code><span class='Function'>PROGRAM</span></code>, <code><span class='Value'>brSub</span></code>, <code><span class='Function'>FCase</span></code>, <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_mCase</span></code>, <code><span class='Modifier'>_mMain</span></code>, <code><span class='Modifier2'>_cCase_</span></code>, <code><span class='Modifier2'>_cMain_</span></code>, or <code><span class='Value'>brNS</span></code> node as defined by the BQN <a href="grammar.html">grammar</a>. An <em>identifier instance</em> is an <code><span class='Value'>s</span></code>, <code><span class='Function'>F</span></code>, <code><span class='Modifier'>_m</span></code>, or <code><span class='Modifier2'>_c_</span></code> node; its <em>containing scope</em> is the &quot;smallest&quot; scope that contains itβ€”the scope that contains the identifier but not any other scopes containing the identifier. An identifier instance is <em>defined</em> when it is contained in the left hand side of an <code><span class='Gets'>←</span></code> assignment expression, that is, the leftmost component of one of the five grammatical rules with <code><span class='Function'>ASGN</span></code>, provided that the <code><span class='Function'>ASGN</span></code> node is <code><span class='String'>&quot;←&quot;</span></code> or <code><span class='String'>&quot;⇐&quot;</span></code>, or in a scope header, that is, a component immediately preceding <code><span class='String'>&quot;:&quot;</span></code>. Each identifier instance in a valid BQN program corresponds to exactly one such defined identifier, called its <em>definition</em>, and two instances are considered to refer to the same identifier if they have the same definition.</p>
<p>Two identifier instances have the <em>same name</em> if their tokens, as strings, match after removing all underscores <code><span class='Modifier2'>_</span></code> 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 <em>potential definition</em> of another identifier instance if the two have the same name, and either:</p>
@@ -19,16 +19,16 @@
<p>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.</p>
<p>The definition of <em>program order</em> for identifier tokens follows the order of BQN <a href="evaluate.html">execution</a>. 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 right come earlier in program order. The exceptions are <code><span class='Function'>PROGRAM</span></code>, <code><span class='Function'>BODY</span></code>, <code><span class='Function'>NS_BODY</span></code>, <code><span class='Value'>list</span></code>, <code><span class='Value'>subject</span></code> (for stranding), and body case (<code><span class='Function'>FCase</span></code>, <code><span class='Modifier'>_mCase</span></code>, <code><span class='Modifier2'>_cCase_</span></code>, <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_mMain</span></code>, <code><span class='Modifier2'>_cMain_</span></code>, <code><span class='Value'>brSub</span></code>, <code><span class='Function'>BrFunc</span></code>, <code><span class='Modifier'>_brMod1</span></code>, and <code><span class='Modifier2'>_brMod2_</span></code>) 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).</p>
<p>A subject label is the <code><span class='Value'>s</span></code> term in a <code><span class='Value'>brSub</span></code> node. As part of a header, it can serve as the definition for an identifier. However, it's defined to be a syntax error if another instance of this identifier appears, except in a <code><span class='Function'>Return</span></code> node (which cannot access its value).</p>
-<h3 id="special-names">Special names</h3>
+<h3 id="special-names"><a class="header" href="#special-names">Special names</a></h3>
<p>Special names such as <code><span class='Value'>𝕩</span></code> or <code><span class='Value'>𝕣</span></code> 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.</p>
<p>The six special names are <code><span class='Value'>π•¨π•©π•—π•˜π•€π•£</span></code>, and the tokens <code><span class='Function'>π•Žπ•π”½π”Ύπ•Š</span></code>, <code><span class='Modifier'>_𝕣</span></code>, and <code><span class='Modifier2'>_𝕣_</span></code> are alternate spellings of these names as described in the <a href="token.html">tokenization rules</a>. Special names may be modified with <code><span class='Gets'>↩</span></code> 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 <a href="evaluate.html">evaluation rules</a>; the grammar for blocks ensures that all special names used in a block will be defined (possibly as the special value <code><span class='Nothing'>Β·</span></code> in the case of <code><span class='Value'>𝕨</span></code>).</p>
-<h3 id="imports-and-exports">Imports and exports</h3>
+<h3 id="imports-and-exports"><a class="header" href="#imports-and-exports">Imports and exports</a></h3>
<p>Names that are preceded by an <code><span class='Value'>atom</span> <span class='String'>&quot;.&quot;</span></code> term, or that appear as <code><span class='Function'>LHS_NAME</span></code> terms in an <code><span class='Function'>NS_VAR</span></code> or <code><span class='Value'>lhsNs</span></code>, are variable references in a namespace: in the first case, the result of the <code><span class='Value'>atom</span></code> node, and in the second, of the overall assignments <code><span class='Value'>subExpr</span></code> right hand side. These names do not follow lexical scoping; in general they must be stored in order to perform a name lookup when the namespace is available. Such a name in <code><span class='Value'>lhsNs</span></code>, or in <code><span class='Function'>NS_VAR</span></code> with no accompanying <code><span class='Value'>lhs</span> <span class='String'>&quot;⇐&quot;</span></code> term, additionally serves as an identifier within the actual enclosing scope, which works like any other assignment.</p>
<p>An identifier is <em>exported</em> if the <code><span class='Function'>ASGN</span></code> node in its definition is <code><span class='String'>&quot;⇐&quot;</span></code>, or if it appears anywhere in an <code><span class='Function'>EXPORT</span></code> term. An identifier can only be exported in the scope where it is defined, and not in a containing scope. An <code><span class='Function'>EXPORT</span></code> term that includes an identifier from such a scope causes an error.</p>
-<h2 id="variables">Variables</h2>
+<h2 id="variables"><a class="header" href="#variables">Variables</a></h2>
<p>A <em>variable</em> is an entity that permits two operations: it can be <em>set</em> to a particular value, and its <em>value</em> can be obtained, resulting in the last value it was set to. When either operation is performed it is referred to as <em>accessing</em> the variable.</p>
<p>When a body in a block is evaluated, it creates a <em>namespace</em>, which contains a variable for each definition (that is, defined identifier instance) the body contains. Whenever another blockβ€”the block itself, not its contentsβ€”is evaluated during the execution of the block, it is linked to the currently-evaluating block, so that it will use the variables defined in this instance. By following these links repeatedly, an instance of a block is always linked to exactly one instance of each block that contains it. These links form a tree that is not necessarily related to the call stack of functions and modifiers. Using the links, the variable an identifier refers to is the one corresponding to that variable's definition in the linked instance of the containing scope for the definition.</p>
<p>The first access to a variable must be made by its definition (this also means it sets the variable). If a different instance of its identifier accesses it first, then an error results. This can happen because every scope contained in a particular scope sees all the definitions it uses, and such a scope could be called before the definition is run. Because of conditional execution, this property must be checked at run time in general; however, in cases where it is possible to statically determine that a program will always violate it, a BQN instance can give an error at compile time rather than run time.</p>
<p>A namespace defines a mapping from names to variables: if the given name is shared by an exported identifier in the body used to create that namespace, then that name maps to the variable corresponding to that identifier. The mapping is undefined for other names.</p>
-<h2 id="returns">Returns</h2>
+<h2 id="returns"><a class="header" href="#returns">Returns</a></h2>
<p>The name <code><span class='Function'>NAME</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Function'>|</span> <span class='String'>&quot;𝕣&quot;</span></code> in a <code><span class='Function'>Return</span></code> node is resolved exactly like any other identifier. Following resolution, the block that defines the identifier must not be a namespace block (export variables or contain an <code><span class='Function'>EXPORT</span></code> statement). Furthermore, if it is a <code><span class='Function'>NAME</span></code>, then its definition must be an internal name for a containing block: <code><span class='Value'>s</span></code> in <code><span class='Value'>brSub</span></code>, <code><span class='Function'>F</span></code> in <code><span class='Function'>FuncHead</span></code> or <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_m</span></code> in <code><span class='Function'>Mod1H1</span></code> or <code><span class='Modifier'>_mMain</span></code>, or <code><span class='Modifier2'>_c_</span></code> in <code><span class='Function'>Mod2H1</span></code> or <code><span class='Modifier2'>_cMain_</span></code>. When reached, the <code><span class='Function'>Return</span></code> node's identifier is not accessed; instead, it is used to indicate the namespace that contains it, and through this the block evaluation that created that namespace.</p>