package ppxlib
Standard infrastructure for ppx rewriters
Install
Dune Dependency
Authors
Maintainers
Sources
ppxlib-0.36.0.tbz
sha256=5aba1bce14c53108614130110c843d004bf93bd2cf3a0778fd7086b85390a434
sha512=1e3e8fee42fe74bffc178dbcbb2db8ec38dd23e71f6fed3c4c92618cf93892f5847787e6e9abb322f5c85d29a76afde28ce840b42e10fedc14cd82ba578ad06a
doc/src/ppxlib/common.ml.html
Source file common.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
open! Import open Ast_builder.Default module Buffer = Stdlib.Buffer module Format = Stdlib.Format let lident x = Longident.Lident x let core_type_of_type_declaration td = let loc = td.ptype_name.loc in ptyp_constr ~loc (Located.map lident td.ptype_name) (List.map td.ptype_params ~f:fst) let strip_gen_symbol_suffix = let chop n ~or_more string pos f = let target = !pos - n in while !pos > 0 && (or_more || !pos > target) && f string.[!pos - 1] do pos := !pos - 1 done; !pos <= target in fun string -> let pos = ref (String.length string) in if chop 1 ~or_more:false string pos (Char.equal '_') && chop 3 ~or_more:true string pos (function | '0' .. '9' -> true | _ -> false) && chop 2 ~or_more:false string pos (Char.equal '_') then String.prefix string !pos else string let gen_symbol = let cnt = ref 0 in fun ?(prefix = "_x") () -> cnt := !cnt + 1; let prefix = strip_gen_symbol_suffix prefix in Printf.sprintf "%s__%03i_" prefix !cnt let name_type_params_in_td_res (td : type_declaration) : (type_declaration, _) result = let open Result in let prefix_string i = (* a, b, ..., y, z, aa, bb, ... *) String.make ((i / 26) + 1) (Char.chr (Char.code 'a' + (i mod 26))) in let name_param i (tp, variance) = (match tp.ptyp_desc with | Ptyp_any -> Ok (Ptyp_var (gen_symbol ~prefix:(prefix_string i) ())) | Ptyp_var _ as v -> Ok v | _ -> Error (Location.Error.createf ~loc:tp.ptyp_loc "not a type parameter")) >>| fun ptyp_desc -> ({ tp with ptyp_desc }, variance) in let ptype_params, errors = td.ptype_params |> List.mapi ~f:name_param |> List.partition_map (function | Ok o -> Either.Left o | Error e -> Either.Right e) in match errors with [] -> Ok { td with ptype_params } | t :: q -> Error (t, q) let name_type_params_in_td (td : type_declaration) : type_declaration = match name_type_params_in_td_res td with | Ok res -> res | Error (err, _) -> Location.Error.raise err let combinator_type_of_type_declaration td ~f = let td = name_type_params_in_td td in let result_type = f ~loc:td.ptype_name.loc (core_type_of_type_declaration td) in List.fold_right td.ptype_params ~init:result_type ~f:(fun (tp, _variance) acc -> let loc = tp.ptyp_loc in ptyp_arrow ~loc Nolabel (f ~loc tp) acc) let string_of_core_type ct = let buf = Buffer.create 128 in let ppf = Format.formatter_of_buffer buf in Pprintast.core_type ppf ct; Format.pp_print_flush ppf (); Buffer.contents buf let get_type_param_name_res (ty, _) = let loc = ty.ptyp_loc in match ty.ptyp_desc with | Ptyp_var name -> Ok (Located.mk ~loc name) | _ -> Error (Location.Error.createf ~loc "not a type parameter", []) let get_type_param_name t = match get_type_param_name_res t with | Ok e -> e | Error (err, _) -> Location.Error.raise err exception Type_is_recursive class type_is_recursive rec_flag tds = object (self) inherit Ast_traverse0.iter as super val type_names : string list = List.map tds ~f:(fun td -> td.ptype_name.txt) method return_true () = raise_notrace Type_is_recursive method! core_type ctype = match ctype.ptyp_desc with | Ptyp_arrow _ -> () | Ptyp_constr ({ txt = Longident.Lident id; _ }, _) when List.mem ~set:type_names id -> self#return_true () | _ -> super#core_type ctype method! constructor_declaration cd = (* Don't recurse through cd.pcd_res *) match cd.pcd_args with | Pcstr_tuple args -> List.iter args ~f:self#core_type | Pcstr_record fields -> List.iter fields ~f:self#label_declaration method! attributes _ = (* Don't recurse through attributes *) () method go () = match rec_flag with | Nonrecursive -> Nonrecursive | Recursive -> ( match List.iter tds ~f:self#type_declaration with | exception Type_is_recursive -> Recursive | () -> Nonrecursive) end let really_recursive rec_flag tds = (new type_is_recursive rec_flag tds)#go () let rec last x l = match l with [] -> x | x :: l -> last x l let loc_of_name_and_payload name payload = match payload with | PStr [] -> name.loc | PStr (x :: l) -> { x.pstr_loc with loc_end = (last x l).pstr_loc.loc_end } | PSig [] -> name.loc | PSig (x :: l) -> { x.psig_loc with loc_end = (last x l).psig_loc.loc_end } | PTyp t -> t.ptyp_loc | PPat (x, None) -> x.ppat_loc | PPat (x, Some e) -> { x.ppat_loc with loc_end = e.pexp_loc.loc_end } let loc_of_payload { attr_name; attr_payload; attr_loc = _ } = loc_of_name_and_payload attr_name attr_payload let loc_of_attribute { attr_name; attr_payload; attr_loc = _ } = (* TODO: fix this in the compiler, and move the logic to omp when converting from older asts. *) (* "ocaml.doc" attributes are generated with [Location.none], which is not helpful for error messages. *) if Location.is_none attr_name.loc then loc_of_name_and_payload attr_name attr_payload else { attr_name.loc with loc_end = (loc_of_name_and_payload attr_name attr_payload).loc_end; } let loc_of_extension (name, payload) = if Location.is_none name.loc then loc_of_name_and_payload name payload else { name.loc with loc_end = (loc_of_name_and_payload name payload).loc_end } let curry_applications expr = let open Ast_builder_generated.M in match expr.pexp_desc with | Pexp_apply (f, orig_forward_args) -> let loc = expr.pexp_loc in let rec loop = function | [] -> f | last_arg :: rev_front_args -> pexp_apply ~loc (loop rev_front_args) [ last_arg ] in loop (List.rev orig_forward_args) | _ -> expr let attributes_errors = List.filter_map ~f:(function | { attr_name = name; attr_loc = _; attr_payload = _ } when Name.ignore_checks name.Location.txt -> None | attr -> let loc = loc_of_attribute attr in Some (Location.Error.createf ~loc "Attributes not allowed here")) let collect_attributes_errors = object inherit [Location.Error.t list] Ast_traverse0.fold method! attribute a acc = attributes_errors [ a ] @ acc end let assert_no_attributes l = match attributes_errors l with | [] -> () | err :: _ -> Location.Error.raise err let assert_no_attributes_in = object inherit Ast_traverse0.iter method! attribute a = assert_no_attributes [ a ] end let attribute_of_warning loc s = { attr_name = { loc; txt = "ocaml.ppwarning" }; attr_payload = PStr [ pstr_eval ~loc (estring ~loc s) [] ]; attr_loc = loc; } let is_polymorphic_variant = let rec check = function | { ptyp_desc = Ptyp_variant _; _ } -> `Definitely | { ptyp_desc = Ptyp_alias (typ, _); _ } -> check typ | { ptyp_desc = Ptyp_constr _; _ } -> `Maybe | _ -> `Surely_not (* Type vars go here even though they could be polymorphic variants, however we don't handle it if they get substituted by a polymorphic variant that is then included. *) in fun td ~sig_ -> match td.ptype_kind with | Ptype_variant _ | Ptype_record _ | Ptype_open -> `Surely_not | Ptype_abstract -> ( match td.ptype_manifest with | None -> if sig_ then `Maybe else `Surely_not | Some typ -> check typ) let mk_named_sig ~loc ~sg_name ~handle_polymorphic_variant = function | [ td ] when String.equal td.ptype_name.txt "t" && List.is_empty td.ptype_cstrs -> if (not handle_polymorphic_variant) && Poly.( = ) (is_polymorphic_variant td ~sig_:true) `Definitely then None else let arity = List.length td.ptype_params in if arity >= 4 then None else let mty = if arity = 0 then sg_name else Printf.sprintf "%s%d" sg_name arity in let td = name_type_params_in_td td in let for_subst = Ast_helper.Type.mk ~loc td.ptype_name ~params:td.ptype_params ~manifest: (ptyp_constr ~loc (Located.map_lident td.ptype_name) (List.map ~f:fst td.ptype_params)) in Some (include_infos ~loc (pmty_with ~loc (pmty_ident ~loc (Located.lident mty ~loc)) [ Pwith_typesubst (Located.lident ~loc "t", for_subst) ])) | _ -> None let exn_to_loc_error exn = match Location.Error.of_exn exn with Some error -> error | None -> raise exn module With_errors = struct type 'a t = 'a * Location.Error.t list let return e = (e, []) let ( >>= ) (x, errors1) f = let y, errors2 = f x in (y, errors1 @ errors2) let ( >>| ) (x, errors) f = (f x, errors) let of_result result ~default = match result with | Ok x -> (x, []) | Error errors -> (default, NonEmptyList.to_list errors) let combine_errors list = (List.map list ~f:fst, List.concat_map list ~f:snd) end let valid_string_constant_delimiter string = let rec attempt_string_constant_delimiter n = let delimiter = String.make n 'x' in if String.is_substring string ~substring:("|" ^ delimiter ^ "}") then attempt_string_constant_delimiter (n + 1) else delimiter in attempt_string_constant_delimiter 0
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>