An Expression Statement That Is No Call Is Refused

Status: refused by design

o.x; is not FunctionalScript. o.x; is valid JavaScript, and fjs compile refuses it by design: the demo below shows what it prints.

A statement whose value is discarded and that is no call, such as o.x;, a + 1; or Number(x);, does nothing a later statement can see: an operator's result thrown away is almost always a mistake. FunctionalScript admits a call statement, which can assert, and refuses the rest. A statement opening with (, [ or a backtick is refused too, since it would continue the line before it (call statements).

The row st.expression of refused constructs registers the refusal, and call statements gives its reason.

Examples

/** @type {(o: { readonly x: number }) => number} */
const f = o => {
    o.x;
    return o.x + 1;
};
export default f({ x: 0 });

The demo on this page compiles sample.mjs, the module above, with this build's fjs compile, and shows the line it prints and the token it refuses. Below that it shows what JavaScript answers for the same module: 1.

The discarded o.x; expression in sample.mjs is intentional. A code-quality check correctly reports that it has no effect; removing it would remove the construct this negative example must show the compiler refusing.

What to Write Instead

Remove the statement, or bind the value with const and use it, as alternative.f.js does:

/** @type {(o: { readonly x: number }) => number} */
const f = o => {
    return o.x + 1;
};
export default f({ x: 0 });

It answers 1.

A Better Message

Today fjs compile prints unexpected token at the refused token. The demo proposes what it should print instead: the reason at the same token, what JavaScript does there, and the allowed spelling, the line alternative.f.js writes, as help. The page compiles the alternative too, so the suggestion is one the compiler accepts.

Reference

Demo

Not allowed in FunctionalScript

This is valid JavaScript, and fjs compile refuses it, by design: it is not a FunctionalScript module.

What fjs compile sample.mjs output.js prints:

sample.mjs:3:5 - error: unexpected token
3 |     o.x;
  |     ^

What it should print instead, pointing to what FunctionalScript allows (proposed):

sample.mjs:3:5 - error: this statement does nothing: FunctionalScript admits a call here, not a value thrown away
3 |     o.x;
  |     ^^^ JavaScript reads `o.x` here and discards it
  = help: remove the statement, or bind the value with `const` and use it:
              return o.x + 1;
  = note: refused by design, see spec/functions/call-statements/expression-statements/README.md

JavaScript source, sample.mjs:

/** @type {(o: { readonly x: number }) => number} */
const f = o => {
    o.x;
    return o.x + 1;
};
export default f({ x: 0 });

What JavaScript answers for the same module, its default export:

1

What to write instead

The FunctionalScript spelling, alternative.f.js:

/**
 * The FunctionalScript spelling of [`sample.mjs`](./sample.mjs): the function without the statement whose value nothing reads
 * ([`README.md`](./README.md)).
 *
 * @module
 */

/** @type {(o: { readonly x: number }) => number} */
const f = o => {
    return o.x + 1;
};
export default f({ x: 0 });

What fjs compile alternative.f.js output.js writes:

const $0=($1)=>$1.x+1;export default $0({"x":0});

What it answers, its default export:

1

Emergent Testing

Idle. Press Run to start the suite.

  • ./proof.f.mjs