Represent array and list literals with spreads with a Pexp_spread node
Why
The parser turned [a, ...b] and list{...a, b} into calls of Primitive_array.spread and Primitive_list.spread marked with res.spread, so the formatter had to rebuild the literal from the call and got it wrong: spreads of literals were flattened, attributes on the literal were dropped and an empty list spread printed as an empty element.
Pexp_spread keeps the items and spreads in source order, and the type checker gives it a Texp_spread node. Translation emits new Parray_spread and Plist_spread primitives that compile to the same runtime calls. A list literal whose only spread is its tail stays a chain of ::. The parsetree and CMT magic numbers are bumped.
modifiedAST array literal with a spread
let x = [1, ...ys]parse
Before
After
expressionexpression├─ Pexp_apply└─ expression ├─ attribute "res.spread" ├─ Pexp_ident "Primitive_array.spread" ├─ <arg> └─ Nolabel└─ Pexp_spread array ├─ Pspread_item └─ expression │ └─ expression └─ Pexp_array ├─ expression │ └─ Pexp_array │ └─ expression │ └─ Pexp_constant PConst_int (1,None) └─ expression └─ Pexp_ident "ys" │ └─ Pexp_constant PConst_int (1,None) └─ Pspread └─ expression └─ Pexp_ident "ys"
addedTypedtree Texp_spread
let ys = [2]let x = [1, ...ys]
typed
expression└─ Texp_spread array ├─ expression │ └─ Texp_array │ └─ expression │ └─ Texp_constant Const_int 1 └─ expression └─ Texp_ident "ys/1001"
modifiedFormat literals with spreads
let x = [...[1, 2], 3, ...[]]let y = @attr list{...xs, ...list{}, 1}
rescript
Before
After
let x = [1, 2, 3, ]let y = list{...xs, , 1}let x = [...[1, 2], 3, ...[]]let y = @attr list{...xs, ...list{}, 1}
Review
- Why do the generated item groups have ghost locations? The v0 encoding has no marker on them, and the ghost flag tells a group of items from an array or list literal that is spread. A call built by a PPX with real locations decodes to spreads only, which concatenates the same values.
- Why does the typed node hold the concatenated parts rather than the elements? The parts are the arrays and cons chains the runtime call takes, so the items keep the errors of array and list literals and translation needs no list building of its own.