package comby-kernel
A match engine for structural code search and replace that supports ~every language
Install
Dune Dependency
Authors
Maintainers
Sources
comby-kernel.1.7.0.tar.gz
md5=ee6556d8bd9b25ed0445ebe23862e48a
sha512=e6386c8ce5ef14bbcab2b0ead5b1edc39375438f56330d5f02e81e467afe6623a7e299f97f26008d77bbc62850c6dc63a7cbe5b81671b5183ff3adeee5946bb3
doc/src/comby-kernel.matchers/evaluate.ml.html
Source file evaluate.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
open Core_kernel open Match open Types.Ast let debug = match Sys.getenv "DEBUG_COMBY" with | exception Not_found -> false | _ -> true type result = bool * Match.environment option let sat = fst let result_env = snd let merge_match_environments matches environment' = List.map matches ~f:(fun { environment; _ } -> Environment.merge environment environment') let apply ?(substitute_in_place = true) ?(metasyntax = Metasyntax.default_metasyntax) ?(external_handler = External.default_external) ?filepath ~(match_all:(?configuration:Configuration.t -> ?filepath:string -> template:string -> source:string -> unit -> Match.t list)) rule env = let (module Metasyntax) = Metasyntax.create metasyntax in let module External = struct let handler = external_handler end in let (module Template : Types.Template.S) = (module (Template.Make(Metasyntax)(External))) in let match_configuration_of_syntax template = (* decide match configuration based on whether there are holes *) match Template.variables template with | [] -> Configuration.create ~match_kind:Exact () | _ -> Configuration.create ~match_kind:Fuzzy () in let rewrite_substitute template env = Rewrite.substitute ~metasyntax ~external_handler ?filepath template env in let substitute env v = match v with | Template t -> rewrite_substitute (Template.to_string t) env | String s -> s in (* accepts only one expression *) let rec eval env = function (* true *) | True -> true, Some env (* false *) | False -> false, Some env (* option *) | Option _ -> true, Some env (* ==, != *) | Equal (Template t, String value) | Equal (String value, Template t) -> let other = rewrite_substitute (Template.to_string t) env in let result = String.equal value other in result, Some env | Equal (String left, String right) -> let result = String.equal left right in result, Some env | Equal (Template left, Template right) -> let left = rewrite_substitute (Template.to_string left) env in let right = rewrite_substitute (Template.to_string right) env in let result = String.equal left right in result, Some env | Not_equal (left, right) -> let sat, env = eval env (Equal (left, right)) in not sat, env (* match ... { ... } *) | Match (source, cases) -> let source = substitute env source in let evaluate template case_expression = let template = substitute env template in let configuration = match_configuration_of_syntax template in let configuration = { configuration with substitute_in_place } in if debug then Format.printf "Running for template %s source %s@." template source; match_all ~configuration ~template ~source () |> function | [] -> None | matches -> (* merge environments. overwrite behavior is undefined *) if debug then Format.printf "Matches: %a@." Match.pp (None, matches); let fold_matches (sat, out) { environment; _ } = let fold_cases (sat, out) predicate = if sat then let env' = Environment.merge env environment in eval env' predicate else (sat, out) in List.fold case_expression ~init:(sat, out) ~f:fold_cases in List.fold matches ~init:(true, None) ~f:fold_matches |> Option.some in List.find_map cases ~f:(fun (template, case_expression) -> evaluate template case_expression) |> Option.value_map ~f:ident ~default:(false, Some env) (* rewrite ... { ... } *) | Rewrite (Template t, (match_template, rewrite_template)) -> let rewrite_template = substitute env rewrite_template in let template = substitute env match_template in let source = rewrite_substitute (Template.to_string t) env in let configuration = Configuration.create ~match_kind:Fuzzy () in let configuration = { configuration with substitute_in_place } in let matches = match_all ?filepath ~configuration ~template ~source () in let source = if substitute_in_place then Some source else None in let result = Rewrite.all ~metasyntax ?filepath ?source ~rewrite_template matches in if Option.is_empty result then (if substitute_in_place then (* rewrites are always sat for in-place. always unsat for newline-sep. *) true, Some env else false, Some env) else let Replacement.{ rewritten_source; _ } = Option.value_exn result in (* substitute for variables that are in the outside scope *) let rewritten_source = rewrite_substitute rewritten_source env in let variable = match t with | [ Types.Template.Hole { variable; _ } ] -> variable | _ -> failwith "Cannot substitute for this template" in let env = Environment.update env variable rewritten_source in true, Some env | Rewrite _ -> failwith "TODO/Invalid: Have not decided whether rewrite \":[x]\" is useful." in List.fold rule ~init:(true, None) ~f:(fun (sat, out) predicate -> if sat then let env = Option.value_map out ~f:(fun out -> Environment.merge out env) ~default:env in eval env predicate else (sat, out))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>