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

Commit e28e31c

Browse files
committed
Callbacks without exponential explosion.
Follows #576
1 parent 75124cc commit e28e31c

15 files changed

+195
-209
lines changed

src/res_doc.ml

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type t =
2121
| LineSuffix of t
2222
| LineBreak of lineStyle
2323
| Group of {mutable shouldBreak: bool; doc: t}
24-
| CustomLayout of t list
24+
| CustomLayout of t lazy_t list
2525
| BreakParent
2626

2727
let nil = Nil
@@ -50,7 +50,7 @@ let ifBreaks t f = IfBreaks {yes = t; no = f; broken = false}
5050
let lineSuffix d = LineSuffix d
5151
let group d = Group {shouldBreak = false; doc = d}
5252
let breakableGroup ~forceBreak d = Group {shouldBreak = forceBreak; doc = d}
53-
let customLayout gs = CustomLayout gs
53+
let customLayout lazyDocs = CustomLayout lazyDocs
5454
let breakParent = BreakParent
5555

5656
let space = Text " "
@@ -102,13 +102,8 @@ let propagateForcedBreaks doc =
102102
let childForcesBreak = walk child in
103103
forceBreak || childForcesBreak)
104104
false children
105-
| CustomLayout children ->
106-
(* When using CustomLayout, we don't want to propagate forced breaks
107-
* from the children up. By definition it picks the first layout that fits
108-
* otherwise it takes the last of the list.
109-
* However we do want to propagate forced breaks in the sublayouts. They
110-
* might need to be broken. We just don't propagate them any higher here *)
111-
let _ = walk (Concat children) in
105+
| CustomLayout _ ->
106+
(* TODO: this should be done lazily *)
112107
false
113108
in
114109
let _ = walk doc in
@@ -119,7 +114,8 @@ let rec willBreak doc =
119114
match doc with
120115
| LineBreak (Hard | Literal) | BreakParent | Group {shouldBreak = true} ->
121116
true
122-
| Group {doc} | Indent doc | CustomLayout (doc :: _) -> willBreak doc
117+
| Group {doc} | Indent doc -> willBreak doc
118+
| CustomLayout (_lazyDoc :: _) -> false (* willBreak (Lazy.force lazyDoc) *)
123119
| Concat docs -> List.exists willBreak docs
124120
| IfBreaks {yes; no} -> willBreak yes || willBreak no
125121
| _ -> false
@@ -155,10 +151,7 @@ let fits w stack =
155151
| Break, IfBreaks {yes = breakDoc} -> calculate indent mode breakDoc
156152
| Flat, IfBreaks {no = flatDoc} -> calculate indent mode flatDoc
157153
| _, Concat docs -> calculateConcat indent mode docs
158-
| _, CustomLayout (hd :: _) ->
159-
(* TODO: if we have nested custom layouts, what we should do here? *)
160-
calculate indent mode hd
161-
| _, CustomLayout [] -> ()
154+
| _, CustomLayout _ -> ()
162155
and calculateConcat indent mode docs =
163156
if result.contents == None then
164157
match docs with
@@ -234,17 +227,18 @@ let toString ~width doc =
234227
if shouldBreak || not (fits (width - pos) ((ind, Flat, doc) :: rest))
235228
then process ~pos lineSuffices ((ind, Break, doc) :: rest)
236229
else process ~pos lineSuffices ((ind, Flat, doc) :: rest)
237-
| CustomLayout docs ->
238-
let rec findGroupThatFits groups =
239-
match groups with
240-
| [] -> Nil
241-
| [lastGroup] -> lastGroup
242-
| doc :: docs ->
243-
if fits (width - pos) ((ind, Flat, doc) :: rest) then doc
244-
else findGroupThatFits docs
230+
| CustomLayout lazyDocs ->
231+
let rec findGroupThatFits lazyDocs =
232+
match lazyDocs with
233+
| [] -> lazy Nil
234+
| [lazyDoc] -> lazyDoc
235+
| lazyDoc :: lazyDocs ->
236+
if fits (width - pos) ((ind, Flat, Lazy.force lazyDoc) :: rest) then
237+
lazyDoc
238+
else findGroupThatFits lazyDocs
245239
in
246-
let doc = findGroupThatFits docs in
247-
process ~pos lineSuffices ((ind, Flat, doc) :: rest))
240+
let lazyDoc = findGroupThatFits lazyDocs in
241+
process ~pos lineSuffices ((ind, Flat, Lazy.force lazyDoc) :: rest))
248242
| [] -> (
249243
match lineSuffices with
250244
| [] -> ()
@@ -282,7 +276,7 @@ let debug t =
282276
line;
283277
text ")";
284278
])
285-
| CustomLayout docs ->
279+
| CustomLayout lazyDocs ->
286280
group
287281
(concat
288282
[
@@ -291,7 +285,9 @@ let debug t =
291285
(concat
292286
[
293287
line;
294-
join ~sep:(concat [text ","; line]) (List.map toDoc docs);
288+
join
289+
~sep:(concat [text ","; line])
290+
(List.map (fun ld -> toDoc (Lazy.force ld)) lazyDocs);
295291
]);
296292
line;
297293
text ")";

src/res_doc.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ val breakableGroup : forceBreak:bool -> t -> t
1616
(* `customLayout docs` will pick the layout that fits from `docs`.
1717
* This is a very expensive computation as every layout from the list
1818
* will be checked until one fits. *)
19-
val customLayout : t list -> t
19+
val customLayout : t lazy_t list -> t
2020
val breakParent : t
2121
val join : sep:t -> t list -> t
2222

src/res_printer.ml

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,20 +1905,27 @@ and printValueBinding ~recFlag vb cmtTbl i =
19051905
if ParsetreeViewer.isSinglePipeExpr vb.pvb_expr then
19061906
Doc.customLayout
19071907
[
1908-
Doc.group
1909-
(Doc.concat
1910-
[
1911-
attrs; header; patternDoc; Doc.text " ="; Doc.space; printedExpr;
1912-
]);
1913-
Doc.group
1914-
(Doc.concat
1915-
[
1916-
attrs;
1917-
header;
1918-
patternDoc;
1919-
Doc.text " =";
1920-
Doc.indent (Doc.concat [Doc.line; printedExpr]);
1921-
]);
1908+
lazy
1909+
(Doc.group
1910+
(Doc.concat
1911+
[
1912+
attrs;
1913+
header;
1914+
patternDoc;
1915+
Doc.text " =";
1916+
Doc.space;
1917+
printedExpr;
1918+
]));
1919+
lazy
1920+
(Doc.group
1921+
(Doc.concat
1922+
[
1923+
attrs;
1924+
header;
1925+
patternDoc;
1926+
Doc.text " =";
1927+
Doc.indent (Doc.concat [Doc.line; printedExpr]);
1928+
]));
19221929
]
19231930
else
19241931
let shouldIndent =
@@ -3977,15 +3984,16 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl =
39773984
* }, longArgumet, veryLooooongArgument)
39783985
*)
39793986
let fitsOnOneLine =
3980-
Doc.concat
3981-
[
3982-
(if uncurried then Doc.text "(. " else Doc.lparen);
3983-
callback;
3984-
Doc.comma;
3985-
Doc.line;
3986-
printedArgs;
3987-
Doc.rparen;
3988-
]
3987+
lazy
3988+
(Doc.concat
3989+
[
3990+
(if uncurried then Doc.text "(. " else Doc.lparen);
3991+
callback;
3992+
Doc.comma;
3993+
Doc.line;
3994+
printedArgs;
3995+
Doc.rparen;
3996+
])
39893997
in
39903998

39913999
(* Thing.map(
@@ -3995,7 +4003,7 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl =
39954003
* arg3,
39964004
* )
39974005
*)
3998-
let breakAllArgs = printArguments ~uncurried args cmtTblCopy in
4006+
let breakAllArgs = lazy (printArguments ~uncurried args cmtTblCopy) in
39994007

40004008
(* Sometimes one of the non-callback arguments will break.
40014009
* There might be a single line comment in there, or a multiline string etc.
@@ -4012,7 +4020,7 @@ and printArgumentsWithCallbackInFirstPosition ~uncurried args cmtTbl =
40124020
* In this case, we always want the arguments broken over multiple lines,
40134021
* like a normal function call.
40144022
*)
4015-
if Doc.willBreak printedArgs then breakAllArgs
4023+
if Doc.willBreak printedArgs then Lazy.force breakAllArgs
40164024
else Doc.customLayout [fitsOnOneLine; breakAllArgs]
40174025

40184026
and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
@@ -4023,7 +4031,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
40234031
let cmtTblCopy2 = CommentTable.copy cmtTbl in
40244032
let rec loop acc args =
40254033
match args with
4026-
| [] -> (Doc.nil, Doc.nil, Doc.nil)
4034+
| [] -> (lazy Doc.nil, lazy Doc.nil, lazy Doc.nil)
40274035
| [(lbl, expr)] ->
40284036
let lblDoc =
40294037
match lbl with
@@ -4034,18 +4042,22 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
40344042
Doc.concat [Doc.tilde; printIdentLike txt; Doc.equal; Doc.question]
40354043
in
40364044
let callbackFitsOnOneLine =
4037-
let pexpFunDoc = printPexpFun ~inCallback:FitsOnOneLine expr cmtTbl in
4038-
let doc = Doc.concat [lblDoc; pexpFunDoc] in
4039-
printComments doc cmtTbl expr.pexp_loc
4045+
lazy
4046+
(let pexpFunDoc =
4047+
printPexpFun ~inCallback:FitsOnOneLine expr cmtTbl
4048+
in
4049+
let doc = Doc.concat [lblDoc; pexpFunDoc] in
4050+
printComments doc cmtTbl expr.pexp_loc)
40404051
in
40414052
let callbackArgumentsFitsOnOneLine =
4042-
let pexpFunDoc =
4043-
printPexpFun ~inCallback:ArgumentsFitOnOneLine expr cmtTblCopy
4044-
in
4045-
let doc = Doc.concat [lblDoc; pexpFunDoc] in
4046-
printComments doc cmtTblCopy expr.pexp_loc
4053+
lazy
4054+
(let pexpFunDoc =
4055+
printPexpFun ~inCallback:ArgumentsFitOnOneLine expr cmtTblCopy
4056+
in
4057+
let doc = Doc.concat [lblDoc; pexpFunDoc] in
4058+
printComments doc cmtTblCopy expr.pexp_loc)
40474059
in
4048-
( Doc.concat (List.rev acc),
4060+
( lazy (Doc.concat (List.rev acc)),
40494061
callbackFitsOnOneLine,
40504062
callbackArgumentsFitsOnOneLine )
40514063
| arg :: args ->
@@ -4056,27 +4068,29 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
40564068

40574069
(* Thing.map(foo, (arg1, arg2) => MyModuleBlah.toList(argument)) *)
40584070
let fitsOnOneLine =
4059-
Doc.concat
4060-
[
4061-
(if uncurried then Doc.text "(." else Doc.lparen);
4062-
printedArgs;
4063-
callback;
4064-
Doc.rparen;
4065-
]
4071+
lazy
4072+
(Doc.concat
4073+
[
4074+
(if uncurried then Doc.text "(." else Doc.lparen);
4075+
Lazy.force printedArgs;
4076+
Lazy.force callback;
4077+
Doc.rparen;
4078+
])
40664079
in
40674080

40684081
(* Thing.map(longArgumet, veryLooooongArgument, (arg1, arg2) =>
40694082
* MyModuleBlah.toList(argument)
40704083
* )
40714084
*)
40724085
let arugmentsFitOnOneLine =
4073-
Doc.concat
4074-
[
4075-
(if uncurried then Doc.text "(." else Doc.lparen);
4076-
printedArgs;
4077-
Doc.breakableGroup ~forceBreak:true callback2;
4078-
Doc.rparen;
4079-
]
4086+
lazy
4087+
(Doc.concat
4088+
[
4089+
(if uncurried then Doc.text "(." else Doc.lparen);
4090+
Lazy.force printedArgs;
4091+
Doc.breakableGroup ~forceBreak:true (Lazy.force callback2);
4092+
Doc.rparen;
4093+
])
40804094
in
40814095

40824096
(* Thing.map(
@@ -4086,7 +4100,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
40864100
* (param1, parm2) => doStuff(param1, parm2)
40874101
* )
40884102
*)
4089-
let breakAllArgs = printArguments ~uncurried args cmtTblCopy2 in
4103+
let breakAllArgs = lazy (printArguments ~uncurried args cmtTblCopy2) in
40904104

40914105
(* Sometimes one of the non-callback arguments will break.
40924106
* There might be a single line comment in there, or a multiline string etc.
@@ -4103,7 +4117,7 @@ and printArgumentsWithCallbackInLastPosition ~uncurried args cmtTbl =
41034117
* In this case, we always want the arguments broken over multiple lines,
41044118
* like a normal function call.
41054119
*)
4106-
if Doc.willBreak printedArgs then breakAllArgs
4120+
if Doc.willBreak (Lazy.force printedArgs) then Lazy.force breakAllArgs
41074121
else Doc.customLayout [fitsOnOneLine; arugmentsFitOnOneLine; breakAllArgs]
41084122

41094123
and printArguments ~uncurried

tests/conversion/reason/expected/bracedJsx.res.txt

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -50,55 +50,45 @@ module Styles = {
5050
let make = () => {
5151
let containerRef = React.useRef(Js.Nullable.null)
5252

53-
let (state, send) = React.useReducer((state, action) =>
54-
switch action {
53+
let (state, send) = React.useReducer((state, action) => switch action {
5554
| RunCommand => {
5655
input: "",
5756
history: Array.concat(
5857
state.history,
59-
[
60-
User(state.input),
61-
switch state.input->Js.String.trim {
58+
[User(state.input), switch state.input->Js.String.trim {
6259
| "" => System("")
63-
| "help" =>
64-
System(`available commands:
60+
| "help" => System(`available commands:
6561
- help
6662
- ls
6763
- cat `)
68-
| "ls" =>
69-
System(`- hack-website.sh
64+
| "ls" => System(`- hack-website.sh
7065
- go-to-home.sh
7166
- nuclear-codes.txt`)
7267
| "cat" => System("cat: missing argument")
7368
| "cat hack-website.sh"
74-
| "cat ./hack-website.sh" =>
75-
System("# seriously?\necho \"lol\"")
69+
| "cat ./hack-website.sh" => System("# seriously?\necho \"lol\"")
7670
| "hack-website.sh"
77-
| "./hack-website.sh" =>
78-
System("lol")
71+
| "./hack-website.sh" => System("lol")
7972
| "cat nuclear-codes.txt"
80-
| "cat ./nuclear-codes.txt" =>
81-
System("000000")
73+
| "cat ./nuclear-codes.txt" => System("000000")
8274
| "go-to-home.sh"
83-
| "./go-to-home.sh" =>
84-
Js.Global.setTimeout(() => ReasonReact.Router.push("/"), 1_000)->ignore
75+
| "./go-to-home.sh" => Js.Global.setTimeout(
76+
() => ReasonReact.Router.push("/"),
77+
1_000,
78+
)->ignore
8579
System("Redirecting ...")
8680
| "cat go-to-home.sh"
87-
| "cat ./go-to-home.sh" =>
88-
System("ReasonReact.Router.push(\"/\")")
81+
| "cat ./go-to-home.sh" => System("ReasonReact.Router.push(\"/\")")
8982
| _ => System("command not found: " ++ (state.input ++ "\ntry command 'help'"))
90-
},
91-
],
83+
}],
9284
),
9385
}
9486
| SetValue(input) => {...state, input}
95-
}
96-
, {history: [], input: ""})
87+
}, {history: [], input: ""})
9788

9889
React.useEffect1(() => {
9990
switch containerRef.current->Js.Nullable.toOption {
100-
| Some(containerRef) =>
101-
open Webapi.Dom
91+
| Some(containerRef) => open Webapi.Dom
10292
containerRef->Element.setScrollTop(containerRef->Element.scrollHeight->float_of_int)
10393
| None => ()
10494
}
@@ -112,18 +102,12 @@ let make = () => {
112102
className=Styles.terminal
113103
onClick={event => (event->ReactEvent.Mouse.target)["querySelector"]("input")["focus"]()}
114104
ref={containerRef->ReactDOMRe.Ref.domRef}>
115-
{state.history
116-
->Array.mapWithIndex((index, item) =>
117-
<div key={j`$index`} className=Styles.line>
118-
{ReasonReact.string(
119-
switch item {
105+
{state.history->Array.mapWithIndex((index, item) =>
106+
<div key={j`$index`} className=Styles.line> {ReasonReact.string(switch item {
120107
| User(value) => userPrefix ++ value
121108
| System(value) => value
122-
},
123-
)}
124-
</div>
125-
)
126-
->ReasonReact.array}
109+
})} </div>
110+
)->ReasonReact.array}
127111
<div>
128112
{userPrefix->ReasonReact.string}
129113
{<input

0 commit comments

Comments
 (0)