diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-03-15 16:59:32 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-03-15 16:59:32 -0400 |
| commit | 4f618598f2f31bc466343e4d304f35b53a366da6 (patch) | |
| tree | f645f16425939a45ac82fcd0b3b477f9030bc7d9 /spec/evaluate.md | |
| parent | e858f41dffaee272ffcf4b2cb63a49ad25ebf7d7 (diff) | |
Finish namespace specification
Diffstat (limited to 'spec/evaluate.md')
| -rw-r--r-- | spec/evaluate.md | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/spec/evaluate.md b/spec/evaluate.md index c5d99751..625192f4 100644 --- a/spec/evaluate.md +++ b/spec/evaluate.md @@ -10,7 +10,7 @@ Here we assume that the referent of each identifier, or equivalently the connect The result of parsing a valid BQN program is a `PROGRAM`, and the program is run by evaluating this term. -A `PROGRAM` or `BODY` is a list of `STMT`s (for `BODY`, the last must be an `EXPR`, a particular kind of `STMT`), which are evaluated in program order. The statement `EXPR` evaluates some APL code and possibly assigns the results, while `nothing` evaluates any `subject` or `Derv` terms it contains but discards the results. +A `PROGRAM` or `BODY` is a list of `STMT`s, which are evaluated in program order. A result is always required for `BODY` nodes, and sometimes for `PROGRAM` nodes (for example, when loaded with `β’Import`). If any identifiers in the node's scope are exported, or any of its statements is an `EXPORT`, then the result is the namespace created in order to evaluate the node. If a result is required but the namespace case doesn't apply, then the last `STMT` node must be an `EXPR` and its result is used. The statement `EXPR` evaluates some APL code and possibly assigns the results, while `nothing` evaluates any `subject` or `Derv` terms it contains but discards the results. An `EXPORT` statement performs no action. A block consists of several `BODY` terms, some of which may have an accompanying header describing accepted inputs and how they are processed. An immediate block `brImm` can only have one `BODY`, and is evaluated by evaluating the code in it. Other types of blocks do not evaluate any `BODY` immediately, but instead return a function or modifier that obtains its result by evaluating a particular `BODY`. The `BODY` is identified and evaluated once the block has received enough inputs (operands or arguments), which for modifiers can take one or two calls: if two calls are required, then on the first call the operands are simply stored and no code is evaluated yet. Two calls are required if there is more than one `BODY` term, if the `BODY` contains the special names `π¨π©π€πππ`, or if its header specifies arguments (the header-body combination is a `_mCase` or `_cCase_`). Otherwise only one is required. @@ -22,15 +22,15 @@ If there is no left argument, but the `BODY` contains `π¨` at the top level, t ### Assignment -An *assignment* is one of the four rules containing `ASGN`, other than `IMPORT`. It is evaluated by first evaluating the right-hand-side `subExpr`, `FuncExpr`, `_m1Expr`, or `_m2Exp_` expression, and then storing the result in the left-hand-side identifier or identifiers. The result of the assignment expression is the result of its right-hand side. Except for subjects, only a lone identifier is allowed on the left-hand side and storage sets it equal to the result. For subjects, *multiple assignment* with a list left-hand side is also allowed. Multiple assignment is performed recursively by assigning right-hand-side values to the left-hand-side targets, with single-identifier (`s`) assignment as the base case. When matching the right-hand side to a list left-hand side, the left hand side is treated as a list of `lhs` targets. The evaluated right-hand side must be a list (rank-1 array) of the same length, and is matched to these targets element-wise. +An *assignment* is one of the four rules containing `ASGN`. It is evaluated by first evaluating the right-hand-side `subExpr`, `FuncExpr`, `_m1Expr`, or `_m2Exp_` expression, and then storing the result in the left-hand-side identifier or identifiers. The result of the assignment expression is the result of its right-hand side. Except for subjects, only a lone identifier is allowed on the left-hand side and storage sets it equal to the result. For subjects, *destructuring assignment* is performed when an `lhs` is `lhsList` or `lhsStr`. Destructuring assignment is performed recursively by assigning right-hand-side values to the left-hand-side targets, with single-identifier assignment as the base case. -*Modified assignment* is the subject assignment rule `lhs Derv "β©" subExpr`. In this case, `lhs` should be evaluated as if it were a `subExpr` (the syntax is a subset of `subExpr`), and the result of the function application `lhs Derv subExpr` should be assigned to `lhs`, and is also the result of the modified assignment expression. +The right-hand-side value, here called `v`, in destructuring assignment must be a list (rank 1 array) or namespace. If it's a list, then each `LHS_ENTRY` node must be an `LHS_ELT`. The left-hand side is treated as a list of `lhs` targets, and matched to `v` element-wise, with an error if the two lists differ in length. If `v` is a namespace, then the left-hand side must be an `lhsStr` where every `LHS_ATOM` is an `LHS_NAME`, or an `lhsList` where every `LHS_ENTRY` is an `LHS_NAME` or `lhs "β" LHS_NAME`, so that it can be considered a list of `LHS_NAME` nodes some of which are also associated with `lhs` nodes. To perform the assignment, the value of each name is obtained from the namespace `v`, giving an error if `v` does not define that name. The value is assigned to the `lhs` node if present (which may be a destructuring assignment or simple subject assignment), and otherwise assigned to the same `LHS_NAME` node used to get it from `v`. -The `IMPORT` rule resembles a multiple assignment. However, in this case the values passed do not form a list but rather a module or namespace, which in this specification is not a value accessible to the programmer. To evaluate the `IMPORT` the `brNS` side is evaluated, then each inner variable mentioned in the `nsLHS` term is extracted and assigned to the corresponding outer identifier. Typically the two will both share the `LHS_NAME`, but if `β` is used in an `NS_VAR` then the `lhs` term refers to the outer identifier and `LHS_NAME` to the inner one. Since `IMPORT` is a statement and not an expression, it doesn't have a result value. +*Modified assignment* is the subject assignment rule `lhs Derv "β©" subExpr`. In this case, `lhs` should be evaluated as if it were a `subExpr` (the syntax is a subset of `subExpr`), and the result of the function application `lhs Derv subExpr` should be assigned to `lhs`, and is also the result of the modified assignment expression. ### Expressions -We now give rules for evaluating an `atom`, `Func`, `_mod1` or `_mod2_` expression (the possible options for `ANY`). A literal or primitive `sl`, `Fl`, `_ml`, or `_cl_` has a fixed value defined by the specification ([literals](literal.md) and [built-ins](primitive.md)). An identifier `s`, `F`, `_m`, or `_c_` is evaluated by returning its value; because of the scoping rules it must have one when evaluated. A parenthesized expression such as `"(" _modExpr ")"` simply returns the result of the interior expression. A braced construct such as `BraceFunc` is defined by the evaluation of the statements it contains after all parameters are accepted. Finally, a list `"β¨" β? ( ( EXPR β )* EXPR β? )? "β©"` or `ANY ( "βΏ" ANY )+` consists grammatically of a list of expressions. To evaluate it, each expression is evaluated in source order and their results are placed as elements of a rank-1 array. The two forms have identical semantics but different punctuation. +We now give rules for evaluating an `atom`, `Func`, `_mod1` or `_mod2_` expression (the possible options for `ANY`). A literal or primitive `sl`, `Fl`, `_ml`, or `_cl_` has a fixed value defined by the specification ([literals](literal.md) and [built-ins](primitive.md)). An identifier `s`, `F`, `_m`, or `_c_`, if not preceded by `atom "."`, must have an associated variable due to the scoping rules, and returns this variable's value, or causes an error if it has not yet been set. If it is preceded by `atom "."`, then the `atom` node is evaluated first; its value must be a namespace, and the result is the value of the identifier's name in the namespace, or an error if the name is undefined. A parenthesized expression such as `"(" _modExpr ")"` simply returns the result of the interior expression. A braced construct such as `BraceFunc` is defined by the evaluation of the statements it contains after all parameters are accepted. Finally, a list `"β¨" β? ( ( EXPR β )* EXPR β? )? "β©"` or `ANY ( "βΏ" ANY )+` consists grammatically of a list of expressions. To evaluate it, each expression is evaluated in source order and their results are placed as elements of a rank-1 array. The two forms have identical semantics but different punctuation. Rules in the table below are function and modifier evaluation. | L | Left | Called | Right | R | Types |
