@@ -166,6 +166,60 @@ let rec fits w doc = match doc with
166
166
| (_ind , _mode , CustomLayout _ )::rest ->
167
167
fits w rest
168
168
169
+ (* Version of fits that does not allocate *)
170
+ let fits0 w ops =
171
+ let wr = ref w in
172
+ let res = ref None in
173
+ let rec doOp ind mode doc = match (mode, doc) with
174
+ | _ when ! res <> None -> ()
175
+ | _ when ! wr < 0 -> res := Some false
176
+ | _ , Text txt -> wr := ! wr - (String. length txt)
177
+ | _ , Indent doc -> doOp (ind + 2 ) mode doc
178
+ | Flat , LineBreak break ->
179
+ if break = Hard || break = Literal then res := Some true
180
+ else wr := if break = Classic then ! wr - 1 else ! wr
181
+ | _ , Nil -> ()
182
+ | Break , LineBreak _break -> res := Some true
183
+ | _ , Group {shouldBreak = forceBreak ; doc} ->
184
+ let mode = if forceBreak then Break else mode in
185
+ doOp ind mode doc
186
+ | _ , IfBreaks {yes = breakDoc ; no = flatDoc } ->
187
+ if mode = Break then
188
+ doOp ind mode breakDoc
189
+ else
190
+ doOp ind mode flatDoc
191
+ | _ , Concat docs ->
192
+ doConcat ind mode docs
193
+ | _ , LineSuffix _ -> ()
194
+ | _ , BreakParent -> ()
195
+ | _ , CustomLayout (hd ::_ ) ->
196
+ (* TODO: if we have nested custom layouts, what we should do here? *)
197
+ doOp ind mode hd
198
+ | _ , CustomLayout [] ->
199
+ ()
200
+ and doConcat ind mode docs = match docs with
201
+ | _ when ! res <> None -> ()
202
+ | [] -> ()
203
+ | doc ::rest ->
204
+ doOp ind mode doc;
205
+ doConcat ind mode rest
206
+ in
207
+ let rec doOps ops = match ops with
208
+ | _ when ! res != None -> ()
209
+ | (ind , mode , doc )::rest ->
210
+ doOp ind mode doc;
211
+ doOps rest
212
+ | [] -> res := Some (! wr > = 0 )
213
+ in
214
+ doOps ops;
215
+ ! res = Some true
216
+
217
+
218
+ let _ = fits0
219
+ let _ = fits
220
+
221
+ let fits = fits0
222
+
169
223
let toString ~width doc =
170
224
let doc = propagateForcedBreaks doc in
171
225
let buffer = MiniBuffer. create 1000 in
0 commit comments