@@ -81,7 +81,7 @@ module ErrorMessages = struct
81
81
...b}` wouldn't make sense, as `b` would override every field of `a` \
82
82
anyway."
83
83
84
- let listExprSpread =
84
+ let _listExprSpread =
85
85
" Lists can only have one `...` spread, and at the end.\n \
86
86
Explanation: lists are singly-linked list, where a node contains a value \
87
87
and points to the next node. `list{a, ...bc}` efficiently creates a new \
@@ -3705,38 +3705,61 @@ and parseTupleExpr ~first ~startPos p =
3705
3705
let loc = mkLoc startPos p.prevEndPos in
3706
3706
Ast_helper.Exp. tuple ~loc exprs
3707
3707
3708
- and parseSpreadExprRegion p =
3708
+ and parseSpreadExprRegionWithLoc p =
3709
+ let startPos = p.Parser. prevEndPos in
3709
3710
match p.Parser. token with
3710
3711
| DotDotDot ->
3711
3712
Parser. next p;
3712
3713
let expr = parseConstrainedOrCoercedExpr p in
3713
- Some (true , expr)
3714
+ Some (true , expr, startPos, p.prevEndPos )
3714
3715
| token when Grammar. isExprStart token ->
3715
- Some (false , parseConstrainedOrCoercedExpr p)
3716
+ Some (false , parseConstrainedOrCoercedExpr p, startPos, p.prevEndPos )
3716
3717
| _ -> None
3717
3718
3718
3719
and parseListExpr ~startPos p =
3719
- let check_all_non_spread_exp exprs =
3720
- exprs
3721
- |> List. map (fun (spread , expr ) ->
3722
- if spread then
3723
- Parser. err p (Diagnostics. message ErrorMessages. listExprSpread);
3724
- expr)
3725
- |> List. rev
3726
- in
3720
+ let split_by_spread exprs =
3721
+ let rec loop exprs acc =
3722
+ match exprs, acc with
3723
+ | [] , acc -> acc
3724
+ | (true , expr , startPos , endPos ) :: exprs , _ ->
3725
+ (* find a spread expression, prepend a new sublist *)
3726
+ loop exprs (([] , Some expr, startPos, endPos) :: acc)
3727
+ | (false , expr , startPos , _endPos ) :: exprs , ((no_spreads , spread , _accStartPos , accEndPos ) :: acc ) ->
3728
+ (* find a non-spread expression, and the accumulated is not empty,
3729
+ * prepend to the first sublist, and update the loc first sublist *)
3730
+ loop exprs ((expr :: no_spreads, spread, startPos, accEndPos) :: acc)
3731
+ | (false , expr , startPos , endPos ) :: exprs , [] ->
3732
+ (* find a non-spread expression, and the accumulated is empty *)
3733
+ loop exprs [[expr] , None , startPos, endPos] in
3734
+ loop exprs [] in
3735
+ let make_sub_expr = function
3736
+ | exprs , Some spread , startPos , endPos ->
3737
+ makeListExpression (mkLoc startPos endPos) exprs (Some spread)
3738
+ | exprs , None , startPos , endPos -> makeListExpression (mkLoc startPos endPos) exprs None in
3727
3739
let listExprsRev =
3728
3740
parseCommaDelimitedReversedList p ~grammar: Grammar. ListExpr ~closing: Rbrace
3729
- ~f: parseSpreadExprRegion
3741
+ ~f: parseSpreadExprRegionWithLoc
3730
3742
in
3731
3743
Parser. expect Rbrace p;
3732
3744
let loc = mkLoc startPos p.prevEndPos in
3733
- match listExprsRev with
3734
- | ( true (* spread expression *) , expr ) :: exprs ->
3735
- let exprs = check_all_non_spread_exp exprs in
3736
- makeListExpression loc exprs ( Some expr)
3745
+ match split_by_spread listExprsRev with
3746
+ | [] -> makeListExpression loc [] None
3747
+ | [exprs, Some spread, _, _] -> makeListExpression loc exprs ( Some spread)
3748
+ | [exprs, None , _, _] -> makeListExpression loc exprs None
3737
3749
| exprs ->
3738
- let exprs = check_all_non_spread_exp exprs in
3739
- makeListExpression loc exprs None
3750
+ let listExprs = List. map
3751
+ make_sub_expr
3752
+ exprs in
3753
+ Ast_helper.Exp. (apply ~loc
3754
+ (Ast_helper.Exp. ident ~loc
3755
+ (Location. mkloc (Longident. (Ldot (Ldot (Lident " Belt" , " List" ), " concatMany" ))) loc))
3756
+ [Asttypes. Nolabel , makeListExpression loc listExprs None ])
3757
+ (* | (true (\* spread expression *\), expr, _) :: exprs ->
3758
+ * let exprs = check_all_non_spread_exp exprs in
3759
+ * makeListExpression loc exprs (Some expr)
3760
+ * | exprs ->
3761
+ * let exprs = check_all_non_spread_exp exprs in
3762
+ * makeListExpression loc exprs None *)
3740
3763
3741
3764
(* Overparse ... and give a nice error message *)
3742
3765
and parseNonSpreadExp ~msg p =
0 commit comments