From bf03554f31e046ae557f1b3f831c9f7658189860 Mon Sep 17 00:00:00 2001 From: trdthg Date: Thu, 25 Jul 2024 03:44:03 +0000 Subject: [PATCH] Fmt: update check_nowrap for nested chunks --- src/lib/format_sail.ml | 135 +++++++++++-------- test/format/default/wrap_into_oneline.expect | 32 ++++- test/format/wrap_into_oneline.sail | 2 +- 3 files changed, 102 insertions(+), 67 deletions(-) diff --git a/src/lib/format_sail.ml b/src/lib/format_sail.ml index 602ef61b8..fa594c50a 100644 --- a/src/lib/format_sail.ml +++ b/src/lib/format_sail.ml @@ -81,9 +81,9 @@ let is_comment chunk = match chunk with Comment (_, _, _, _, _) | Doc_comment _ let is_block chunk = match chunk with Block (_, _) -> true | _ -> false let is_match chunk = match chunk with Match _ -> true | _ -> false let is_let chunk = match chunk with Binder (_, _, _, _) -> true | _ -> false -let is_delta chunk = match chunk with Delim _ | Opt_delim _ -> true | _ -> false +let is_delim chunk = match chunk with Delim _ | Opt_delim _ -> true | _ -> false -let rec count_chunks_by_rule ?(ignore_rule = is_delta) chunks target_rule = +let rec count_chunks_by_rule ?(ignore_rule = is_delim) chunks target_rule = let rec go chunks target_count other_count = match chunks with | [] -> (target_count, other_count) @@ -463,63 +463,79 @@ module type CONFIG = sig val config : config end -type chunk_wrap_opt = { nest : int; in_braces : bool } -let nest_add opt = { opt with nest = opt.nest + 1 } +type chunk_wrap_opt_state = { non_delim_count : int; non_wrap_count : int } +type chunk_wrap_opt = { strict : bool; app_nest : int; in_braces : bool; state : chunk_wrap_opt_state } +let app_nest_add opt = { opt with app_nest = opt.app_nest + 1 } +let check_nowrap_strict opt = { opt with strict = true } let in_braces opt = { opt with in_braces = true } +let default_opt = + { strict = false; app_nest = 0; in_braces = false; state = { non_delim_count = 0; non_wrap_count = 0 } } -let rec can_chunks_list_wrap ?(opt = { nest = 0; in_braces = false }) cqs = +let rec check_chunks_nowrap ?(opt = default_opt) cqs = match cqs with | [] -> true - | [cq] -> ( - let count = ref 0 in - match List.of_seq (Queue.to_seq cq) with - | [] -> true - | [c] -> - (* if deep > 0, then not wrap - * i.e. - * - foo(a, bar(a, b)) - *) - let can_wrap_nested = - match c with - | Atom _ | String_literal _ | Delim _ | Opt_delim _ -> true - | Block (_, cqs) -> can_chunks_list_wrap ~opt cqs - | Field (cq, id) -> can_chunks_list_wrap ~opt [cq] - | _ -> false - in - if not can_wrap_nested then count := !count + 1; - if opt.nest > 0 && !count > 1 && not can_wrap_nested then false - else ( - match c with - (* Atom *) - | Atom _ | String_literal _ -> true - (* unit => (), *) - | Delim _ | Opt_delim _ -> true (* Xs[unsigned(r)], *) - | App (id, cqs) -> can_chunks_list_wrap ~opt:(opt |> nest_add) cqs - (* zero_extend(fcsr.bits) *) - | Field (cq, id) -> can_chunks_list_wrap ~opt [cq] - (* (v128 >> shift)[64..0] *) - | Binary (x, op, y) -> can_chunks_list_wrap ~opt [x] && can_chunks_list_wrap ~opt [y] - (* if regval[31..16] then *) - | Index (cq, ix) -> can_chunks_list_wrap ~opt:(opt |> in_braces) [cq] && can_chunks_list_wrap ~opt [ix] - (* if (a > 1) then {1} else {2} *) - | If_then_else (_, i, t, e) -> - can_chunks_list_wrap ~opt [i] && can_chunks_list_wrap ~opt [t] && can_chunks_list_wrap ~opt [e] - (* {{{ Atom }}} *) - | Block (_, cqs) -> can_chunks_list_wrap ~opt:(opt |> in_braces) cqs - (* case => (), // comment *) - (* then 2 // comment *) - | Comment (_, _, _, _, trailing) -> (not opt.in_braces) && trailing - | _ -> false + | [cq] -> + let nest_nowrap_count = ref 0 in + let non_delim_count = ref 0 in + let len = Queue.length cq in + let res, _ = + Queue.fold + (fun (acc, index) c -> + let res = + if (* unit => (), *) + is_delim c then true + else ( + non_delim_count := !non_delim_count + 1; + (* strict rule, for nested chunks *) + let check_chunk_nowrap_strict = + match c with + | Atom _ | String_literal _ -> true + | Field (cq, id) -> check_chunks_nowrap ~opt [cq] + | Block (_, cqs) -> check_chunks_nowrap ~opt cqs + | Index (cq, ix) -> check_chunks_nowrap ~opt:(opt |> in_braces) [cq] && check_chunks_nowrap ~opt [ix] + | App (id, cqs) -> List.length cqs = 1 && check_chunks_nowrap ~opt:(opt |> app_nest_add) cqs + | _ -> false + in + if opt.strict then check_chunk_nowrap_strict + else ( + if check_chunk_nowrap_strict then nest_nowrap_count := !nest_nowrap_count + 1; + (* normal rule *) + match c with + (* Atom *) + | Atom _ | String_literal _ -> true + (* Xs[unsigned(r)], *) + | App (id, cqs) -> check_chunks_nowrap ~opt:(opt |> app_nest_add) cqs + (* zero_extend(fcsr.bits) *) + | Field (cq, id) -> check_chunks_nowrap ~opt [cq] + (* (v128 >> shift)[64..0] *) + | Binary (x, op, y) -> check_chunks_nowrap ~opt [x] && check_chunks_nowrap ~opt [y] + (* if regval[31..16] then *) + | Index (cq, ix) -> check_chunks_nowrap ~opt:(opt |> in_braces) [cq] && check_chunks_nowrap ~opt [ix] + (* if (a > 1) then {1} else {2} *) + | If_then_else (_, i, t, e) -> + check_chunks_nowrap ~opt [i] && check_chunks_nowrap ~opt [t] && check_chunks_nowrap ~opt [e] + (* {{{ Atom }}} *) + | Block (_, cqs) -> check_chunks_nowrap ~opt:(opt |> in_braces) cqs + | Comment _ -> + if not (index = len - 1) then false + else ( + match c with + (* case => (), // comment *) + (* then 2 // comment *) + | Comment (Comment_line, _, _, _, true) -> not opt.in_braces + | Comment (Comment_block, _, _, _, _) -> not opt.in_braces + | _ -> false + ) + | _ -> false + ) + ) + in + (acc && res, index + 1) ) - | c :: cq -> ( - match c with - | Comment (_, _, _, _, _) -> false - | _ -> - can_chunks_list_wrap ~opt [Queue.of_seq (List.to_seq [c])] - && can_chunks_list_wrap ~opt [Queue.of_seq (List.to_seq cq)] - ) - ) - | cq :: cqs -> can_chunks_list_wrap ~opt [cq] && can_chunks_list_wrap ~opt cqs + (true, 0) cq + in + res + | cq :: cqs -> check_chunks_nowrap ~opt [cq] && check_chunks_nowrap ~opt cqs module Make (Config : CONFIG) = struct let indent = Config.config.indent @@ -589,8 +605,9 @@ module Make (Config : CONFIG) = struct | If_then_else (bracing, i, t, e) -> let insert_braces = opts.statement || bracing.then_brace || bracing.else_brace in let i_doc, i_wrap = doc_chunks_exps (opts |> nonatomic |> expression_like) i in - let t_wrap = can_chunks_list_wrap [t] in - let e_wrap = can_chunks_list_wrap [e] in + (* check_nowrap with strict mode here *) + let t_wrap = check_chunks_nowrap ~opt:(default_opt |> check_nowrap_strict) [t] in + let e_wrap = check_chunks_nowrap ~opt:(default_opt |> check_nowrap_strict) [e] in (* if any one can't wrap, then all should expand i.e. @@ -760,7 +777,7 @@ module Make (Config : CONFIG) = struct | Block (always_hardline, exps) -> let always_hardline = match exps with - | [x] -> if not wrap then true else if can_chunks_list_wrap exps then false else always_hardline + | [x] -> if not wrap then true else if check_chunks_nowrap exps then false else always_hardline | _ -> always_hardline in let exps = @@ -846,13 +863,13 @@ module Make (Config : CONFIG) = struct *) and doc_chunks_wrapped ?(ungroup_tuple = false) ?(force_hardline = false) opts chunks = let doc = Queue.fold (fun doc chunk -> doc ^^ doc_chunk ~ungroup_tuple opts chunk) empty chunks in - let wrapped = can_chunks_list_wrap [chunks] in + let wrapped = check_chunks_nowrap [chunks] in if wrapped then doc else surround_hardline true indent 1 empty doc empty (* Format chunks, add prefix if can't wrap *) and doc_chunks_exps ?(ungroup_tuple = false) ?(wrap = true) opts chunks = let doc = Queue.fold (fun doc chunk -> doc ^^ doc_chunk ~wrap ~ungroup_tuple opts chunk) empty chunks in - let wrapped = can_chunks_list_wrap [chunks] in + let wrapped = check_chunks_nowrap [chunks] in let rec count_chunks_block_like chunks = count_chunks_by_rule chunks (fun chunk -> is_block chunk || is_match chunk) diff --git a/test/format/default/wrap_into_oneline.expect b/test/format/default/wrap_into_oneline.expect index ae5f773c6..cbd2332a4 100644 --- a/test/format/default/wrap_into_oneline.expect +++ b/test/format/default/wrap_into_oneline.expect @@ -136,7 +136,11 @@ function f b = if b == bitone then { } function valid_hex_bits_signed(n, str) = { - if string_take(str, 1) == "-" then { valid_hex_bits(n, string_drop(str, 1)) } else { valid_hex_bits(n, str) } + if string_take(str, 1) == "-" then { + valid_hex_bits(n, string_drop(str, 1)) + } else { + valid_hex_bits(n, str) + } } function if_stmt () = @@ -158,12 +162,26 @@ function fp_min(op1, op2) = { 64 => riscv_f64Lt_quiet(op1, op2), }; - let result_val = if f_is_NaN(op1) & f_is_NaN(op2) then { canonical_NaN(sizeof('m)) } else { - if f_is_NaN(op1) then { op2 } else { - if f_is_NaN(op2) then { op1 } else { - if f_is_neg_zero(op1) & f_is_pos_zero(op2) then { op1 } else { - if f_is_neg_zero(op2) & f_is_pos_zero(op1) then { op2 } else { - if op1_lt_op2 then { op1 } else { op2 } + let result_val = if f_is_NaN(op1) & f_is_NaN(op2) then { + canonical_NaN(sizeof('m)) + } else { + if f_is_NaN(op1) then { + op2 + } else { + if f_is_NaN(op2) then { + op1 + } else { + if f_is_neg_zero(op1) & f_is_pos_zero(op2) then { + op1 + } else { + if f_is_neg_zero(op2) & f_is_pos_zero(op1) then { + op2 + } else { + if op1_lt_op2 then { + op1 + } else { + /* (not rs2_lt_rs1) */ op2 + } } } } diff --git a/test/format/wrap_into_oneline.sail b/test/format/wrap_into_oneline.sail index 950f1cc62..0c8e883ea 100644 --- a/test/format/wrap_into_oneline.sail +++ b/test/format/wrap_into_oneline.sail @@ -62,7 +62,7 @@ function fp_min(op1, op2) = { if op1_lt_op2 then { op1 } else { - op2 + /* (not rs2_lt_rs1) */ op2 } } }