@@ -133,91 +133,51 @@ let join ~sep docs =
133
133
in
134
134
concat(loop [] sep docs)
135
135
136
+ let fits w stack =
137
+ let width = ref w in
138
+ let result = ref None in
136
139
137
- let rec fits w doc = match doc with
138
- | _ when w < 0 -> false
139
- | [] -> true
140
- | (_ind , _mode , Text txt )::rest -> fits (w - String. length txt) rest
141
- | (ind , mode , Indent doc )::rest -> fits w ((ind + 2 , mode, doc)::rest)
142
- | (_ind , Flat, LineBreak break )::rest ->
143
- if break = Hard || break = Literal then true
144
- else
145
- let w = if break = Classic then w - 1 else w in
146
- fits w rest
147
- | (_ind , _mode , Nil)::rest -> fits w rest
148
- | (_ind , Break, LineBreak _break )::_rest -> true
149
- | (ind , mode , Group {shouldBreak = forceBreak ; doc} )::rest ->
150
- let mode = if forceBreak then Break else mode in
151
- fits w ((ind, mode, doc)::rest)
152
- | (ind , mode , IfBreaks {yes = breakDoc ; no = flatDoc } )::rest ->
153
- if mode = Break then
154
- fits w ((ind, mode, breakDoc)::rest)
155
- else
156
- fits w ((ind, mode, flatDoc)::rest)
157
- | (ind , mode , Concat docs )::rest ->
158
- let ops = List. map (fun doc -> (ind, mode, doc)) docs in
159
- fits w (List. append ops rest)
160
- (* | (_ind, _mode, Cursor)::rest -> fits w rest *)
161
- | (_ind , _mode , LineSuffix _ )::rest -> fits w rest
162
- | (_ind , _mode , BreakParent)::rest -> fits w rest
163
- | (ind , mode , CustomLayout (hd ::_ ))::rest ->
164
- (* TODO: if we have nested custom layouts, what we should do here? *)
165
- fits w ((ind, mode, hd)::rest)
166
- | (_ind , _mode , CustomLayout _ )::rest ->
167
- fits w rest
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 _ -> ()
140
+ let rec calculate indent mode doc =
141
+ match mode, doc with
142
+ | _ when result.contents != None -> ()
143
+ | _ when width.contents < 0 -> result := Some false
144
+ | _, Nil
145
+ | _, LineSuffix _
194
146
| _ , BreakParent -> ()
147
+ | _ , Text txt -> width := width.contents - (String. length txt)
148
+ | _ , Indent doc -> calculate (indent + 2 ) mode doc
149
+ | Flat , LineBreak Hard
150
+ | Flat , LineBreak Literal -> result := Some true
151
+ | Flat , LineBreak Classic -> width := width.contents - 1
152
+ | Flat , LineBreak Soft -> ()
153
+ | Break , LineBreak _ -> result := Some true
154
+ | _ , Group {shouldBreak = true ; doc} -> calculate indent Break doc
155
+ | _ , Group {doc} -> calculate indent mode doc
156
+ | Break , IfBreaks {yes = breakDoc } -> calculate indent mode breakDoc
157
+ | Flat , IfBreaks {no = flatDoc } -> calculate indent mode flatDoc
158
+ | _ , Concat docs -> calculateConcat indent mode docs
195
159
| _ , CustomLayout (hd ::_ ) ->
196
160
(* 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
161
+ calculate indent mode hd
162
+ | _ , CustomLayout [] -> ()
163
+ and calculateConcat indent mode docs =
164
+ if result.contents == None then (
165
+ match docs with
166
+ | [] -> ()
167
+ | doc ::rest ->
168
+ calculate indent mode doc;
169
+ calculateConcat indent mode rest
170
+ )
206
171
in
207
- let rec doOps ops = match ops with
208
- | _ when ! res != None -> ! res = Some true
209
- | (ind , mode , doc )::rest ->
210
- doOp ind mode doc;
211
- doOps rest
212
- | [] -> ! wr > = 0
172
+ let rec calculateAll stack =
173
+ match result.contents, stack with
174
+ | Some r , _ -> r
175
+ | None , [] -> ! width > = 0
176
+ | None , (indent , mode , doc )::rest ->
177
+ calculate indent mode doc;
178
+ calculateAll rest
213
179
in
214
- doOps ops
215
-
216
-
217
- let _ = fits0
218
- let _ = fits
219
-
220
- let fits = fits0
180
+ calculateAll stack
221
181
222
182
let toString ~width doc =
223
183
let doc = propagateForcedBreaks doc in
@@ -293,7 +253,7 @@ let toString ~width doc =
293
253
process ~pos: 0 [] (List. rev suffices)
294
254
end
295
255
in
296
- process ~pos: 0 [] [0 , Flat , doc];
256
+ process ~pos: 0 [] [( 0 , Flat , doc) ];
297
257
MiniBuffer. contents buffer
298
258
299
259
0 commit comments