@@ -38,6 +38,10 @@ type id = loc(Identifier.t);
3838type str = loc (string );
3939type loc = Location . t ;
4040
41+ type array_concat_item =
42+ | ArrayConcatItems (list (expression ))
43+ | ArrayConcatSpread (expression );
44+
4145let ident_empty = {
4246 txt: Identifier . IdentName (Location . mknoloc("[]" )),
4347 loc: Location . dummy_loc,
@@ -433,41 +437,49 @@ module Expression = {
433437 tuple_construct(~loc, ~attributes? , ident_cons, [ expr, empty] )
434438 | ListSpread (expr , _ ) => expr
435439 };
436- if (List . exists(
437- expr =>
438- switch (expr) {
439- | ListSpread (_ ) => true
440- | ListItem (_ ) => false
441- },
442- rest,
443- )) {
444- collection_concat(
445- ~loc,
446- ~attributes? ,
447- PExpListConcat ,
448- List . map(
449- expr =>
440+ let has_nonfinal_spread =
441+ List . exists(
442+ expr =>
443+ switch (expr) {
444+ | ListSpread (_ ) => true
445+ | ListItem (_ ) => false
446+ },
447+ rest,
448+ );
449+ if (has_nonfinal_spread) {
450+ let grouped =
451+ List . fold_left(
452+ (acc, expr) => {
450453 switch (expr) {
451- | ListSpread (expr , loc ) => (
452- PExpSpreadExpr ,
454+ | ListSpread (expr , loc ) => [
453455 {... expr, pexp_loc: loc},
454- )
455- | ListItem (expr ) => (
456- PExpNonSpreadExpr ,
457- // Still convert to a single-element list to make later compilation steps easier
456+ ... acc,
457+ ]
458+ | ListItem (expr ) =>
459+ let (first , rest ) =
460+ switch (acc) {
461+ | [ first , ... rest ] => (first, rest)
462+ | _ => assert (false )
463+ };
464+ [
458465 tuple_construct(
459- ~loc= expr . pexp_loc ,
466+ ~loc,
460467 ~attributes? ,
461468 ident_cons,
462- [
463- expr,
464- tuple_construct(~loc= expr. pexp_loc, ident_empty, [] ),
465- ] ,
469+ [ expr, first] ,
466470 ),
467- )
468- },
469- a,
470- ),
471+ ... rest,
472+ ] ;
473+ }
474+ },
475+ [ base] ,
476+ rest,
477+ );
478+ collection_concat(
479+ ~loc,
480+ ~attributes? ,
481+ PExpListConcat ,
482+ List . map(expr => (PExpSpreadExpr , expr), grouped),
471483 );
472484 } else {
473485 List . fold_left(
@@ -489,51 +501,70 @@ module Expression = {
489501 {... list, pexp_loc: loc};
490502 };
491503 let array_items = (~loc, ~attributes=?, a) => {
492- let no_spreads =
493- List . for_all (
504+ let has_spread =
505+ List . exists (
494506 x => {
495507 switch (x) {
496- | ArrayItem (_ ) => true
497- | ArraySpread (_ ) => false
508+ | ArraySpread (_ ) => true
509+ | ArrayItem (_ ) => false
498510 }
499511 },
500512 a,
501513 );
502- if (no_spreads) {
503- array(
504- ~loc,
505- ~attributes? ,
506- List . map(
507- expr =>
514+ if (has_spread) {
515+ let grouped =
516+ List . fold_right(
517+ (expr, acc) => {
508518 switch (expr) {
509- | ArraySpread (_ ) =>
510- failwith (
511- "Impossible: spread in array when existence has been disproven" ,
512- )
513- | ArrayItem (expr ) => expr
514- },
519+ | ArrayItem (expr ) =>
520+ switch (acc) {
521+ | [ArrayConcatItems (exprs ), ... rest ] => [
522+ ArrayConcatItems ([ expr, ... exprs] ),
523+ ... rest,
524+ ]
525+ | _ => [ ArrayConcatItems ([ expr] ), ... acc]
526+ }
527+ | ArraySpread (expr , loc ) => [
528+ ArrayConcatSpread ({... expr, pexp_loc: loc}),
529+ ... acc,
530+ ]
531+ }
532+ },
515533 a,
516- ),
517- );
518- } else {
534+ [] ,
535+ );
519536 collection_concat(
520537 ~loc,
521538 ~attributes? ,
522539 PExpArrayConcat ,
523540 List . map(
524541 x => {
525542 switch (x) {
526- | ArrayItem ( expr ) => (
543+ | ArrayConcatItems ( [ first , ... rest ] as exprs ) => (
527544 PExpNonSpreadExpr ,
528- // Still convert to a single-element array to make later compilation steps easier
529- array(~loc= expr. pexp_loc, ~attributes? , [ expr] ),
530- )
531- | ArraySpread (expr , loc ) => (
532- PExpSpreadExpr ,
533- {... expr, pexp_loc: loc},
545+ array(~loc= first. pexp_loc, ~attributes? , exprs),
534546 )
547+ | ArrayConcatItems ([] ) =>
548+ failwith ("Impossible: empty ArrayConcatItems" )
549+ | ArrayConcatSpread (expr ) => (PExpSpreadExpr , expr)
535550 }
536551 },
552+ grouped,
553+ ),
554+ );
555+ } else {
556+ array(
557+ ~loc,
558+ ~attributes? ,
559+ List . map(
560+ expr =>
561+ switch (expr) {
562+ | ArraySpread (_ ) =>
563+ failwith (
564+ "Impossible: spread in array when existence has been disproven" ,
565+ )
566+ | ArrayItem (expr ) => expr
567+ },
537568 a,
538569 ),
539570 );
0 commit comments