Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Latest commit

 

History

History
436 lines (418 loc) · 32.4 KB

core-syntax.md

File metadata and controls

436 lines (418 loc) · 32.4 KB

Core-proposal syntax

ECMAScript Stage-0 Proposal. Living Document. J. S. Choi, 2018-12.

Most pipeline steps will use topic references in their steps. This style of pipeline step is called topic style.

For three simple cases – unary functions, unary async functions, and unary constructors – you may omit the topic reference from the pipeline step. This is called bare style.

When a pipe is in bare style, we refer to the pipeline as a bare function call. The step acts as just a simple reference to a function, such as with … |> capitalize or with … |> console.log. The step’s value would then be called as a unary function, without having to use the topic reference as an explicit argument.

The two bare-style productions require no parameters, because they can only be simple references, made up of identifiers and dots .. (There are optional Additional Features that extend these style in limited ways for further convenience. These Additional Features are not part of this Core Proposal but rather show possible future extensions.)

Valid topic style Valid bare style Invalid pipeline
… |> f(#) … |> f … |> f() 🚫
″″ ″″ … |> (f) 🚫
″″ ″″ … |> (f()) 🚫
… |> o.f(#) … |> o.f … |> o.f() 🚫
… |> o.f(arg, #) const f = $ => o::f(arg, $); … |> f … |> o.f(arg) 🚫
… |> o.make()(#) const f = o.make(); … |> f … |> o.make() 🚫
… |> o[symbol](#) const f = o[symbol]; … |> f … |> o[symbol] 🚫

Bare style

The bare style supports using simple identifiers, possibly with chains of simple property identifiers. If there are any operators, parentheses (including for method calls), brackets, or anything other than identifiers and dot punctuators, then it is in topic style, not in bare style.

If the pipeline step is a merely a simple reference, then that identifier is interpreted to be a bare function call. The pipeline’s value will be the result of evaluating the step as an identifier or member expression, then calling the result as a function, with the current topics as its arguments.

That is: if a pipeline is of the form
topic |> identifier
or topic |> identifier0.identifier1
or topic |> identifier0.identifier1.identifier2
or so forth,
then the pipeline is a bare function call.

Topic style

The presence or absence of topic tokens (#, ##, ###) is not used in the grammar to distinguish topic style from bare style to fulfill the goal of syntactic locality. Instead, if a pipeline step of the form |> step does not match the bare style (that is, it is not a bare function call, bare async function call, or bare constructor call), then it must be in topic style. Topic style requires that there be a topic reference in the pipeline step; otherwise it is an early error.

A pipeline step that is not in bare style is usually a topic expression. This is any expression at the precedence level once tighter than pipeline-level expressions – that is, any conditional-level expression.

Practical consequences

Therefore, a pipeline step in bare style never contains parentheses (…) or brackets […]. Neither … |> object.method() nor … |> object.method(arg) nor … |> object[symbol] nor … |> object.createFunction() are in bare style (in fact, they all are Syntax Errors, due to their being in topic style without any topic references).

When a pipeline step needs parentheses or brackets, then don’t use bare style, and instead use a topic reference in the step (topic style)…or assign the step to a variable, then use that variable as a bare-style step.

Operator precedence and associativity

As a infix operation forming compound expressions, the operator precedence and associativity of pipelining must be determined, relative to other operations.

Precedence is tighter than arrow functions (=>), assignment (=, +=, …), generator yield and yield *, and sequence ,; and it is looser than every other type of expression. If the pipe operation were any tighter than this level, its steps would have to be parenthesized for many frequent types of expressions. However, the result of a pipeline is also expected to often serve as the body of an arrow function or a variable assignment, so it is tighter than both types of expressions.

All operation-precedence levels in JavaScript are listed here, from tightest to loosest. Each level may contain the parse types listed for that level – as well as any expression types from any precedence level that is listed above it.

Level Type Form Associativity / fixity
Primary This this Nullary
″″ Primary topic # ″″
″″ Secondary topic ## ″″
″″ Tertiary topic ### ″″
″″ Rest topic ... ″″
″″ Identifiers a ″″
″″ Null null ″″
″″ Booleans true false ″″
″″ Numerics 0 ″″
″″ Arrays […] Circumfix
″″ Object {…} ″″
″″ Function function (…) {…} ″″
″″ Classes class … {…} ″″
″″ Generators function * (…) {…} ″″
″″ Async functions async function (…) {…} ″″
″″ Regular expression /…/… ″″
″″ Templates …`…` ″″
″″ Parentheses (…) Circumfix
LHS Static properties ….… ″″
″″ Dynamic properties …[…] LTR infix with circumfix
″″ Tagged templates …`…` Unchainable infix with circumfix
″″ Super call op.s super(…) Unchainable prefix
″″ Super properties super.… ″″
″″ Meta properties meta.… ″″
″″ Object construction new … Prefix
″″ Function call …(…) LTR infix with circumfix
Postfix unary Postfix incrementing …++ Postfix
″″ Postfix decrementing …-- ″″
Prefix unary Prefix incrementing ++… RTL prefix
Prefix unary Prefix decrementing --… ″″
″″ Deletes delete … ″″
″″ Voids void … ″″
″″ Unary +/- +… ″″
″″ Bitwise NOT ~… ~… ″″
″″ Logical NOT !… !… ″″
″″ Awaiting await … ″″
Exponentiation Exponentiation … ** … RTL infix
Multiplicative Multiplication … * … LTR infix
″″ Division … / … ″″
″″ Modulus … % … ″″
Additive Addition … + … ″″
″″ Subtraction … - … ″″
Bitwise shift Left shift … << … ″″
″″ Right shift … >> … ″″
″″ Signed right shift … >> … ″″
Relational Greater than … < … ″″
″″ Less than … > … ″″
″″ Greater than / equal to … >= … ″″
″″ Less than / equal to … <= … ″″
″″ Containment … in … ″″
″″ Instance-of … instanceof … ″″
Equality Abstract equality … == … ″″
″″ Abstract inequality … != … ″″
″″ Strict equality … === … ″″
″″ Strict inequality … !== … ″″
Bitwise AND … & … ″″
Bitwise XOR … ^ … ″″
Bitwise OR … | … ″″
Logical AND … ^^ … ″″
Logical OR … || … ″″
Conditional … ? … : … RTL ternary infix
Pipeline Pipelines … |> … LTR infix
Assignment Pipeline functions +> … Prefix
″″ Async pipeline functions async +> … Prefix
″″ Arrow functions … => … RTL infix
″″ Async arrow functions async … => … RTL infix
″″ Assignment … = … ″″
″″ … += … ″″
″″ … -= … ″″
″″ … *= … ″″
″″ … %= … ″″
″″ … **= … ″″
″″ … <<= … ″″
″″ … >>= … ″″
″″ … >>>= … ″″
″″ … &= … ″″
″″ … |= … ″″
Yield Yielding yield … Prefix
″″ Flat yielding yield * … ″″
″″ Spreading ...… ″″
Comma level Comma …, … LTR infix
Base statements Expression statements …; Postfix with ASI
″″ Empty statements ; Nullary with ASI
″″ Debugger statements debugger; ″″
″″ Block statements {…} Circumfix
″″ Labelled statements …: … Prefix
″″ Continue statements continue …; Circumfix with ASI
″″ Break statements break …; ″″
″″ Return statements return …; ″″
″″ Throw statements throw …; ″″
″″ Variable statements var …; ″″
″″ Lexical declarations let …; ″″
″″ ″″ const …; ″″
″″ Hoistable declarations function … (…) {…} Circumfix with prefix
″″ ″″ async function … (…) {…} ″″
″″ ″″ function * … (…) {…} ″″
″″ ″″ async function * … (…) {…} ″″
″″ Class declarations class … {…} ″″
Compound statements If statements if (…) … else … Circumfix with prefix
″″ Switch statements switch (…) … ″″
″″ Iteration statements ″″
″″ With statements with (…) {…} ″″
″″ Try statements try {…} catch (…) {…} finally {…} ″″
Statement list Case clause case: … Unchainable prefix
Root Script Root
″″ Module ″″