Skip to content

Commit

Permalink
Fmt: update check_nowrap for nested chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
trdthg committed Jul 25, 2024
1 parent fd32b89 commit bf03554
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 67 deletions.
135 changes: 76 additions & 59 deletions src/lib/format_sail.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 =
Expand Down Expand Up @@ -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)
Expand Down
32 changes: 25 additions & 7 deletions test/format/default/wrap_into_oneline.expect
Original file line number Diff line number Diff line change
Expand Up @@ -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 () =
Expand All @@ -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
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/format/wrap_into_oneline.sail
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function fp_min(op1, op2) = {
if op1_lt_op2 then {
op1
} else {
op2
/* (not rs2_lt_rs1) */ op2
}
}
}
Expand Down

0 comments on commit bf03554

Please sign in to comment.