Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 0447df1

Browse files
let spread at anywhere when creating a list
1 parent d64839e commit 0447df1

File tree

1 file changed

+42
-19
lines changed

1 file changed

+42
-19
lines changed

src/res_core.ml

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ module ErrorMessages = struct
8181
...b}` wouldn't make sense, as `b` would override every field of `a` \
8282
anyway."
8383

84-
let listExprSpread =
84+
let _listExprSpread =
8585
"Lists can only have one `...` spread, and at the end.\n\
8686
Explanation: lists are singly-linked list, where a node contains a value \
8787
and points to the next node. `list{a, ...bc}` efficiently creates a new \
@@ -3705,38 +3705,61 @@ and parseTupleExpr ~first ~startPos p =
37053705
let loc = mkLoc startPos p.prevEndPos in
37063706
Ast_helper.Exp.tuple ~loc exprs
37073707

3708-
and parseSpreadExprRegion p =
3708+
and parseSpreadExprRegionWithLoc p =
3709+
let startPos = p.Parser.prevEndPos in
37093710
match p.Parser.token with
37103711
| DotDotDot ->
37113712
Parser.next p;
37123713
let expr = parseConstrainedOrCoercedExpr p in
3713-
Some (true, expr)
3714+
Some (true, expr, startPos, p.prevEndPos)
37143715
| token when Grammar.isExprStart token ->
3715-
Some (false, parseConstrainedOrCoercedExpr p)
3716+
Some (false, parseConstrainedOrCoercedExpr p, startPos, p.prevEndPos)
37163717
| _ -> None
37173718

37183719
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
37273739
let listExprsRev =
37283740
parseCommaDelimitedReversedList p ~grammar:Grammar.ListExpr ~closing:Rbrace
3729-
~f:parseSpreadExprRegion
3741+
~f:parseSpreadExprRegionWithLoc
37303742
in
37313743
Parser.expect Rbrace p;
37323744
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
37373749
| 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 *)
37403763

37413764
(* Overparse ... and give a nice error message *)
37423765
and parseNonSpreadExp ~msg p =

0 commit comments

Comments
 (0)