recursive rules with matcher and merge tests

This commit is contained in:
Rijnard van Tonder 2021-05-07 01:09:52 -07:00
parent 3512864079
commit 55c793f48f
93 changed files with 4543 additions and 7300 deletions

View File

@ -1,49 +1,8 @@
module Match = Match
type match' = Match.t
module Matchers = struct
module Matcher = Matchers.Matcher
module Configuration = Matchers.Configuration
type configuration = Configuration.t
module Syntax = Matchers.Syntax
type syntax = Matchers.Syntax.t
module Hole = Matchers.Hole
module Metasyntax = Matchers.Metasyntax
type metasyntax = Matchers.Metasyntax.t
module Alpha = Matchers.Alpha
module Omega = Matchers.Omega
module Languages = Matchers.Languages
end
module Rule = struct
open Language
type t = Rule.t
type result = Rule.result
let sat = Rule.sat
let result_env = Rule.result_env
let create = Rule.create
let apply = Rule.apply
end
type rule = Rule.t
module Replacement = Replacement
type replacement = Replacement.result
module Rewrite = struct
include Rewriter.Rewrite
include Rewriter.Rewrite_template
end
include Comby_kernel
module Pipeline = struct
module Specification = Configuration.Specification
type specification = Specification.t
include Configuration.Command_input
include Pipeline
end
module Regex = Configuration.Regex

View File

@ -1,554 +1,4 @@
open Core
(** {2 Match}
A match is a result of matching a template pattern in an input source.
A match comprises:
(1) an environment of metavariables to values, where values have an associated range.
(2) the entire string matched by a match template.
(3) the range of the entire matched string. *)
module Match : sig
module Location : sig
type t =
{ offset : int
; line : int
; column : int
}
[@@deriving eq, sexp]
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
val default : t
end
type location = Location.t
[@@deriving eq, sexp]
module Range : sig
type t =
{ match_start : location [@key "start"]
; match_end : location [@key "end"]
}
[@@deriving eq, sexp]
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
val default : t
end
type range = Range.t
[@@deriving eq, sexp]
(** {3 Environment}
A match environment maps metavariables to values for a given match. *)
module Environment : sig
type t
[@@deriving eq]
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** [create] creates a new, empty environment *)
val create : unit -> t
(** [vars env] returns all metavariables for this environment. *)
val vars : t -> string list
(** [add range env var value] adds a metavariable [var] to [env] with value
[value] and range [range]. If [var] already exists, this function has no
effect and returns the existing environment. *)
val add : ?range:range -> t -> string -> string -> t
(** [lookup env ar] returns the value assocated with a metavariable [var]. *)
val lookup : t -> string -> string option
(** [update env var value] updates the [value] of a metavariable [var] in [env]. If
the metavariable does not exist, the entry is added. *)
val update : t -> string -> string -> t
(** [lookup_range env var] returns the range associated with metavariable [var] in [env]. *)
val lookup_range : t -> string -> range option
(** [update_range env var value range] updates [env] with the [range]
associated with the [value] of [var] *)
val update_range : t -> string -> range -> t
val equal : t -> t -> bool
val copy : t -> t
val merge : t -> t -> t
val to_string : t -> string
val exists : t -> string -> bool
end
type environment = Environment.t
(** A match t is:
(1) an environment of metavariables to values, where values have an associated range.
(2) the entire string matched by a match template.
(3) the range of the entire matched string. *)
type t =
{ range : range
; environment : environment
; matched : string
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** [create] creates a new match with empty range by default. *)
val create : ?range:range -> unit -> t
(** [convert_offset] populates line and column information for a [source] file
associated with the match (by default, only the offset is computed
matches). For matches [fast] is an experimental option that uses a binary
search to perform the conversion quickly. *)
val convert_offset : fast:bool -> source:string -> t -> t
(** [pp] is a grep-like formatted printer for matches. It accepts a (optional
file path * match list) *)
val pp : Format.formatter -> string option * t list -> unit
(** [pp] is a JSON formatted printer for (optional file path * match list).
One line printed per match. *)
val pp_json_lines : Format.formatter -> string option * t list -> unit
end
type match' = Match.t
(** {2 Matchers}
Defines modules for matching a pattern in input sources to produce
matches. *)
module Matchers : sig
(** {3 Configuration}
Defines some parameters for changing match behavior. *)
module Configuration : sig
type t
type match_kind =
| Exact
| Fuzzy
(** [create] creates a new configuration based for some parts of matching
behavior. These options are for uncommon use cases and the defaults are
usually the right choice.
- [disable_substring_matching] determines whether a pattern like "a"
matches inside a substring, or whole words. Default: [false].
- [match_kind] determines whether a match template can match anywhere
inside a source file (Fuzzy), or must match it exactly (Exact). Default:
[Fuzzy].
- [significant_whitespace] is currently has no effect.
- [match_newline_toplevel] determines whether matching should terminate
on newlines if a hole is not specified inside a recognized block syntax.
Default: [false].
- [fresh] is a generator for fresh values, used to evaluate equality
relations. *)
val create
: ?disable_substring_matching:bool
-> ?match_kind:match_kind
-> ?significant_whitespace:bool
-> ?match_newline_toplevel:bool
-> ?fresh:(unit -> string)
-> unit
-> t
end
type configuration = Configuration.t
(** {3 Syntax}
Defines the syntax structures for the target language (C, Go, etc.) that
are significant for matching. *)
module Syntax : sig
(** Defines a set of quoted syntax for strings based on one or more
delimiters and associated escape chracter.
E.g., this supports single and double quotes with escape character '\'
as: { delimiters = [ {|"|}, {|'|} ]; escape_character = '\\' } *)
type escapable_string_literals =
{ delimiters : string list
; escape_character: char
}
(** Defines comment syntax as one of Multiline, Nested_multiline with
associated left and right delimiters, or Until_newline that defines a
comment prefix. associated prefix. *)
type comment_kind =
| Multiline of string * string
| Nested_multiline of string * string
| Until_newline of string
(** Defines syntax as:
- [user_defined_delimiters] are delimiters treated as code structures
(parentheses, brackets, braces, alphabetic words) -
[escapable_string_literals] are escapable quoted strings
- [raw_string literals] are raw quoted strings that have no escape
character
- [comments] are comment structures *)
type t =
{ user_defined_delimiters : (string * string) list
; escapable_string_literals : escapable_string_literals option [@default None]
; raw_string_literals : (string * string) list
; comments : comment_kind list
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** The module signature that defines language syntax for a matcher *)
module type S = sig
val user_defined_delimiters : (string * string) list
val escapable_string_literals : escapable_string_literals option
val raw_string_literals : (string * string) list
val comments : comment_kind list
end
end
type syntax = Syntax.t
(** {3 Hole}
The kinds of holes with associated matching behavior:
- [Everything] is the default hole that matches across newlines and within
the bounds of code blocks or strings, and lazily between prefix and suffix
strings in a given template.
- [Expression] matches expression-like syntax that corresponds to
contiguous well-formed code structures or strings that are whitespace
separated.
- [Alphanum] matches alphanumeric characters and underscore.
- [Non_space] matches one or more alphanumeric characters and punctuation
like ., ;, and - that do not affect balanced syntax. Language dependent.
- [Line] matches zero or more characters up to a newline, including the
newline.
- [Blank] matches one or more spaces or tabs.
- [Regex] matches a string based on a regular expression. *)
module Hole : sig
type sort =
| Everything
| Expression
| Alphanum
| Non_space
| Line
| Blank
| Regex
end
(** {3 Metasyntax}
Defines the metasyntax recognized in templates and associates the
metasyntax with the matching behavior of holes. *)
module Metasyntax : sig
(** A hole definition should comprise either a string prefix, suffix, or
both which encloses an variable identifier. See example below. *)
type hole_definition =
| Delimited of string option * string option
| Reserved_identifiers of string list
(** Defines syntax definitions for holes. Zero or more Hole sorts, excluding
[Regex] should have an associated [hole_definition]. The [Regex] hole
must define a prefix, separator, and suffix. See example below. *)
type hole_syntax =
| Hole of Hole.sort * hole_definition
| Regex of string * char * string
(** A metasyntax comprises:
- [identifier] where the list of characters are allowed in identifiers.
For example, to allow only contiguous capitalized letters as recognized
identifiers within some hole syntax, use:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- [syntax] with one or more hole definitions. For example, the default
metasyntax for the [Everything] hole is defined as:
[ Hole (Everything, Delimited (Some ":[", Some "]")) ]
A Regex hole must define a prefix, separator, and suffix. The current
convention is taken to parse Regex holes as:
<prefix><identifier><separator><regular expression><suffix>
A separator is required to syntactically distinguish arbitrary
identifier syntax from regular exressions. A suffix is required to
syntactically distinguish when to stop parsing a regular expression and
resume parsing the rest of the template. *)
type t =
{ syntax : hole_syntax list
; identifier : string
}
(** A module signature for metasyntax to parameterize a matcher *)
module type S = sig
val syntax : hole_syntax list
val identifier : string
end
(** The default metasyntax. It is defined as:
let default_syntax =
[ Hole (Everything, Delimited (Some ":[", Some "]"))
; Hole (Expression, Delimited (Some ":[", Some ":e]"))
; Hole (Alphanum, Delimited (Some ":[[", Some "]]"))
; Hole (Non_space, Delimited (Some ":[", Some ".]"))
; Hole (Line, Delimited (Some ":[", Some "\\n]"))
; Hole (Blank, Delimited (Some ":[ ", Some "]"))
; Regex (":[", '~', "]")
]
let default_identifier =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
*)
val default_metasyntax : t
(** A JSON representation of the metasyntax defintion *)
val json : t -> string
(** [create definition] creates a metasyntax module from a definition *)
val create : t -> (module S)
(** [default] returns the default metasyntax module *)
val default : (module S)
end
type metasyntax = Metasyntax.t
(** {3 Matcher}
Defines the functions that a matcher can perform. *)
module Matcher : sig
module type S = sig
(** [all conf nested template source] finds all matches of [template] in
[source]. If [nested] is true, template matching will descend
recursively on matched content. *)
val all
: ?configuration:configuration
-> ?nested: bool
-> template:string
-> source:string
-> unit
-> match' list
(** [first conf shift template source] finds the first match of [template] in [source] starting
at position [shift] (default 0). *)
val first
: ?configuration:configuration
-> ?shift:int
-> string
-> string
-> match' Or_error.t
(** [name] returns the name of this matcher (e.g., "C", "Go", etc.). *)
val name : string
(** [extensions] returns the file extensions associated with the language
that this matcher supports (e.g., ".c" and "h" for C). *)
val extensions : string list
(** [set_rewrite_template] is currently unused. *)
val set_rewrite_template : string -> unit
end
end
(** {3 Alpha Matcher}
Alpha is the match engine that defines default matchers for languages.
*)
module Alpha : sig
(** [select_with_extension metasyntax file_extension] is a convenience
function that returns a matcher associated with a [file_extension]. E.g.,
use ".c" to get the C matcher. For a full list of extensions associated
with matchers, run comby -list. If [metasyntax] is specified, the matcher
will use a custom metasyntax definition instead of the default. *)
val select_with_extension : ?metasyntax:metasyntax -> string -> (module Matcher.S) option
(** [create metasyntax syntax] creates a matcher for a language defined by
[syntax]. If [metasyntax] is specified, the matcher will use a custom
metasyntax definition instead of the default. *)
val create : ?metasyntax:metasyntax -> syntax -> (module Matcher.S)
(** [all] returns all default matchers. *)
val all : (module Matcher.S) list
(** {4 Supported Matchers} *)
module Text : Matcher.S
module Paren : Matcher.S
module Dyck : Matcher.S
module JSON : Matcher.S
module JSONC : Matcher.S
module GraphQL : Matcher.S
module Dhall : Matcher.S
module Latex : Matcher.S
module Assembly : Matcher.S
module Clojure : Matcher.S
module Lisp : Matcher.S
module Generic : Matcher.S
module Bash : Matcher.S
module Ruby : Matcher.S
module Elixir : Matcher.S
module Python : Matcher.S
module Html : Matcher.S
module Xml : Matcher.S
module SQL : Matcher.S
module Erlang : Matcher.S
module C : Matcher.S
module Csharp : Matcher.S
module Java : Matcher.S
module CSS : Matcher.S
module Kotlin : Matcher.S
module Scala : Matcher.S
module Nim : Matcher.S
module Dart : Matcher.S
module Php : Matcher.S
module Go : Matcher.S
module Javascript : Matcher.S
module Jsx : Matcher.S
module Typescript : Matcher.S
module Tsx : Matcher.S
module Swift : Matcher.S
module Rust : Matcher.S
module OCaml : Matcher.S
module Reason : Matcher.S
module Fsharp : Matcher.S
module Pascal : Matcher.S
module Julia : Matcher.S
module Fortran : Matcher.S
module Haskell : Matcher.S
module Elm : Matcher.S
module Zig : Matcher.S
module Coq : Matcher.S
module Move : Matcher.S
module Solidity : Matcher.S
module C_nested_comments : Matcher.S
end
end
(** {2 Rule}
Defines types and operations for match rules. *)
module Rule : sig
type t
type result
(** [sat result] returns true if a result of a rule is satisfied. *)
val sat : result -> bool
(** [result_env] returns a match environment associated with a rule result. *)
val result_env : result -> Match.environment option
(** [create] parses and creates a rule. *)
val create : string -> t Or_error.t
(** [apply matcher substitute_in_place fresh metasyntax rule env] applies a [rule]
according to some [matcher] for existing matches in [env]. If
[substitute_in_place] is true, rewrite rules substitute their values in
place (default true). [fresh] introduces fresh variables for evaluating
rules. [metasyntax] uses the custom metasyntax definition. *)
val apply
: ?matcher:(module Matchers.Matcher.S)
-> ?substitute_in_place:bool
-> ?fresh:(unit -> string)
-> ?metasyntax:Matchers.Metasyntax.t
-> t
-> Match.environment
-> result
end
type rule = Rule.t
(** {2 Replacement}
Defines the result of a rewrite operation. *)
module Replacement : sig
(** A replacement consists of the replaced range, the replacement content, and
the environment associated with the replacement content. *)
type t =
{ range : Match.range
; replacement_content : string
; environment : Match.environment
}
(** A replacement result is the rewritten source, and the replacement
fragments. *)
type result =
{ rewritten_source : string
; in_place_substitutions : t list
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
end
type replacement = Replacement.result
(** {2 Rewrite}
Defines rewrite operations. *)
module Rewrite : sig
(** [all source metasyntax fresh rewrite_template matches] substitutes
[rewrite_template] with each match in [matches] to create a rewrite result.
If [source] is specified, each rewrite result is substituted in-place in
the source. If [source] is not specified, rewritten matches are
newline-separated. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
If the rewrite template contains the syntax :[id()], then it is
substituted with fresh values. [fresh] may be specified to supply custom
fresh values. If not specified, fresh variables are generated in increasing
rank starting with 1, and incremented. See [substitute] for more. *)
val all
: ?source:string
-> ?metasyntax:Matchers.metasyntax
-> ?fresh:(unit -> string)
-> rewrite_template:string
-> match' list
-> replacement option
(** [substitute metasyntax fresh template environment] substitutes [template]
with the variable and value pairs in the [environment]. It returns the
result after substitution, and the list of variables in [environment] that
were substituted for. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
The syntax :[id()] is substituted with fresh values. If [fresh] is not
specified, the default behavior substitutes :[id()] starting with 1, and
subsequent :[id()] values increment the ID. If [fresh] is set, substitutes
the pattern :[id()] with the value of fresh () as the hole is encountered,
left to right. *)
val substitute
: ?metasyntax:Matchers.metasyntax
-> ?fresh:(unit -> string)
-> string
-> Match.environment
-> (string * string list)
end
include module type of Comby_kernel
(** {2 Pipeline}
@ -561,35 +11,13 @@ module Pipeline : sig
| Path of string
| String of string
(** {2 Specification}
Defines an internal type that represents an atomic operation for matching,
rule application and rewriting. *)
module Specification : sig
type t
(** [create rewrite_template rule match_template] creates a new specification.
If [rule] is supplied, it will be applied to matches of [match_template].
If [rewrite_template] is supplied, running a specification will return
replacements rather than just matches (see [process_single_source] below).
*)
val create
: ?rewrite_template:string
-> ?rule:rule
-> match_template:string
-> unit
-> t
end
type specification = Specification.t
(** The output of running a specification. Matches are a list of matches and
the number of matches found. A Replacement consists of the list of
replacement fragments, the rewrite output, and the number of replacements
made. *)
type output =
| Matches of (match' list * int)
| Replacement of (Replacement.t list * string * int)
| Matches of (Comby_kernel.match' list * int)
| Replacement of (Comby_kernel.Replacement.t list * string * int)
| Nothing
(** [execute matcher subst timeout metasyntax fresh config source spec] runs a
@ -603,12 +31,15 @@ module Pipeline : sig
[Rewrite.substitute] for more. *)
val execute
: (module Matchers.Matcher.S)
-> ?substitute_in_place:bool
-> ?timeout:int
-> ?metasyntax:Matchers.metasyntax
-> ?fresh:(unit -> string)
-> ?configuration:Matchers.configuration
-> single_source
-> specification
-> Matchers.specification
-> output
end
module Regex : sig
val to_regex : Matchers.specification -> string
end

View File

@ -3,7 +3,7 @@ open Camlzip
open Polymorphic_compare
open Language
open Comby_kernel
let debug =
Sys.getenv "DEBUG_COMBY"
@ -105,7 +105,7 @@ let read filename =
|> Option.value ~default:template
let create_rule rule =
match Option.map rule ~f:Rule.create with
match Option.map rule ~f:Matchers.Rule.create with
| None -> None
| Some Ok rule -> Some rule
| Some Error error ->
@ -138,7 +138,7 @@ let parse_toml path =
let rule = Table.find_opt (Toml.Min.key "rule") t |> to_string |> create_rule in
let rewrite_template = Table.find_opt (Toml.Min.key "rewrite") t |> to_string in
if debug then Format.printf "Processed ->%s<-@." match_template;
(name, (Specification.create ~match_template ?rule ?rewrite_template ()))::acc
(name, (Matchers.Specification.create ~match_template ?rule ?rewrite_template ()))::acc
| v ->
Format.eprintf "Unexpected format, could not parse ->%s<-@." (Toml.Printer.string_of_value v);
exit 1
@ -161,7 +161,7 @@ let parse_templates ?(warn_for_missing_file_in_dir = false) paths =
| Some match_template ->
let rule = create_rule @@ read_optional (path ^/ "rule") in
let rewrite_template = read_optional (path ^/ "rewrite") in
Specification.create ~match_template ?rule ?rewrite_template ()
Matchers.Specification.create ~match_template ?rule ?rewrite_template ()
|> Option.some
in
let f acc ~depth:_ ~absolute_path ~is_file =
@ -428,7 +428,7 @@ end
type t =
{ sources : Command_input.t
; specifications : Specification.t list
; specifications : Matchers.Specification.t list
; run_options : run_options
; output_printer : Printer.t
; interactive_review : interactive_review option
@ -499,7 +499,7 @@ let emit_errors { input_options; output_options; _ } =
Option.value_exn message
else
"UNREACHABLE")
; (let result = Rule.create input_options.rule in
; (let result = Matchers.Rule.create input_options.rule in
Or_error.is_error result
, if Or_error.is_error result then
Format.sprintf "Match rule parse error: %s@." @@
@ -532,7 +532,7 @@ let emit_warnings { input_options; output_options; _ } =
let warn_on =
[ (let match_templates =
match input_options.templates, input_options.anonymous_arguments with
| None, Some { match_template; _ } ->
| None, Some ({ match_template; _ } : anonymous_arguments) ->
[ match_template ]
| Some templates, _ ->
List.map (parse_templates templates) ~f:(fun { match_template; _ } -> match_template)
@ -682,7 +682,7 @@ let select_matcher custom_metasyntax custom_matcher override_matcher file_filter
let regex_of_specifications specifications =
Format.sprintf "(%s)"
@@ String.concat ~sep:")|("
@@ List.map specifications ~f:Specification.to_regex
@@ List.map specifications ~f:Regex.to_regex
let ripgrep_file_filters specifications args : string list =
let regex = regex_of_specifications specifications in
@ -734,28 +734,28 @@ let create
emit_warnings configuration >>= fun () ->
let rule =
let rule = String.substr_replace_all rule ~pattern:"..." ~with_:":[_]" in
Rule.create rule |> Or_error.ok_exn
Matchers.Rule.create rule |> Or_error.ok_exn
in
let specifications =
match templates, anonymous_arguments with
| None, Some { match_template; rewrite_template; _ } ->
if match_only || count then
[ Specification.create ~match_template ~rule () ]
[ Matchers.Specification.create ~match_template ~rule () ]
else
[ Specification.create ~match_template ~rewrite_template ~rule () ]
[ Matchers.Specification.create ~match_template ~rewrite_template ~rule () ]
| Some templates, _ ->
parse_templates ~warn_for_missing_file_in_dir:true templates
| _ -> assert false
in
let specifications =
List.map specifications ~f:(fun ({ match_template; _ } as spec) ->
List.map specifications ~f:(fun ({ match_template ; _ } as spec) ->
{ spec with match_template =
String.substr_replace_all match_template ~pattern:"..." ~with_:":[_]" })
in
let specifications =
if match_only then
List.map specifications ~f:(fun { match_template; rule; _ } ->
Specification.create ~match_template ?rule ())
Matchers.Specification.create ~match_template ?rule ())
else
specifications
in

View File

@ -1,5 +1,7 @@
open Core
open Comby_kernel
module Printer : sig
type printable_result =
| Matches of
@ -85,7 +87,7 @@ type user_input =
type t =
{ sources : Command_input.t
; specifications : Specification.t list
; specifications : Matchers.Specification.t list
; run_options : run_options
; output_printer : Printer.t
; interactive_review : interactive_review option

View File

@ -1,13 +1,7 @@
open Core
open Angstrom
open Language
type t =
{ match_template : string
; rule : Rule.t option
; rewrite_template : string option
}
open Comby_kernel
let (|>>) p f =
p >>= fun x -> return (f x)
@ -120,7 +114,7 @@ let escape s =
aux (String.to_list s)
|> String.of_char_list
let to_regex { match_template; _ } =
let to_regex Matchers.Specification.{ match_template; _ } =
let state = Buffered.parse extract in
let state = Buffered.feed state (`String match_template) in
let extracted =
@ -136,6 +130,3 @@ let to_regex { match_template; _ } =
(* ?s is modifier metasyntax where . matches all chars including newlines. See
regular-expressions.info/modifier.html *)
Format.sprintf "(%s)" @@ String.concat extracted ~sep:")(\\n|.)*?("
let create ?rewrite_template ?rule ~match_template () =
{ match_template; rule; rewrite_template }

View File

@ -0,0 +1,3 @@
open Comby_kernel
val to_regex : Matchers.specification -> string

View File

@ -1,11 +0,0 @@
open Language
type t =
{ match_template : string
; rule : Rule.t option
; rewrite_template : string option
}
val to_regex : t -> string
val create : ?rewrite_template:string -> ?rule:Language.Rule.t -> match_template:string -> unit -> t

View File

@ -1,13 +1,13 @@
open Core
open Comby_kernel
open Configuration
open Command_configuration
open Command_input
open Rewriter
open Statistics
open Match
open Language
open Matchers
let verbose_out_file = "/tmp/comby.out"
@ -15,32 +15,9 @@ let debug =
Sys.getenv "DEBUG_COMBY"
|> Option.is_some
let infer_equality_constraints environment =
let vars = Environment.vars environment in
List.fold vars ~init:[] ~f:(fun acc var ->
if String.is_suffix var ~suffix:"_equal" then
match String.split var ~on:'_' with
| _uuid :: target :: _equal ->
let expression = Language.Ast.Equal (Variable var, Variable target) in
expression::acc
| _ -> acc
else
acc)
let apply_rule ?(substitute_in_place = true) ?metasyntax matcher rule matches =
let open Option in
List.filter_map matches ~f:(fun ({ environment; _ } as matched) ->
let rule = rule @ infer_equality_constraints environment in
let fresh () = Uuid_unix.(Fn.compose Uuid.to_string create ()) in
let sat, env = Rule.apply ?metasyntax ~fresh ~substitute_in_place ~matcher rule environment in
(if sat then env else None)
>>| fun environment -> { matched with environment })
let timed_run
(module Matcher : Matchers.Matcher.S)
(module Matcher : Matcher.S)
?(fast_offset_conversion = false)
?substitute_in_place
?metasyntax
~configuration
~source
~specification:(Specification.{ match_template = template; rule; rewrite_template })
@ -48,10 +25,9 @@ let timed_run
(match rewrite_template with
| Some template -> Matcher.set_rewrite_template template;
| None -> ());
let rule = Option.value rule ~default:[Ast.True] in
let rule = Option.value rule ~default:(Rule.create "where true" |> Or_error.ok_exn) in
let options = Rule.options rule in
let matches = Matcher.all ~nested:options.nested ~configuration ~template ~source () in
let matches = apply_rule ?substitute_in_place ?metasyntax (module Matcher) rule matches in
let matches = Matcher.all ~rule ~nested:options.nested ~configuration ~template ~source () in
List.map matches ~f:(Match.convert_offset ~fast:fast_offset_conversion ~source)
type output =
@ -74,7 +50,6 @@ let log_to_file path =
let process_single_source
matcher
?(fast_offset_conversion = false)
?(substitute_in_place = false)
?(verbose = false)
?(timeout = 3)
?metasyntax
@ -95,8 +70,6 @@ let process_single_source
with_timeout timeout source ~f:(fun () ->
timed_run
matcher
?metasyntax
~substitute_in_place
~fast_offset_conversion
~configuration
~specification
@ -222,7 +195,6 @@ let run_interactive
specifications
matcher
fast_offset_conversion
substitute_in_place
match_configuration
verbose
timeout
@ -237,7 +209,6 @@ let run_interactive
process_single_source
matcher
~fast_offset_conversion
~substitute_in_place
~verbose
~timeout
match_configuration
@ -268,7 +239,7 @@ let run
{ verbose
; match_timeout = timeout
; dump_statistics
; substitute_in_place
; substitute_in_place = _ (* FIXME remove *)
; disable_substring_matching
; fast_offset_conversion
; match_newline_toplevel
@ -304,7 +275,6 @@ let run
process_single_source
matcher
~fast_offset_conversion
~substitute_in_place
~verbose
~timeout
?metasyntax
@ -327,7 +297,6 @@ let run
specifications
matcher
fast_offset_conversion
substitute_in_place
match_configuration
verbose
timeout
@ -339,7 +308,6 @@ let run
let execute
matcher
?substitute_in_place
?timeout
?metasyntax
?fresh
@ -349,7 +317,6 @@ let execute
process_single_source
matcher
~fast_offset_conversion:false
?substitute_in_place
~verbose:false
?timeout
?metasyntax

View File

@ -1,3 +1,5 @@
open Comby_kernel
open Configuration
open Command_input
@ -9,25 +11,23 @@ type output =
val process_single_source
: (module Matchers.Matcher.S)
-> ?fast_offset_conversion:bool
-> ?substitute_in_place:bool
-> ?verbose:bool
-> ?timeout:int
-> ?metasyntax:Matchers.Metasyntax.t
-> ?fresh:(unit -> string)
-> Matchers.Configuration.t
-> single_source
-> Specification.t
-> Matchers.Specification.t
-> output
val execute
: (module Matchers.Matcher.S)
-> ?substitute_in_place:bool
-> ?timeout:int
-> ?metasyntax:Matchers.Metasyntax.t
-> ?fresh:(unit -> string)
-> ?configuration:Matchers.Configuration.t
-> single_source
-> Specification.t
-> Matchers.Specification.t
-> output
val with_timeout : int -> Command_input.single_source -> f:(unit -> 'a list) -> 'a list

View File

@ -1,7 +1,15 @@
module Match = Match
type match' = Match.t
module Replacement = Replacement
type replacement = Replacement.result
module Matchers = struct
module Engine = Matchers.Engine
module Info = Matchers.Info
module Language = Matchers.Language
module Matcher = Matchers.Matcher
module Configuration = Matchers.Configuration
@ -18,25 +26,20 @@ module Matchers = struct
module Omega = Matchers.Omega
module Languages = Matchers.Languages
end
module Rule = struct
open Language
type t = Rule.t
type result = Rule.result
let sat = Rule.sat
let result_env = Rule.result_env
let create = Rule.create
let apply = Rule.apply
end
type rule = Rule.t
module Replacement = Replacement
type replacement = Replacement.result
module Rewrite = struct
include Rewriter.Rewrite
include Rewriter.Rewrite_template
module Rule = struct
include Matchers.Rule
include Matchers.Rule.Ast
include Matchers.Rule.Parser
include Matchers.Evaluate
end
type rule = Rule.t
module Specification = Matchers.Specification
type specification = Specification.t
module Rewrite = struct
include Matchers.Rewriter.Rewrite
include Matchers.Rewriter.Rewrite_template
end
end

View File

@ -1,5 +1,3 @@
open Core_kernel
(** {2 Match}
A match is a result of matching a template pattern in an input source.
@ -119,10 +117,48 @@ module Match : sig
(** [pp] is a JSON formatted printer for (optional file path * match list).
One line printed per match. *)
val pp_json_lines : Format.formatter -> string option * t list -> unit
val pp_match_count : Format.formatter -> string option * t list -> unit
end
type match' = Match.t
(** {2 Replacement}
Defines the result of a rewrite operation. *)
module Replacement : sig
(** A replacement consists of the replaced range, the replacement content, and
the environment associated with the replacement content. *)
type t =
{ range : Match.range
; replacement_content : string
; environment : Match.environment
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
val to_json
: ?path:string
-> ?replacements:t list
-> ?rewritten_source:string
-> diff:string
-> unit
-> Yojson.Safe.json
(** A replacement result is the rewritten source, and the replacement
fragments. *)
type result =
{ rewritten_source : string
; in_place_substitutions : t list
}
val result_to_yojson : result -> Yojson.Safe.json
end
type replacement = Replacement.result
(** {2 Matchers}
Defines modules for matching a pattern in input sources to produce
@ -170,61 +206,6 @@ module Matchers : sig
type configuration = Configuration.t
(** {3 Syntax}
Defines the syntax structures for the target language (C, Go, etc.) that
are significant for matching. *)
module Syntax : sig
(** Defines a set of quoted syntax for strings based on one or more
delimiters and associated escape chracter.
E.g., this supports single and double quotes with escape character '\'
as: { delimiters = [ {|"|}, {|'|} ]; escape_character = '\\' } *)
type escapable_string_literals =
{ delimiters : string list
; escape_character: char
}
(** Defines comment syntax as one of Multiline, Nested_multiline with
associated left and right delimiters, or Until_newline that defines a
comment prefix. associated prefix. *)
type comment_kind =
| Multiline of string * string
| Nested_multiline of string * string
| Until_newline of string
(** Defines syntax as:
- [user_defined_delimiters] are delimiters treated as code structures
(parentheses, brackets, braces, alphabetic words) -
[escapable_string_literals] are escapable quoted strings
- [raw_string literals] are raw quoted strings that have no escape
character
- [comments] are comment structures *)
type t =
{ user_defined_delimiters : (string * string) list
; escapable_string_literals : escapable_string_literals option [@default None]
; raw_string_literals : (string * string) list
; comments : comment_kind list
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** The module signature that defines language syntax for a matcher *)
module type S = sig
val user_defined_delimiters : (string * string) list
val escapable_string_literals : escapable_string_literals option
val raw_string_literals : (string * string) list
val comments : comment_kind list
end
end
type syntax = Syntax.t
(** {3 Hole}
The kinds of holes with associated matching behavior:
@ -305,12 +286,18 @@ module Matchers : sig
; identifier : string
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** A module signature for metasyntax to parameterize a matcher *)
module type S = sig
val syntax : hole_syntax list
val identifier : string
end
(** A module representing the default metasyntax *)
module Default : S
(** The default metasyntax. It is defined as:
let default_syntax =
@ -343,14 +330,15 @@ module Matchers : sig
(** {3 Matcher}
Defines the functions that a matcher can perform. *)
module Matcher : sig
module rec Matcher : sig
module type S = sig
(** [all conf nested template source] finds all matches of [template] in
[source]. If [nested] is true, template matching will descend
recursively on matched content. *)
val all
: ?configuration:configuration
-> ?nested: bool
-> ?rule:Rule.t
-> ?nested:bool
-> template:string
-> source:string
-> unit
@ -363,7 +351,7 @@ module Matchers : sig
-> ?shift:int
-> string
-> string
-> match' Or_error.t
-> match' Core_kernel.Or_error.t
(** [name] returns the name of this matcher (e.g., "C", "Go", etc.). *)
val name : string
@ -377,175 +365,356 @@ module Matchers : sig
end
end
(** {2 Rule}
Defines types and operations for match rules. *)
and Rule : sig
module Ast : sig
type atom =
| Variable of string
| String of string
[@@deriving sexp]
type antecedent = atom
[@@deriving sexp]
type expression =
| True
| False
| Option of string
| Equal of atom * atom
| Not_equal of atom * atom
| Match of atom * (antecedent * consequent) list
| RewriteTemplate of string
| Rewrite of atom * (antecedent * expression)
and consequent = expression list
[@@deriving sexp]
end
type t = Ast.expression list
[@@deriving sexp]
type options =
{ nested : bool
}
val create : string -> t Core_kernel.Or_error.t
val options : t -> options
type result
(** [sat result] returns true if a result of a rule is satisfied. *)
val sat : result -> bool
val result_env : result -> Match.environment option
(** [apply matcher substitute_in_place fresh metasyntax rule env] applies a [rule]
according to some [matcher] for existing matches in [env]. If
[substitute_in_place] is true, rewrite rules substitute their values in
place (default true). [fresh] introduces fresh variables for evaluating
rules. [metasyntax] uses the custom metasyntax definition. *)
val apply :
?substitute_in_place:bool ->
?fresh:(unit -> string) ->
?metasyntax:Metasyntax.t ->
match_all:(?configuration:Configuration.t ->
template:string -> source:string -> unit -> Match.t list) ->
Rule.Ast.expression list ->
Match.Environment.t -> result
end
type rule = Rule.t
(** {3 Specification}
Defines an internal type that represents an atomic operation for matching,
rule application and rewriting. *)
module Specification : sig
type t =
{ match_template : string
; rule : Rule.t option
; rewrite_template : string option
}
(** [create rewrite_template rule match_template] creates a new specification.
If [rule] is supplied, it will be applied to matches of [match_template].
If [rewrite_template] is supplied, running a specification will return
replacements rather than just matches (see [process_single_source] below).
*)
val create : ?rewrite_template:string -> ?rule:rule -> match_template:string -> unit -> t
end
type specification = Specification.t
(** {3 Syntax}
Defines the syntax structures for the target language (C, Go, etc.) that
are significant for matching. *)
module Syntax : sig
(** Defines a set of quoted syntax for strings based on one or more
delimiters and associated escape chracter.
E.g., this supports single and double quotes with escape character '\'
as: { delimiters = [ {|"|}, {|'|} ]; escape_character = '\\' } *)
type escapable_string_literals =
{ delimiters : string list
; escape_character: char
}
(** Defines comment syntax as one of Multiline, Nested_multiline with
associated left and right delimiters, or Until_newline that defines a
comment prefix. associated prefix. *)
type comment_kind =
| Multiline of string * string
| Nested_multiline of string * string
| Until_newline of string
(** Defines syntax as:
- [user_defined_delimiters] are delimiters treated as code structures
(parentheses, brackets, braces, alphabetic words) -
[escapable_string_literals] are escapable quoted strings
- [raw_string literals] are raw quoted strings that have no escape
character
- [comments] are comment structures *)
type t =
{ user_defined_delimiters : (string * string) list
; escapable_string_literals : escapable_string_literals option [@default None]
; raw_string_literals : (string * string) list
; comments : comment_kind list
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
(** The module signature that defines language syntax for a matcher *)
module type S = sig
val user_defined_delimiters : (string * string) list
val escapable_string_literals : escapable_string_literals option
val raw_string_literals : (string * string) list
val comments : comment_kind list
end
end
type syntax = Syntax.t
module Info : sig
module type S = sig
val name : string
val extensions : string list
end
end
module Language : sig
module type S = sig
module Info : Info.S
module Syntax : Syntax.S
end
end
module Languages : sig
module Text : Language.S
module Paren : Language.S
module Dyck : Language.S
module JSON : Language.S
module JSONC : Language.S
module GraphQL : Language.S
module Dhall : Language.S
module Latex : Language.S
module Assembly : Language.S
module Clojure : Language.S
module Lisp : Language.S
module Generic : Language.S
module Bash : Language.S
module Ruby : Language.S
module Elixir : Language.S
module Python : Language.S
module Html : Language.S
module Xml : Language.S
module SQL : Language.S
module Erlang : Language.S
module C : Language.S
module Csharp : Language.S
module Java : Language.S
module CSS : Language.S
module Kotlin : Language.S
module Scala : Language.S
module Nim : Language.S
module Dart : Language.S
module Php : Language.S
module Go : Language.S
module Javascript : Language.S
module Jsx : Language.S
module Typescript : Language.S
module Tsx : Language.S
module Swift : Language.S
module Rust : Language.S
module OCaml : Language.S
module Reason : Language.S
module Fsharp : Language.S
module Pascal : Language.S
module Julia : Language.S
module Fortran : Language.S
module Haskell : Language.S
module Elm : Language.S
module Zig : Language.S
module Coq : Language.S
module Move : Language.S
module Solidity : Language.S
module C_nested_comments : Language.S
val all : (module Language.S) list
val select_with_extension : string -> (module Language.S) option
end
module Engine : sig
module type S = sig
module Make : Language.S -> Metasyntax.S -> Matcher.S
(** {4 Supported Matchers} *)
module Text : Matcher.S
module Paren : Matcher.S
module Dyck : Matcher.S
module JSON : Matcher.S
module JSONC : Matcher.S
module GraphQL : Matcher.S
module Dhall : Matcher.S
module Latex : Matcher.S
module Assembly : Matcher.S
module Clojure : Matcher.S
module Lisp : Matcher.S
module Generic : Matcher.S
module Bash : Matcher.S
module Ruby : Matcher.S
module Elixir : Matcher.S
module Python : Matcher.S
module Html : Matcher.S
module Xml : Matcher.S
module SQL : Matcher.S
module Erlang : Matcher.S
module C : Matcher.S
module Csharp : Matcher.S
module Java : Matcher.S
module CSS : Matcher.S
module Kotlin : Matcher.S
module Scala : Matcher.S
module Nim : Matcher.S
module Dart : Matcher.S
module Php : Matcher.S
module Go : Matcher.S
module Javascript : Matcher.S
module Jsx : Matcher.S
module Typescript : Matcher.S
module Tsx : Matcher.S
module Swift : Matcher.S
module Rust : Matcher.S
module OCaml : Matcher.S
module Reason : Matcher.S
module Fsharp : Matcher.S
module Pascal : Matcher.S
module Julia : Matcher.S
module Fortran : Matcher.S
module Haskell : Matcher.S
module Elm : Matcher.S
module Zig: Matcher.S
module Coq: Matcher.S
module Move: Matcher.S
module Solidity: Matcher.S
module C_nested_comments : Matcher.S
(** [all] returns all default matchers. *)
val all : (module Matcher.S) list
(** [select_with_extension metasyntax file_extension] is a convenience
function that returns a matcher associated with a [file_extension]. E.g.,
use ".c" to get the C matcher. For a full list of extensions associated
with matchers, run comby -list. If [metasyntax] is specified, the matcher
will use a custom metasyntax definition instead of the default. *)
val select_with_extension : ?metasyntax:Metasyntax.t -> string -> (module Matcher.S) option
(** [create metasyntax syntax] creates a matcher for a language defined by
[syntax]. If [metasyntax] is specified, the matcher will use a custom
metasyntax definition instead of the default. *)
val create : ?metasyntax:Metasyntax.t -> Syntax.t -> (module Matcher.S)
end
end
(** {3 Alpha Matcher}
Alpha is the match engine that defines default matchers for languages.
*)
module Alpha : sig
(** [select_with_extension metasyntax file_extension] is a convenience
function that returns a matcher associated with a [file_extension]. E.g.,
use ".c" to get the C matcher. For a full list of extensions associated
with matchers, run comby -list. If [metasyntax] is specified, the matcher
will use a custom metasyntax definition instead of the default. *)
val select_with_extension : ?metasyntax:metasyntax -> string -> (module Matcher.S) option
module Alpha : Engine.S
(** [create metasyntax syntax] creates a matcher for a language defined by
[syntax]. If [metasyntax] is specified, the matcher will use a custom
metasyntax definition instead of the default. *)
val create : ?metasyntax:metasyntax -> syntax -> (module Matcher.S)
(** {3 Omega Matcher}
(** [all] returns all default matchers. *)
val all : (module Matcher.S) list
Alternative, partial, experimental match engine.
*)
module Omega : Engine.S
(** {4 Supported Matchers} *)
module Text : Matcher.S
module Paren : Matcher.S
module Dyck : Matcher.S
module JSON : Matcher.S
module JSONC : Matcher.S
module GraphQL : Matcher.S
module Dhall : Matcher.S
module Latex : Matcher.S
module Assembly : Matcher.S
module Clojure : Matcher.S
module Lisp : Matcher.S
module Generic : Matcher.S
module Bash : Matcher.S
module Ruby : Matcher.S
module Elixir : Matcher.S
module Python : Matcher.S
module Html : Matcher.S
module Xml : Matcher.S
module SQL : Matcher.S
module Erlang : Matcher.S
module C : Matcher.S
module Csharp : Matcher.S
module Java : Matcher.S
module CSS : Matcher.S
module Kotlin : Matcher.S
module Scala : Matcher.S
module Nim : Matcher.S
module Dart : Matcher.S
module Php : Matcher.S
module Go : Matcher.S
module Javascript : Matcher.S
module Jsx : Matcher.S
module Typescript : Matcher.S
module Tsx : Matcher.S
module Swift : Matcher.S
module Rust : Matcher.S
module OCaml : Matcher.S
module Reason : Matcher.S
module Fsharp : Matcher.S
module Pascal : Matcher.S
module Julia : Matcher.S
module Fortran : Matcher.S
module Haskell : Matcher.S
module Elm : Matcher.S
module Zig : Matcher.S
module Coq : Matcher.S
module Move : Matcher.S
module Solidity : Matcher.S
module C_nested_comments : Matcher.S
(** {3 Rewrite}
Defines rewrite operations. *)
module Rewrite : sig
(** [all source metasyntax fresh rewrite_template matches] substitutes
[rewrite_template] with each match in [matches] to create a rewrite result.
If [source] is specified, each rewrite result is substituted in-place in
the source. If [source] is not specified, rewritten matches are
newline-separated. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
If the rewrite template contains the syntax :[id()], then it is
substituted with fresh values. [fresh] may be specified to supply custom
fresh values. If not specified, fresh variables are generated in increasing
rank starting with 1, and incremented. See [substitute] for more. *)
val all
: ?source:string
-> ?metasyntax:metasyntax
-> ?fresh:(unit -> string)
-> rewrite_template:string
-> match' list
-> replacement option
(** [substitute metasyntax fresh template environment] substitutes [template]
with the variable and value pairs in the [environment]. It returns the
result after substitution, and the list of variables in [environment] that
were substituted for. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
The syntax :[id()] is substituted with fresh values. If [fresh] is not
specified, the default behavior substitutes :[id()] starting with 1, and
subsequent :[id()] values increment the ID. If [fresh] is set, substitutes
the pattern :[id()] with the value of fresh () as the hole is encountered,
left to right. *)
val substitute
: ?metasyntax:metasyntax
-> ?fresh:(unit -> string)
-> string
-> Match.environment
-> (string * string list)
type syntax =
{ variable: string
; pattern: string
}
type extracted =
| Hole of syntax
| Constant of string
module Make : Metasyntax.S -> sig
val parse : string -> extracted list option
val variables : string -> syntax list
end
val get_offsets_for_holes : syntax list -> string -> (string * int) list
val get_offsets_after_substitution : (string * int) list -> Match.environment -> (string * int) list
end
end
(** {2 Rule}
Defines types and operations for match rules. *)
module Rule : sig
type t
type result
(** [sat result] returns true if a result of a rule is satisfied. *)
val sat : result -> bool
(** [result_env] returns a match environment associated with a rule result. *)
val result_env : result -> Match.environment option
(** [create] parses and creates a rule. *)
val create : string -> t Or_error.t
(** [apply matcher substitute_in_place fresh metasyntax rule env] applies a [rule]
according to some [matcher] for existing matches in [env]. If
[substitute_in_place] is true, rewrite rules substitute their values in
place (default true). [fresh] introduces fresh variables for evaluating
rules. [metasyntax] uses the custom metasyntax definition. *)
val apply
: ?matcher:(module Matchers.Matcher.S)
-> ?substitute_in_place:bool
-> ?fresh:(unit -> string)
-> ?metasyntax:Matchers.Metasyntax.t
-> t
-> Match.environment
-> result
end
type rule = Rule.t
(** {2 Replacement}
Defines the result of a rewrite operation. *)
module Replacement : sig
(** A replacement consists of the replaced range, the replacement content, and
the environment associated with the replacement content. *)
type t =
{ range : Match.range
; replacement_content : string
; environment : Match.environment
}
(** A replacement result is the rewritten source, and the replacement
fragments. *)
type result =
{ rewritten_source : string
; in_place_substitutions : t list
}
val to_yojson : t -> Yojson.Safe.json
val of_yojson : Yojson.Safe.json -> (t, string) Result.t
end
type replacement = Replacement.result
(** {2 Rewrite}
Defines rewrite operations. *)
module Rewrite : sig
(** [all source metasyntax fresh rewrite_template matches] substitutes
[rewrite_template] with each match in [matches] to create a rewrite result.
If [source] is specified, each rewrite result is substituted in-place in
the source. If [source] is not specified, rewritten matches are
newline-separated. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
If the rewrite template contains the syntax :[id()], then it is
substituted with fresh values. [fresh] may be specified to supply custom
fresh values. If not specified, fresh variables are generated in increasing
rank starting with 1, and incremented. See [substitute] for more. *)
val all
: ?source:string
-> ?metasyntax:Matchers.metasyntax
-> ?fresh:(unit -> string)
-> rewrite_template:string
-> match' list
-> replacement option
(** [substitute metasyntax fresh template environment] substitutes [template]
with the variable and value pairs in the [environment]. It returns the
result after substitution, and the list of variables in [environment] that
were substituted for. If [metasyntax] is defined, the rewrite template will
respect custom metasyntax definitions.
The syntax :[id()] is substituted with fresh values. If [fresh] is not
specified, the default behavior substitutes :[id()] starting with 1, and
subsequent :[id()] values increment the ID. If [fresh] is set, substitutes
the pattern :[id()] with the value of fresh () as the hole is encountered,
left to right. *)
val substitute
: ?metasyntax:Matchers.metasyntax
-> ?fresh:(unit -> string)
-> string
-> Match.environment
-> (string * string list)
end

View File

@ -5,8 +5,6 @@
(preprocess (pps ppx_deriving.show ppx_deriving.eq ppx_sexp_conv))
(libraries
core_kernel
comby-kernel.language
comby-kernel.match
comby-kernel.matchers
comby-kernel.replacement
comby-kernel.rewriter))
comby-kernel.replacement))

View File

@ -1,56 +0,0 @@
open Core_kernel
type atom =
| Variable of string
| String of string
[@@deriving sexp]
type antecedent = atom
[@@deriving sexp]
type expression =
| True
| False
| Option of string
| Equal of atom * atom
| Not_equal of atom * atom
| Match of atom * (antecedent * consequent) list
| RewriteTemplate of string
| Rewrite of atom * (antecedent * expression)
and consequent = expression list
[@@deriving sexp]
let (=) left right = Equal (left, right)
let (<>) left right = Not_equal (left, right)
type t = expression list
[@@deriving sexp]
module Script = struct
module Specification = struct
type t =
{ match_template : string
; rule : expression list option
; rewrite_template : string option
}
[@@deriving sexp]
end
type spec = Specification.t
[@@deriving sexp]
type op =
| And
| Or
| Not
[@@deriving sexp]
type exp =
| Exp of op * exp list
| Spec of spec
[@@deriving sexp]
type t = exp list
[@@deriving sexp]
end

View File

@ -1,6 +0,0 @@
(library
(name language)
(public_name comby-kernel.language)
(instrumentation (backend bisect_ppx))
(preprocess (pps ppx_sexp_conv))
(libraries comby-kernel.parsers comby-kernel.match comby-kernel.rewriter core_kernel))

View File

@ -1,10 +0,0 @@
open Core_kernel
type t =
{ nested : bool
}
let of_rule (rule : Ast.t) : t =
List.fold rule ~init:{ nested = false } ~f:(fun acc -> function
| Option name when String.(name = Syntax.option_nested) -> { nested = true }
| _ -> acc)

View File

@ -1,5 +0,0 @@
type t =
{ nested : bool
}
val of_rule : Ast.t -> t

View File

@ -1,195 +0,0 @@
open Core_kernel
open Angstrom
open Ast
let alphanum =
satisfy (function
| 'a' .. 'z'
| 'A' .. 'Z'
| '0' .. '9' -> true
| _ -> false)
let variable_parser =
(string Syntax.variable_left_delimiter
*> (many (alphanum <|> char '_') >>| String.of_char_list)
<* string Syntax.variable_right_delimiter)
(** Interpret escape sequences inside quotes *)
let char_token_s =
(char '\\' *> any_char >>|
function
| 'r' -> Char.to_string '\r'
| 'n' -> Char.to_string '\n'
| 't' -> Char.to_string '\t'
| '\\' -> Char.to_string '\\'
| c -> Format.sprintf {|\%c|} c)
<|> (any_char >>| String.of_char)
(** With escape sequences *)
let quote s =
(string s *> (many_till char_token_s (string s)))
>>| String.concat
let raw s =
(string s *> (many_till any_char (string s)))
>>| String.of_char_list
let quoted_parser =
choice [ quote {|"|}; quote {|'|}; raw {|`|} ]
let operator_parser =
choice
[ string Syntax.equal
; string Syntax.not_equal
]
let any_char_except ~reserved =
List.fold reserved
~init:(return `OK)
~f:(fun acc reserved_sequence ->
option `End_of_input
(peek_string (String.length reserved_sequence)
>>= fun s ->
if String.equal s reserved_sequence then
return `Reserved_sequence
else
acc))
>>= function
| `OK -> any_char
| `End_of_input -> any_char
| `Reserved_sequence -> fail "reserved sequence hit"
let value_parser ~reserved () =
match reserved with
| [] -> fail "no value allowed to scan here"
| reserved -> many (any_char_except ~reserved)
let map_special s =
if String.is_prefix s ~prefix:"~" then
Variable (Format.sprintf ":[%s]" s)
else if String.equal s "_" then
Variable ":[_]"
else
String s
let antecedent_parser ?(reserved = []) () =
choice
[ (quoted_parser >>| fun value -> String value)
; (value_parser ~reserved () >>| fun value -> map_special (String.of_char_list value))
]
let atom_parser ?(reserved = []) () =
choice
[ (variable_parser >>| fun variable -> Variable variable)
; (quoted_parser >>| fun value -> String value)
; (value_parser ~reserved () >>| fun value -> String (String.of_char_list value))
]
let rewrite_template_parser =
quoted_parser >>| fun value -> RewriteTemplate value
let ignore p =
p *> return ()
let make_equality_expression left operator right =
if String.equal operator Syntax.equal then
Equal (left, right)
else
Not_equal (left, right)
let is_whitespace = function
| ' ' | '\t' | '\r' | '\n' -> true
| _ -> false
let spaces =
take_while is_whitespace
let spaces1 =
satisfy is_whitespace *>
take_while is_whitespace *>
return ()
let optional_trailing c = option () (skip (Char.equal c))
let option_parser = spaces *> string Syntax.option_nested <* spaces >>| fun _ -> Option "nested"
let true' = lift (fun _ -> True) (spaces *> string Syntax.true' <* spaces)
let false' = lift (fun _ -> False) (spaces *> string Syntax.false' <* spaces)
(** <atom> [==, !=] <atom> *)
let operator_parser =
lift3
make_equality_expression
(spaces *> atom_parser ())
(spaces *> operator_parser)
(spaces *> atom_parser ())
<* spaces
let make_rewrite_expression atom match_template rewrite_template =
Rewrite (atom, (match_template, rewrite_template))
let make_match_expression atom cases =
Match (atom, cases)
(** rewrite <atom> { <atom> -> <atom> } *)
let rewrite_pattern_parser =
lift3
make_rewrite_expression
(string Syntax.start_rewrite_pattern *> spaces *> atom_parser () <* spaces <* char '{' <* spaces)
(antecedent_parser ~reserved:[" ->"] () <* spaces <* string Syntax.arrow <* spaces)
(spaces *> rewrite_template_parser <* spaces <* char '}' <* spaces)
(** <atom> -> atom [, <expr>], [,] *)
let match_arrow_parser expression_parser =
both
(antecedent_parser ~reserved:[" ->"] () <* spaces <* string Syntax.arrow <* spaces)
(spaces *> sep_by (char ',') expression_parser <* spaces <* optional_trailing ',' <* spaces)
(** [|] <match_arrow> *)
let first_case_parser expression_parser =
spaces *> option () (ignore @@ string Syntax.pipe_operator *> spaces) *>
match_arrow_parser expression_parser
(** | <match_arrow> *)
let case_parser expression_parser =
spaces *> string Syntax.pipe_operator *> spaces *>
match_arrow_parser expression_parser
(** [|] <match_arrow> | <match_arrow> *)
let case_block expression_parser =
first_case_parser expression_parser >>= fun case ->
many (case_parser expression_parser) >>= fun cases ->
return (case :: cases)
(** match <atom> { <case_parser> } *)
let match_pattern_parser expression_parser =
string Syntax.start_match_pattern *> spaces *>
lift2
make_match_expression
(atom_parser () <* spaces <* char '{' <* spaces)
(case_block expression_parser <* char '}' <* spaces)
let expression_parser =
fix (fun expression_parser ->
choice
[ match_pattern_parser expression_parser
; rewrite_pattern_parser
; operator_parser
; true'
; false'
; option_parser
])
(** where <expression> [,] *)
let parse =
spaces *> string Syntax.rule_prefix *>
spaces1 *> sep_by1 (spaces *> char ',' <* spaces) expression_parser
<* optional_trailing ','
<* spaces
let create rule =
match parse_string ~consume:All (parse <* end_of_input) rule with
| Ok rule -> Ok rule
| Error error -> Or_error.error_string error

View File

@ -1,5 +0,0 @@
include Types
let create = Parser.create
include Evaluate

View File

@ -1,7 +0,0 @@
open Core_kernel
include module type of Types
val create : string -> t Or_error.t
include Engine

View File

@ -1,25 +0,0 @@
open Matchers
open Match
type t = Ast.t
type result = bool * environment option
type options = Options.t
module type Engine = sig
val options : t -> Options.t
val sat : result -> bool
val result_env : result -> environment option
val apply
: ?matcher:(module Matcher.S)
-> ?substitute_in_place:bool
-> ?fresh:(unit -> string)
-> ?metasyntax:Matchers.Metasyntax.t
-> t
-> environment
-> result
end

File diff suppressed because it is too large Load Diff

View File

@ -3,4 +3,4 @@
(public_name comby-kernel.matchers)
(instrumentation (backend bisect_ppx))
(preprocess (pps ppx_here ppx_sexp_conv ppx_sexp_message ppx_deriving_yojson))
(libraries comby-kernel.parsers comby-kernel.match angstrom core_kernel mparser mparser-pcre re yojson ppx_deriving_yojson))
(libraries comby-kernel.replacement comby-kernel.parsers comby-kernel.match angstrom core_kernel mparser mparser-pcre re yojson ppx_deriving_yojson))

View File

@ -1,19 +1,15 @@
open Core_kernel
open Match
open Rewriter
open Rule
open Ast
module Configuration = Matchers.Configuration
let debug =
match Sys.getenv "DEBUG_COMBY" with
| exception Not_found -> false
| _ -> true
type t = Ast.t
type result = bool * environment option
type options = Options.t
let options = Options.of_rule
type result = bool * Match.environment option
let sat = fst
@ -42,21 +38,20 @@ let counter =
uuid_for_id_counter := !uuid_for_id_counter + 1;
Format.sprintf "gu3ssme_%012d" !uuid_for_id_counter
let equal_in_environment var value env =
match Environment.lookup env var with
| None -> false, Some env
| Some var_value -> String.equal var_value value, Some env
let rec apply
?(matcher = (module Matchers.Alpha.Generic : Matchers.Matcher.S))
?(substitute_in_place = true)
?(fresh = counter)
?metasyntax
~(match_all:(?configuration:Configuration.t -> template:string -> source:string -> unit -> Match.t list))
predicates
env =
let open Option in
let (module Matcher) = matcher in
let equal_in_environment var value env =
match Environment.lookup env var with
| None -> false, Some env
| Some var_value -> String.equal var_value value, Some env
in
(* accepts only one expression *)
let rec rule_match ?(rewrite_context : rewrite_context option) env =
function
@ -79,14 +74,18 @@ let rec apply
let sat, env = rule_match env (Equal (left, right)) in
not sat, env
| Match (Variable variable, cases) ->
if debug then Format.printf "ENV: %s@." (Environment.to_string env);
let result =
Environment.lookup env variable >>= fun source ->
let evaluate template case_expression =
let configuration = match_configuration_of_syntax template in
Matcher.all ~configuration ~template ~source () |> function
| [] -> None
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
@ -138,7 +137,7 @@ let rec apply
let result =
Environment.lookup env variable >>= fun source ->
let configuration = Configuration.create ~match_kind:Fuzzy () in
let matches = Matcher.all ~configuration ~template ~source () in
let matches = match_all ~configuration ~template ~source () in
let source = if substitute_in_place then Some source else None in
let result = Rewrite.all ?metasyntax ?source ~rewrite_template matches in
match result with

View File

@ -1,12 +1,20 @@
module Configuration = Configuration
module Languages = Languages
module Metasyntax = Metasyntax
module Rule = Rule
module Evaluate = Evaluate
module Alpha = Engine.Make(Alpha.Make)
module Omega = Engine.Make(Omega.Make)
module Engine = Types.Engine
module Matcher = Types.Matcher
module Info = Types.Info
module Syntax = Types.Syntax
module Hole = Types.Hole
module Language = Types.Language
module Script = Script
module Specification = Specification
module Rewriter = Rewriter

View File

@ -1,12 +1,20 @@
module Configuration = Configuration
module Languages = Languages
module Metasyntax = Metasyntax
module Rule = Rule
module Evaluate = Evaluate
module Alpha : Types.Engine.S
module Omega : Types.Engine.S
module Engine = Types.Engine
module Matcher = Types.Matcher
module Info = Types.Info
module Syntax = Types.Syntax
module Hole = Types.Hole
module Language = Types.Language
module Script : module type of Script
module Specification : module type of Specification
module Rewriter = Rewriter

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@ let debug =
identifiers that contain -, etc. *)
let match_context_syntax =
let identifier = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" in
Matchers.Metasyntax.{ default_metasyntax with identifier }
Metasyntax.{ default_metasyntax with identifier }
let match_context_metasyntax =
Matchers.Metasyntax.(create match_context_syntax)
Metasyntax.(create match_context_syntax)
module Match_context_metasyntax = (val match_context_metasyntax)
module Match_context_template = Rewrite_template.Make(Match_context_metasyntax)
@ -69,10 +69,10 @@ let substitute_match_contexts ?fresh (matches: Match.t list) source replacements
*)
let substitute_in_rewrite_template
?fresh
?(metasyntax = Matchers.Metasyntax.default_metasyntax)
?(metasyntax = Metasyntax.default_metasyntax)
rewrite_template
({ environment; _ } : Match.t) =
let (module M) = Matchers.Metasyntax.create metasyntax in
let (module M) = Metasyntax.create metasyntax in
let module Template_parser = Rewrite_template.Make(M) in
let variables = Template_parser.variables rewrite_template in

View File

@ -2,7 +2,7 @@
emit result separated by newlines *)
val all
: ?source:string
-> ?metasyntax:Matchers.Metasyntax.t
-> ?metasyntax:Types.Metasyntax.t
-> ?fresh:(unit -> string)
-> rewrite_template:string
-> Match.t list

View File

@ -8,7 +8,10 @@ let debug =
| exception Not_found -> false
| _ -> true
type syntax = { variable: string; pattern: string }
type syntax =
{ variable: string
; pattern: string
}
[@@deriving sexp_of]
type extracted =
@ -16,7 +19,7 @@ type extracted =
| Constant of string
[@@deriving sexp_of]
module Make (Metasyntax : Matchers.Metasyntax.S) = struct
module Make (Metasyntax : Types.Metasyntax.S) = struct
let alphanum =
satisfy (function
@ -148,7 +151,7 @@ let sub_counter =
Format.sprintf "sub_%d" !uuid_for_sub_counter
let replacement_sentinel metasyntax =
let open Matchers.Metasyntax in
let open Types.Metasyntax in
List.find_map metasyntax.syntax ~f:(function
| Hole (Everything, Delimited (left, right)) ->
let left = Option.value left ~default:"" in
@ -162,7 +165,7 @@ let replacement_sentinel metasyntax =
| None -> failwith "A custom metasyntax must define syntax for an Everything hole or Regex to customize rewriting"
(** Parse the first :[id(label)] label encountered in the template. *)
let parse_first_label ?(metasyntax = Matchers.Metasyntax.default_metasyntax) template =
let parse_first_label ?(metasyntax = Metasyntax.default_metasyntax) template =
let label = take_while (function | '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' | '_' -> true | _ -> false) in
let left, right = replacement_sentinel metasyntax in
let parser =
@ -178,7 +181,7 @@ let parse_first_label ?(metasyntax = Matchers.Metasyntax.default_metasyntax) tem
| Error _ -> None
let substitute_fresh
?(metasyntax = Matchers.Metasyntax.default_metasyntax)
?(metasyntax = Metasyntax.default_metasyntax)
?(fresh = counter)
template =
let label_table = String.Table.create () in
@ -202,8 +205,8 @@ let substitute_fresh
done;
!template_ref
let substitute ?(metasyntax = Matchers.Metasyntax.default_metasyntax) ?fresh template env =
let (module M) = Matchers.Metasyntax.create metasyntax in
let substitute ?(metasyntax = Metasyntax.default_metasyntax) ?fresh template env =
let (module M) = Metasyntax.create metasyntax in
let module Template_parser = Make(M) in
let vars = Template_parser.variables template in
let template = substitute_fresh ~metasyntax ?fresh template in
@ -240,7 +243,7 @@ let of_match_context
in
let after_part = String.slice source end_index (String.length source) in
let hole_id = fresh () in
let left, right = replacement_sentinel Matchers.Metasyntax.default_metasyntax in
let left, right = replacement_sentinel Metasyntax.default_metasyntax in
let rewrite_template = String.concat [before_part; left; hole_id; right; after_part] in
hole_id, rewrite_template

View File

@ -1,4 +1,3 @@
open Matchers
open Match
type syntax = { variable: string; pattern: string }

235
lib/kernel/matchers/rule.ml Normal file
View File

@ -0,0 +1,235 @@
open Core_kernel
open Angstrom
module Ast = struct
type atom =
| Variable of string
| String of string
[@@deriving sexp]
type antecedent = atom
[@@deriving sexp]
type expression =
| True
| False
| Option of string
| Equal of atom * atom
| Not_equal of atom * atom
| Match of atom * (antecedent * consequent) list
| RewriteTemplate of string
| Rewrite of atom * (antecedent * expression)
and consequent = expression list
[@@deriving sexp]
let (=) left right = Equal (left, right)
let (<>) left right = Not_equal (left, right)
end
module Parser = struct
open Ast
let alphanum =
satisfy (function
| 'a' .. 'z'
| 'A' .. 'Z'
| '0' .. '9' -> true
| _ -> false)
let variable_parser =
(string Syntax.variable_left_delimiter
*> (many (alphanum <|> char '_') >>| String.of_char_list)
<* string Syntax.variable_right_delimiter)
(** Interpret escape sequences inside quotes *)
let char_token_s =
(char '\\' *> any_char >>|
function
| 'r' -> Char.to_string '\r'
| 'n' -> Char.to_string '\n'
| 't' -> Char.to_string '\t'
| '\\' -> Char.to_string '\\'
| c -> Format.sprintf {|\%c|} c)
<|> (any_char >>| String.of_char)
(** With escape sequences *)
let quote s =
(string s *> (many_till char_token_s (string s)))
>>| String.concat
let raw s =
(string s *> (many_till any_char (string s)))
>>| String.of_char_list
let quoted_parser =
choice [ quote {|"|}; quote {|'|}; raw {|`|} ]
let operator_parser =
choice
[ string Syntax.equal
; string Syntax.not_equal
]
let any_char_except ~reserved =
List.fold reserved
~init:(return `OK)
~f:(fun acc reserved_sequence ->
option `End_of_input
(peek_string (String.length reserved_sequence)
>>= fun s ->
if String.equal s reserved_sequence then
return `Reserved_sequence
else
acc))
>>= function
| `OK -> any_char
| `End_of_input -> any_char
| `Reserved_sequence -> fail "reserved sequence hit"
let value_parser ~reserved () =
match reserved with
| [] -> fail "no value allowed to scan here"
| reserved -> many (any_char_except ~reserved)
let map_special s =
if String.is_prefix s ~prefix:"~" then
Variable (Format.sprintf ":[%s]" s)
else if String.equal s "_" then
Variable ":[_]"
else
String s
let antecedent_parser ?(reserved = []) () =
choice
[ (quoted_parser >>| fun value -> String value)
; (value_parser ~reserved () >>| fun value -> map_special (String.of_char_list value))
]
let atom_parser () =
choice
[ (variable_parser >>| fun variable -> Variable variable)
; (quoted_parser >>| fun value -> String value)
; (value_parser ~reserved:[] () >>| fun value -> String (String.of_char_list value))
]
let rewrite_template_parser =
quoted_parser >>| fun value -> RewriteTemplate value
let ignore p =
p *> return ()
let make_equality_expression left operator right =
if String.equal operator Syntax.equal then
Equal (left, right)
else
Not_equal (left, right)
let is_whitespace = function
| ' ' | '\t' | '\r' | '\n' -> true
| _ -> false
let spaces =
take_while is_whitespace
let spaces1 =
satisfy is_whitespace *>
take_while is_whitespace *>
return ()
let optional_trailing c = option () (skip (Char.equal c))
let option_parser = spaces *> string Syntax.option_nested <* spaces >>| fun _ -> Option "nested"
let true' = lift (fun _ -> True) (spaces *> string Syntax.true' <* spaces)
let false' = lift (fun _ -> False) (spaces *> string Syntax.false' <* spaces)
(** <atom> [==, !=] <atom> *)
let operator_parser =
lift3
make_equality_expression
(spaces *> atom_parser ())
(spaces *> operator_parser)
(spaces *> atom_parser ())
<* spaces
let make_rewrite_expression atom match_template rewrite_template =
Rewrite (atom, (match_template, rewrite_template))
let make_match_expression atom cases =
Match (atom, cases)
(** rewrite <atom> { <atom> -> <atom> } *)
let rewrite_pattern_parser =
lift3
make_rewrite_expression
(string Syntax.start_rewrite_pattern *> spaces *> atom_parser () <* spaces <* char '{' <* spaces)
(antecedent_parser ~reserved:[" ->"] () <* spaces <* string Syntax.arrow <* spaces)
(spaces *> rewrite_template_parser <* spaces <* char '}' <* spaces)
(** <atom> -> atom [, <expr>], [,] *)
let match_arrow_parser expression_parser =
both
(antecedent_parser ~reserved:[" ->"] () <* spaces <* string Syntax.arrow <* spaces)
(spaces *> sep_by (char ',') expression_parser <* spaces <* optional_trailing ',' <* spaces)
(** [|] <match_arrow> *)
let first_case_parser expression_parser =
spaces *> option () (ignore @@ string Syntax.pipe_operator *> spaces) *>
match_arrow_parser expression_parser
(** | <match_arrow> *)
let case_parser expression_parser =
spaces *> string Syntax.pipe_operator *> spaces *>
match_arrow_parser expression_parser
(** [|] <match_arrow> | <match_arrow> *)
let case_block expression_parser =
first_case_parser expression_parser >>= fun case ->
many (case_parser expression_parser) >>= fun cases ->
return (case :: cases)
(** match <atom> { <case_parser> } *)
let match_pattern_parser expression_parser =
string Syntax.start_match_pattern *> spaces *>
lift2
make_match_expression
(atom_parser () <* spaces <* char '{' <* spaces)
(case_block expression_parser <* char '}' <* spaces)
let expression_parser =
fix (fun expression_parser ->
choice
[ match_pattern_parser expression_parser
; rewrite_pattern_parser
; operator_parser
; true'
; false'
; option_parser
])
(** where <expression> [,] *)
let parse =
spaces *> string Syntax.rule_prefix *>
spaces1 *> sep_by1 (spaces *> char ',' <* spaces) expression_parser
<* optional_trailing ','
<* spaces
let create rule =
match parse_string ~consume:All (parse <* end_of_input) rule with
| Ok rule -> Ok rule
| Error error -> Or_error.error_string error
end
type t = Ast.expression list
[@@deriving sexp]
type options =
{ nested : bool
}
let options rule =
List.fold rule ~init:{ nested = false } ~f:(fun acc -> function
| Ast.Option name when String.(name = Syntax.option_nested) -> { nested = true }
| _ -> acc)

View File

@ -1,9 +1,26 @@
open Core_kernel
open Angstrom
open Rule
open Parser
open Ast
open Script
type spec = Specification.t
[@@deriving sexp]
type op =
| And
| Or
| Not
[@@deriving sexp]
type exp =
| Exp of op * exp list
| Spec of spec
[@@deriving sexp]
type t = exp list
[@@deriving sexp]
let ignore p =
p *> return ()
@ -26,7 +43,7 @@ let spec =
(option None (spaces *> string Syntax.arrow *> spaces *> atom_parser () >>| fun x -> Some x))
in
match_rewrite_parser >>= fun (match_template_atom, rewrite_template_atom) ->
(option None (spaces1 *> Parser.parse >>| fun x -> Some x)) >>= fun rule ->
(option None (spaces1 *> parse >>| fun x -> Some x)) >>= fun rule ->
let match_template = Sexplib.Sexp.to_string_hum (sexp_of_atom match_template_atom) in
let rewrite_template =
match rewrite_template_atom with
@ -36,10 +53,10 @@ let spec =
return [(Spec (Specification.{ match_template; rule; rewrite_template }))]
let unop syntax exp_parser =
choice (List.map string syntax) *> spaces *> exp_parser >>| fun exp -> [Exp (Not, exp)]
choice (List.map ~f:string syntax) *> spaces *> exp_parser >>| fun exp -> [Exp (Not, exp)]
let binop syntax op =
spaces *> choice (List.map string syntax) *> spaces *> return (fun left right -> [Exp (op, left@right)])
spaces *> choice (List.map ~f:string syntax) *> spaces *> return (fun left right -> [Exp (op, left@right)])
let exp_parser =
fix (fun exp ->
@ -56,4 +73,4 @@ let parse script =
parse_string ~consume:All parser script
let to_string exp =
Sexplib.Sexp.to_string_hum (Script.sexp_of_t exp)
Sexplib.Sexp.to_string_hum (sexp_of_t exp)

View File

@ -0,0 +1,12 @@
open Core_kernel
type t =
{ match_template : string
; rule : Rule.t option
; rewrite_template : string option
}
[@@deriving sexp]
let create ?rewrite_template ?rule ~match_template () =
{ match_template; rule; rewrite_template }

View File

@ -0,0 +1,8 @@
type t =
{ match_template : string
; rule : Rule.t option
; rewrite_template : string option
}
[@@deriving sexp]
val create : ?rewrite_template:string -> ?rule:Rule.t -> match_template:string -> unit -> t

View File

@ -43,7 +43,6 @@ module Language = struct
end
end
type dimension =
| Code
| Escapable_string_literal
@ -119,6 +118,7 @@ module Matcher = struct
module type S = sig
val all
: ?configuration:Configuration.t
-> ?rule:Rule.t
-> ?nested: bool
-> template:string
-> source:string
@ -135,7 +135,6 @@ module Matcher = struct
include Info.S
val set_rewrite_template : string -> unit
end
end

View File

@ -1,6 +0,0 @@
(library
(name rewriter)
(public_name comby-kernel.rewriter)
(instrumentation (backend bisect_ppx))
(preprocess (pps ppx_deriving_yojson ppx_sexp_message ppx_sexp_conv))
(libraries comby-kernel.matchers comby-kernel.replacement core_kernel))

View File

@ -1,6 +1,8 @@
open Core
open Command.Let_syntax
open Comby_kernel
open Configuration
open Command_configuration
@ -74,7 +76,7 @@ let substitute_environment_only_and_exit metasyntax_path anonymous_arguments jso
Match.Environment.of_yojson json
|> function
| Ok environment ->
let substituted, _ = Rewriter.Rewrite_template.substitute ~metasyntax rewrite_template environment in
let substituted, _ = Matchers.Rewrite.substitute ~metasyntax rewrite_template environment in
Format.printf "%s@." substituted;
exit 0
| Error err ->

View File

@ -17,7 +17,6 @@ let timeout =
| None -> 30 (* seconds *)
| Some t -> Int.of_string t
let max_request_length =
match Sys.getenv "MAX_REQUEST_LENGTH" with
| None -> Int.max_value
@ -49,7 +48,7 @@ let perform_match request =
in
let run ?rule () =
let configuration = Matchers.Configuration.create ~match_kind:Fuzzy () in
let specification = Pipeline.Specification.create ~match_template ?rule () in
let specification = Matchers.Specification.create ~match_template ?rule () in
let matches =
Pipeline.execute
matcher
@ -87,10 +86,10 @@ let perform_rewrite request =
| Some matcher -> matcher
| None -> (module Matchers.Alpha.Generic)
in
let source_substitution, substitute_in_place =
let source_substitution =
match substitution_kind with
| "newline_separated" -> None, false
| "in_place" | _ -> Some source, true
| "newline_separated" -> None
| "in_place" | _ -> Some source
in
let default =
Out.Rewrite.to_string
@ -101,11 +100,10 @@ let perform_rewrite request =
in
let run ?rule () =
let configuration = Configuration.create ~match_kind:Fuzzy () in
let specification = Pipeline.Specification.create ~match_template ?rule () in
let specification = Matchers.Specification.create ~match_template ?rule () in
let matches =
Pipeline.execute
matcher
~substitute_in_place
~configuration
(String source)
specification
@ -113,8 +111,8 @@ let perform_rewrite request =
| Matches (m, _) -> m
| _ -> []
in
Rewrite.all matches ?source:source_substitution ~rewrite_template
|> Option.value_map ~default ~f:(fun Replacement.{ rewritten_source; in_place_substitutions } ->
Comby_kernel.Matchers.Rewrite.all matches ?source:source_substitution ~rewrite_template
|> Option.value_map ~default ~f:(fun Comby_kernel.Replacement.{ rewritten_source; in_place_substitutions } ->
Out.Rewrite.to_string
{ rewritten_source
; in_place_substitutions
@ -143,7 +141,7 @@ let perform_environment_substitution request =
let code, result =
200,
Out.Substitution.to_string
{ result = fst @@ Rewrite.substitute rewrite_template environment
{ result = fst @@ Comby_kernel.Matchers.Rewrite.substitute rewrite_template environment
; id
}
in

View File

@ -1,6 +1,6 @@
open Core
open Comby
open Comby_kernel
open Match
module In = struct

View File

@ -1,5 +1,7 @@
open Core
open Comby_kernel
let configuration = Matchers.Configuration.create ~match_kind:Fuzzy ()
let create syntax =
@ -144,10 +146,7 @@ let%expect_test "custom_metasyntax_rewrite" =
let metasyntax = Matchers.Metasyntax.{ syntax; identifier = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_" } in
let matcher = Option.value_exn (Matchers.Alpha.select_with_extension ~metasyntax ".go") in
(* KNOWN LIMITATION/BUG: if ? is a prefix it conflicts with ? optional syntax
for variable names and substitution. Expect should be ?bar here. Remove
optional syntax. *)
let specification = Configuration.Specification.create ~match_template:"$A(?B)" ~rewrite_template:"??B -> $A$A" () in
let specification = Matchers.Specification.create ~match_template:"$A(?B)" ~rewrite_template:"??B -> $A$A" () in
let result = Pipeline.execute matcher ~metasyntax (String "simple(bar)") specification in
let output = match result with
| Replacement (_, result, _) -> result
@ -157,7 +156,7 @@ let%expect_test "custom_metasyntax_rewrite" =
print_string output;
[%expect_exact {|bar -> simplesimple|}];
let specification = Configuration.Specification.create ~match_template:"$A(?B)" ~rewrite_template:"$id() $id(a) $id(a)" () in
let specification = Matchers.Specification.create ~match_template:"$A(?B)" ~rewrite_template:"$id() $id(a) $id(a)" () in
let result = Pipeline.execute matcher ~metasyntax (String "simple(bar)") specification in
let output = match result with
| Replacement (_, result, _) -> result

View File

@ -7,8 +7,6 @@
test_cli_helper
test_script
test_extract_regex
test_alpha
test_omega
test_cli
test_cli_list
test_statistics
@ -17,57 +15,23 @@
test_rewrite_parts
test_parse_rewrite_template
test_substitute
test_rewrite_rule_alpha
test_rewrite_rule_omega
test_integration_alpha
test_integration_omega
test_match_rule_alpha
test_match_rule_omega
test_python_string_literals_alpha
test_python_string_literals_omega
test_hole_extensions_alpha
test_hole_extensions_omega
test_generic_alpha
test_generic_omega
test_string_literals_alpha
test_string_literals_omega
test_c_style_comments_alpha
test_c_style_comments_omega
test_nested_comments_alpha
test_nested_comments_omega
test_c_alpha
test_c_omega
test_bash_alpha
test_bash_omega
test_go_alpha
test_go_omega
test_c_separators_alpha
test_c_separators_omega
test_pipeline_alpha
test_pipeline_omega
test_user_defined_language_alpha
test_user_defined_language_omega
test_nested_matches_alpha
test_nested_matches_omega
test_regex_holes_alpha
test_regex_holes_omega
test_rewrite_rule
test_integration
test_match_rule
test_python_string_literals
test_hole_extensions
test_generic
test_string_literals
test_c_style_comments
test_nested_comments
test_c
test_bash
test_go
test_c_separators
test_pipeline
test_user_defined_language
test_nested_matches
test_regex_holes
)
(inline_tests)
(preprocess (pps ppx_expect ppx_sexp_message ppx_deriving_yojson))

View File

@ -1,2 +0,0 @@
include Matchers.Alpha
module Rule = Language.Rule

View File

@ -1,24 +1,11 @@
open Core
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
open Test_alpha
let run_bash source match_template rewrite_template =
Bash.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let run_go source match_template rewrite_template =
Go.first ~configuration match_template source
let run (module M: Matchers.Matcher.S) source match_template rewrite_template =
M.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
@ -45,11 +32,17 @@ let%expect_test "custom_long_delimiters" =
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run_bash source match_template rewrite_template;
run (module Alpha.Bash) source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac
|}];
run (module Omega.Bash) source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac
|}]
let%expect_test "custom_long_delimiters_doesn't_work_in_go" =
let source =
{|
@ -67,7 +60,17 @@ let%expect_test "custom_long_delimiters_doesn't_work_in_go" =
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run_go source match_template rewrite_template;
run (module Alpha.Go) source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac
case
block 2
esac
esac
|}];
run (module Omega.Go) source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac

View File

@ -1,78 +0,0 @@
open Core
open Rewriter
open Test_helpers
open Test_omega
let run_bash source match_template rewrite_template =
Bash.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let run_go source match_template rewrite_template =
Go.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let%expect_test "custom_long_delimiters" =
let source =
{|
case
case
block 1
esac
case
block 2
esac
esac
|}
in
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run_bash source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac
|}]
let%expect_test "custom_long_delimiters_doesn't_work_in_go" =
let source =
{|
case
case
block 1
esac
case
block 2
esac
esac
|}
in
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run_go source match_template rewrite_template;
[%expect_exact {|
case nuked blocks esac
case
block 2
esac
esac
|}]

View File

@ -1,13 +1,11 @@
open Core
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
open Test_alpha
let run source match_template rewrite_template =
C.first ~configuration match_template source
let run (module E : Engine.S) source match_template rewrite_template =
E.C.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
@ -22,7 +20,9 @@ let%expect_test "comments_1" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|expect|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_2" =
@ -30,7 +30,9 @@ let%expect_test "comments_2" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|expect|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_3" =
@ -38,7 +40,9 @@ let%expect_test "comments_3" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|expect|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_4" =
@ -46,7 +50,9 @@ let%expect_test "comments_4" =
let match_template = {|match this :[1]end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|expect|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_5" =
@ -54,7 +60,9 @@ let%expect_test "comments_5" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|expect|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_6" =
@ -62,7 +70,9 @@ let%expect_test "comments_6" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|nothing matches|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_7" =
@ -70,7 +80,9 @@ let%expect_test "comments_7" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|nothing matches|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_8" =
@ -78,7 +90,9 @@ let%expect_test "comments_8" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|nothing matches|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_9" =
@ -86,7 +100,9 @@ let%expect_test "comments_9" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do (b)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do (b)|}]
let%expect_test "comments_10" =
@ -94,7 +110,9 @@ let%expect_test "comments_10" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do ()|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do ()|}]
let%expect_test "comments_11" =
@ -102,5 +120,7 @@ let%expect_test "comments_11" =
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|do (b) /* don't match this (a) end */|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|do (b) /* don't match this (a) end */|}]

View File

@ -1,106 +0,0 @@
open Core
open Rewriter
open Test_helpers
open Test_omega
let run source match_template rewrite_template =
C.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let%expect_test "comments_1" =
let source = {|match this /**/ expect end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_2" =
let source = {|match this /* */ expect end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_3" =
let source = {|match this /* blah blah */ expect /**/ end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_4" =
let source = {|match this expect/**/end|} in
let match_template = {|match this :[1]end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_5" =
let source = {|match this expect /**/end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|expect|}]
let%expect_test "comments_6" =
let source = {|/* don't match this (a) end */|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_7" =
let source = {|/* don't match /**/ this (a) end */|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_8" =
let source = {|(/* don't match this (a) end */)|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|nothing matches|} in
run source match_template rewrite_template;
[%expect_exact {|nothing matches|}]
let%expect_test "comments_9" =
let source = {|/* don't match this (a) end */ do match this (b) end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do (b)|}]
let%expect_test "comments_10" =
let source = {|/* don't match this (a) end */ do match this () end|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|/* don't match this (a) end */ do ()|}]
let%expect_test "comments_11" =
let source = {|do match this (b) end /* don't match this (a) end */|} in
let match_template = {|match this :[1] end|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|do (b) /* don't match this (a) end */|}]

View File

@ -1,13 +1,11 @@
open Core
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_omega
let run source match_template rewrite_template =
C.first ~configuration match_template source
let run (module E : Engine.S) source match_template rewrite_template =
E.C.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
@ -21,17 +19,23 @@ let%expect_test "whitespace_should_not_matter_between_separators" =
let source = {|*p|} in
let match_template = {|*:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|p|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|p|}];
let source = {|* p|} in
let match_template = {|*:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {| p|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {| p|}];
let source = {|* p|} in
let match_template = {|* :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|p|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|p|}]

View File

@ -1,37 +0,0 @@
open Core
open Rewriter
open Test_helpers
include Test_alpha
let run source match_template rewrite_template =
C.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let%expect_test "whitespace_should_not_matter_between_separators" =
let source = {|*p|} in
let match_template = {|*:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|p|}];
let source = {|* p|} in
let match_template = {|*:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {| p|}];
let source = {|* p|} in
let match_template = {|* :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|p|}]

View File

@ -1,24 +1,27 @@
open Core
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_omega
let match_all ?(configuration = configuration) (module E : Engine.S) template source =
E.C.all ~configuration ~template ~source ()
let all ?(configuration = configuration) template source =
C.all ~configuration ~template ~source ()
let all ?(configuration = configuration) engine template source rewrite_template =
match_all ~configuration engine template source
|> (fun matches ->
Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let%expect_test "rewrite_comments_1" =
let template = "replace this :[1] end" in
let source = "/* don't replace this () end */ do replace this () end" in
let rewrite_template = "X" in
all template source
|> (fun matches ->
Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact "/* don't replace this () end */ do X"];
all (module Omega) template source rewrite_template;
[%expect_exact "/* don't replace this () end */ do X"]
let%expect_test "rewrite_comments_2" =
@ -45,20 +48,54 @@ let%expect_test "rewrite_comments_2" =
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|
if (real_condition_body_must_be_empty) {}
|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|
if (real_condition_body_must_be_empty) {}
|}]
let%expect_test "capture_comments" =
let template = {|if (:[1]) { :[2] }|} in
let source = {|if (true) { /* some comment */ console.log(z); }|} in
let matches = all template source in
print_matches matches;
match_all (module Alpha) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 48, "line": 1, "column": 49 }
},
"environment": [
{
"variable": "1",
"value": "true",
"range": {
"start": { "offset": 4, "line": 1, "column": 5 },
"end": { "offset": 8, "line": 1, "column": 9 }
}
},
{
"variable": "2",
"value": "console.log(z);",
"range": {
"start": { "offset": 31, "line": 1, "column": 32 },
"end": { "offset": 46, "line": 1, "column": 47 }
}
}
],
"matched": "if (true) { /* some comment */ console.log(z); }"
}
]|}];
match_all (module Omega) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -87,6 +124,7 @@ let%expect_test "capture_comments" =
}
]|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
@ -105,15 +143,19 @@ let%expect_test "single_quote_in_comment" =
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|
{test}
|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|
{test}
|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
@ -136,10 +178,18 @@ let%expect_test "single_quote_in_comment" =
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|
{
a = 1;
/* Events with mask == AE_NONE are not set. So let's initiaize the
* vector with it. */
for (i = 0; i < setsize; i++)
}
|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|
{
@ -150,6 +200,7 @@ let%expect_test "single_quote_in_comment" =
}
|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
@ -171,10 +222,17 @@ let%expect_test "single_quote_in_comment" =
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|
{
a = 1;
/* ' */
for (i = 0; i < setsize; i++)
}
|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|
{
@ -184,6 +242,7 @@ let%expect_test "single_quote_in_comment" =
}
|}]
let%expect_test "give_back_the_comment_characters_for_newline_comments_too" =
let template =
{| {:[1]} |}
@ -203,10 +262,15 @@ let%expect_test "give_back_the_comment_characters_for_newline_comments_too" =
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|
{
// a comment
}
|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|
{
@ -214,6 +278,7 @@ let%expect_test "give_back_the_comment_characters_for_newline_comments_too" =
}
|}]
let%expect_test "comments_in_templates_imply_whitespace" =
let template =
{|
@ -235,9 +300,9 @@ a
{|erased|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
all (module Alpha) template source rewrite_template;
[%expect_exact
{|erased|}];
all (module Omega) template source rewrite_template;
[%expect_exact
{|erased|}]

View File

@ -1,243 +0,0 @@
open Core
open Rewriter
open Test_helpers
include Test_alpha
let all ?(configuration = configuration) template source =
C.all ~configuration ~template ~source ()
let%expect_test "rewrite_comments_1" =
let template = "replace this :[1] end" in
let source = "/* don't replace this () end */ do replace this () end" in
let rewrite_template = "X" in
all template source
|> (fun matches ->
Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "/* don't replace this () end */ do X"]
let%expect_test "rewrite_comments_2" =
let template =
{|
if (:[1]) { :[2] }
|}
in
let source =
{|
/* if (fake_condition_body_must_be_non_empty) { fake_body; } */
// if (fake_condition_body_must_be_non_empty) { fake_body; }
if (real_condition_body_must_be_empty) {
int i;
int j;
}
|}
in
let rewrite_template =
{|
if (:[1]) {}
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|
if (real_condition_body_must_be_empty) {}
|}]
let%expect_test "capture_comments" =
let template = {|if (:[1]) { :[2] }|} in
let source = {|if (true) { /* some comment */ console.log(z); }|} in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 48, "line": 1, "column": 49 }
},
"environment": [
{
"variable": "1",
"value": "true",
"range": {
"start": { "offset": 4, "line": 1, "column": 5 },
"end": { "offset": 8, "line": 1, "column": 9 }
}
},
{
"variable": "2",
"value": "console.log(z);",
"range": {
"start": { "offset": 31, "line": 1, "column": 32 },
"end": { "offset": 46, "line": 1, "column": 47 }
}
}
],
"matched": "if (true) { /* some comment */ console.log(z); }"
}
]|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
in
let source =
{|
/*'*/
{test}
|}
in
let rewrite_template =
{|
{:[1]}
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|
{test}
|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
in
let source =
{|
{
a = 1;
/* Events with mask == AE_NONE are not set. So let's initiaize the
* vector with it. */
for (i = 0; i < setsize; i++)
}
|}
in
let rewrite_template =
{|
{:[1]}
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|
{
a = 1;
/* Events with mask == AE_NONE are not set. So let's initiaize the
* vector with it. */
for (i = 0; i < setsize; i++)
}
|}]
let%expect_test "single_quote_in_comment" =
let template =
{| {:[1]} |}
in
let source =
{|
{
a = 1;
/* ' */
for (i = 0; i < setsize; i++)
}
|}
in
let rewrite_template =
{|
{:[1]}
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|
{
a = 1;
/* ' */
for (i = 0; i < setsize; i++)
}
|}]
let%expect_test "give_back_the_comment_characters_for_newline_comments_too" =
let template =
{| {:[1]} |}
in
let source =
{|
{
// a comment
}
|}
in
let rewrite_template =
{|
{:[1]}
|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|
{
// a comment
}
|}]
let%expect_test "comments_in_templates_imply_whitespace" =
let template =
{|
/* f */
// q
a
|}
in
let source =
{|
// idgaf
/* fooo */
a
|}
in
let rewrite_template =
{|erased|}
in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact
{|erased|}]

View File

@ -1252,7 +1252,7 @@ let%expect_test "test_custom_metasyntax_partial_rule_support" =
let command = Format.sprintf "%s %s" binary_path command_args in
let result = read_expect_stdin_and_stdout command source in
print_string result;
[%expect "a b"]
[%expect "$C b"]
let%expect_test "test_custom_metasyntax_reserved_identifiers" =
let source = "fun f -> (fun x -> f (x x)) (fun x -> f (x x))" in

View File

@ -1,10 +1,10 @@
open Core
open Configuration
open Comby
let%expect_test "basic" =
let match_template = "for :[i], :[x] := range :[list] {:[body]}" in
let spec = Specification.create ~match_template () in
let result = Specification.to_regex spec in
let spec = Matchers.Specification.create ~match_template () in
let result = Regex.to_regex spec in
print_string result;
[%expect_exact {|(for\s+)(\n|.)*?(,\s+)(\n|.)*?(\s+:=\s+range\s+)(\n|.)*?(\s+\{)(\n|.)*?(\})|}];

View File

@ -1,14 +1,11 @@
open Core
open Matchers
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_alpha
let run ?(configuration = configuration) source match_template rewrite_template =
Generic.first ~configuration match_template source
let run (module E : Engine.S) ?(configuration = configuration) source match_template rewrite_template =
E.Generic.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
@ -19,8 +16,7 @@ let run ?(configuration = configuration) source match_template rewrite_template
(* this is too annoying to fix every time the grammar changes. *)
print_string ""
let run_all ?(m = (module Generic : Matchers.Matcher.S)) ?(configuration = configuration) source match_template rewrite_template =
let (module M) = m in
let run_all (module M : Matchers.Matcher.S) ?(configuration = configuration) source match_template rewrite_template =
M.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
@ -29,332 +25,446 @@ let run_all ?(m = (module Generic : Matchers.Matcher.S)) ?(configuration = confi
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let run_match (module M : Matchers.Matcher.S) source match_template =
M.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string (Yojson.Safe.to_string (Match.to_yojson hd))
let%expect_test "basic" =
let source = {|a b c d|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b c d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b c d|}];
let source = {|a b c d|} in
let match_template = {|a :[1] c d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b|}];
let source = {|a b c d|} in
let match_template = {|a :[1] d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b c|}];
let source = {|a b c d|} in
let match_template = {|a :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b c d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b c d|}];
let source = {|a b c d|} in
let match_template = {|:[1] c d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|a b c d|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
let source = {|a b c d|} in
let match_template = {|:[2] :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] :[1] d|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(b) (c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(b) (c)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(b) (c d)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(b) (c d)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] c :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(b) (d)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(b) (d)|}];
let source = {|x:|} in
let match_template = {|:[1]:|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|x|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|x|}]
let%expect_test "basic_failures" =
let source = {|a x b bbq|} in
let match_template = {|a :[1] b c|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {||}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {||}];
let source = {|a b c d|} in
let match_template = {|a :[2] d :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact
{||}];
run (module Omega) source match_template rewrite_template;
[%expect_exact
{||}];
let source = {|a b c d|} in
let match_template = {|a :[2] b :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {||}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {||}]
let%expect_test "delimiter_matching" =
let source = {|foo(bar)|} in
let match_template = {|:[1](bar)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|foo|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|foo|}];
let source = {|(a b c) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b c|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b c|}];
let source = {|(a b c) d|} in
let match_template = {|(:[1] b :[2]) d|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
let source = {|q(a b c) d|} in
let match_template = {|q(:[1] b :[2]) d|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
let source = {|((a) b)|} in
let match_template = {|(:[1] b)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a)|}];
let source = {|((a b c)) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
let source = {|((a b c)) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
let source = {|((a b c) q) d|} in
let match_template = {|((:[1]) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b c|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b c|}];
let source = {|((a b c) q) d|} in
let match_template = {|((:[1] c) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|((a b () c) q) d|} in
let match_template = {|((:[1] () c) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|((a ((x) d) b c)) d|} in
let match_template = {|((a :[1] :[2] c)) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|((x) d)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|((x) d)|}];
let source = {|((a ((x) d) b c)) d|} in
let match_template = {|((a (:[1]) :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(x) d b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(x) d b|}];
let source = {|(b (c) d)|} in
let match_template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
let source = {|(b (c) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
let source = {|(b (c.) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b (c.) d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b (c.) d|}];
let source = {|(b. (c) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b. (c) d|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b. (c) d|}];
let source = {|(b (c) d.)|} in
let match_template = {|(b :[1] d.)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(c)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(c)|}];
let source = {|outer(inner(dst,src),src)|} in
let match_template = {|outer(:[1],src)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|inner(dst,src)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|inner(dst,src)|}];
let source = {|(b ((c)) d.)|} in
let match_template = {|(b :[1] d.)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|((c))|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|((c))|}];
let source = {|a b c|} in
let match_template = {|a :[1] c|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|b|}];
let source = {|x = foo;|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|foo|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|foo|}];
let source = {|((a {{x} d} b c)) d|} in
let match_template = {|((a {:[1] d} :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|{x} b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|{x} b|}];
let source = {|((a {([{x}]) d} b c)) d|} in
let match_template = {|((a {:[1] d} :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|([{x}]) b|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|([{x}]) b|}];
let source = {|(((((x)))))|} in
let match_template = {|(((:[1])))|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|((x))|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|((x))|}];
let source = {|((((y(x)z))))|} in
let match_template = {|(((:[1])))|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(y(x)z)|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(y(x)z)|}];
let source = {|((((y(x)z))))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(y(x)z) |}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(y(x)z) |}];
let source = {|(((x)z))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|x z|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|x z|}];
let source = {|((((x))z))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|(x) z|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|(x) z|}];
let source = {|lolwtfbbq|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|wtf|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|wtf|}];
let source = {|x = foo; x = bar;|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|foo x = bar;|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|foo x = bar;|}];
let source = {|[ no match prefix ] x = foo; [ no match suffix ]|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|[ no match prefix ] foo [ no match suffix ]|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|[ no match prefix ] foo [ no match suffix ]|}];
let source = {|x = a; x = b; x = c|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|a x = b; x = c|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|a x = b; x = c|}];
let source = {|x = ( x = x; );|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|( x = x; )|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|( x = x; )|}];
let source = {|( x = x = x; )|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|( x = x )|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|( x = x )|}];
let source = {|xxx a b d c 1 2 3 b d d blah|} in
let match_template = {|a :[1] c :[2] d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|xxx b d 1 2 3 b d blah|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|xxx b d 1 2 3 b d blah|}];
let source = {|howevenlolwtfbbqispossible|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|howevenwtfispossible|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|howevenwtfispossible|}];
let source = {|lolhowevenlolwtfbbqispossiblebbq|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|howevenlolwtfispossiblebbq|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|howevenlolwtfispossiblebbq|}];
let source = {|hello my name is bob the builder|} in
let match_template = {|:[alongidentifiername] :[2] :[3] :[xyz] :[5] :[6]|} in
let rewrite_template = {|:[alongidentifiername] :[2] :[3] :[xyz] :[5] :[6]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|hello my name is bob the builder|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|hello my name is bob the builder|}];
let source = {|www.testdofooname.com/picsinsideit/stunningpictureofkays1381737242g8k4n-280x428.jpg|} in
let match_template = {|www.:[1]-:[2].jpg|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|testdofooname.com/picsinsideit/stunningpictureofkays1381737242g8k4n 280x428|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|testdofooname.com/picsinsideit/stunningpictureofkays1381737242g8k4n 280x428|}];
let source = {|https://api.github.com/repos/dmjacobsen/slurm/commits/716c1499695c68afcab848a1b49653574b4fc167|} in
let match_template = {|:[1]api.:[2]/repos/:[3]s/:[4]|} in
let rewrite_template = {|:[1] :[2] :[3] :[4]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|https:// github.com dmjacobsen/slurm/commit 716c1499695c68afcab848a1b49653574b4fc167|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|https:// github.com dmjacobsen/slurm/commit 716c1499695c68afcab848a1b49653574b4fc167|}];
let source =
@ -369,7 +479,12 @@ let%expect_test "delimiter_matching" =
in
let match_template = {|memcpy(:[1], :[2], :[3]);|} in
let rewrite_template = {|:[1], :[2], :[3]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|assert(stream->md_len + md_len -
si.foo_data_begin <= MAD_BUFFER_MDLEN);
*stream->foo_data + stream->md_len, mad_bit_nextbyte(&stream->ptr), frame_used = md_len - si.foo_data_begin
stream->md_len += frame_used;|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|assert(stream->md_len + md_len -
si.foo_data_begin <= MAD_BUFFER_MDLEN);
*stream->foo_data + stream->md_len, mad_bit_nextbyte(&stream->ptr), frame_used = md_len - si.foo_data_begin
@ -382,7 +497,9 @@ let%expect_test "significant_whitespace" =
let source = {|two spaces|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|two spaces|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|two spaces|}];
(* FIXME: this should fail. also test case where separators do or do not need
@ -391,46 +508,48 @@ let%expect_test "significant_whitespace" =
let source = {|two spaces|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|two spaces|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|two spaces|}]
let%expect_test "contextual_matching" =
let run = run_all in
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[1], :[2], :[3])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run_all (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}];
run_all (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}];
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[1], :[2], :[3])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run_all (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}];
run_all (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}]
let%expect_test "contextual_matching_with_short_hole_syntax" =
let run = run_all in
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[[1]], :[2], :[3])|} in
let rewrite_template = {|:[[1]]|} in
run source match_template rewrite_template;
run_all (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}];
run_all (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}]
let%expect_test "trivial_empty_case" =
let source = "" in
let match_template = "" in
begin
Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string (Yojson.Safe.to_string (Match.to_yojson hd))
end;
run_match (module Alpha.Generic) source match_template;
[%expect_exact {|{"range":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":0,"line":1,"column":1}},"environment":[],"matched":""}|}];
run_match (module Omega.Generic) source match_template;
[%expect_exact {|{"range":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":0,"line":1,"column":1}},"environment":[],"matched":""}|}]
let%expect_test "test_top_level_hole_stops_at_newline" =
let%expect_test "test_top_level_hole_stops_at_newline_false_implies_default_generic" =
let source =
{|
a = b
@ -449,8 +568,9 @@ let%expect_test "test_top_level_hole_stops_at_newline" =
in
let match_template = ":[1] = :[2]" in
let rewrite_template = "line" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = false } in
run_all ~configuration source match_template rewrite_template;
let configuration = Configuration.create ~match_newline_toplevel:false () in
run_all (module Alpha.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|
line
line
@ -464,80 +584,14 @@ line
line
)
line
|}]
|}];
let%expect_test "test_top_level_hole_stops_at_newline_for_example" =
let source =
{|
for i, x := range derp {
do not match
}
for i, x := range derp {
do match
}
|}
in
let match_template = "for i, x := :[_] { do match }" in
let rewrite_template = "erased" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = false } in
run_all ~configuration source match_template rewrite_template;
[%expect_exact {|
for i, x := range derp {
do not match
}
erased
|}]
let%expect_test "test_top_level_hole_stops_at_newline_for_example" =
let source =
{|
for i, x := range derp {
do not match
}
for i, x := range derp {
do match
}
|}
in
let match_template = "for i, x := :[_] { do match }" in
let rewrite_template = "erased" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = false } in
run_all ~configuration source match_template rewrite_template;
[%expect_exact {|
for i, x := range derp {
do not match
}
erased
|}]
let%expect_test "test_top_level_hole_stops_at_newline_false" =
let source =
{|
a = b
c = d
(
e = f
(
g = h
i = j
)
k = l
m = n
)
o = p
|}
in
let match_template = ":[1] = :[2]" in
let rewrite_template = "line" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = true } in
run_all ~configuration source match_template rewrite_template;
(* Unimplemented: Does not stop at newline *)
run_all (module Omega.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|line|}]
let%expect_test "test_top_level_hole_stops_at_newline_for_example_false" =
let%expect_test "test_top_level_hole_stops_at_newline_for_example_generic_go_false" =
let source =
{|
for i, x := range derp {
@ -551,13 +605,24 @@ let%expect_test "test_top_level_hole_stops_at_newline_for_example_false" =
in
let match_template = "for i, x := :[_] { do match }" in
let rewrite_template = "erased" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = true } in
run_all ~configuration source match_template rewrite_template;
let configuration = Configuration.create ~match_newline_toplevel:false () in
run_all (module Alpha.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|
for i, x := range derp {
do not match
}
erased
|}];
(* Unimplemented: Does not stop at newline *)
run_all (module Omega.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|
erased
|}]
let%expect_test "test_top_level_hole_stops_at_newline_for_example_false" =
let%expect_test "test_top_level_hole_stops_at_newline_for_example_generic_go_true" =
let source =
{|
for i, x := range derp {
@ -571,12 +636,44 @@ let%expect_test "test_top_level_hole_stops_at_newline_for_example_false" =
in
let match_template = "for i, x := :[_] { do match }" in
let rewrite_template = "erased" in
let configuration = { (Configuration.create ()) with match_newline_toplevel = true } in
run_all ~configuration source match_template rewrite_template;
let configuration = Configuration.create ~match_newline_toplevel:true () in
run_all (module Alpha.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|
erased
|}];
run_all (module Omega.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|
erased
|}]
let%expect_test "test_top_level_hole_stops_at_newline_generic_true" =
let source =
{|
a = b
c = d
(
e = f
(
g = h
i = j
)
k = l
m = n
)
o = p
|}
in
let match_template = ":[1] = :[2]" in
let rewrite_template = "line" in
let configuration = Configuration.create ~match_newline_toplevel:true () in
run_all (module Alpha.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|line|}];
run_all (module Omega.Generic) ~configuration source match_template rewrite_template;
[%expect_exact {|line|}]
let%expect_test "test_top_level_hole_crosses_newlines_for_html_by_default" =
let source =
{|
@ -587,7 +684,16 @@ let%expect_test "test_top_level_hole_crosses_newlines_for_html_by_default" =
in
let match_template = "<foo>:[x]</foo>" in
let rewrite_template = ":[x]" in
run_all ~m:(module Matchers.Alpha.Html) ~configuration source match_template rewrite_template;
run_all (module Alpha.Html) ~configuration source match_template rewrite_template;
[%expect_exact {|
stuff
|}];
(* Unimplemented: Has no effect *)
run_all (module Omega.Html) ~configuration source match_template rewrite_template;
[%expect_exact {|
stuff

View File

@ -1,477 +0,0 @@
open Core
open Matchers
open Rewriter
open Test_helpers
include Test_omega
let run ?(configuration = configuration) source match_template rewrite_template =
Generic.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
| Error _ ->
(* this is too annoying to fix every time the grammar changes. *)
print_string ""
let run_all ?(configuration = configuration) source match_template rewrite_template =
Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| results ->
Option.value_exn (Rewrite.all ~source ~rewrite_template results)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let%expect_test "basic" =
let source = {|a b c d|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b c d|}];
let source = {|a b c d|} in
let match_template = {|a :[1] c d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b|}];
let source = {|a b c d|} in
let match_template = {|a :[1] d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b c|}];
let source = {|a b c d|} in
let match_template = {|a :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b c d|}];
let source = {|a b c d|} in
let match_template = {|:[1] c d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|a b c d|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
let source = {|a b c d|} in
let match_template = {|:[2] :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
[%expect_exact {|(a) (b c d)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] :[1] d|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
[%expect_exact {|(b) (c)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
[%expect_exact {|(b) (c d)|}];
let source = {|a b c d|} in
let match_template = {|a :[2] c :[1]|} in
let rewrite_template = {|(:[2]) (:[1])|} in
run source match_template rewrite_template;
[%expect_exact {|(b) (d)|}];
let source = {|x:|} in
let match_template = {|:[1]:|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|x|}]
let%expect_test "basic_failures" =
let source = {|a x b bbq|} in
let match_template = {|a :[1] b c|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {||}];
let source = {|a b c d|} in
let match_template = {|a :[2] d :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact
{||}];
let source = {|a b c d|} in
let match_template = {|a :[2] b :[1]|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {||}]
let%expect_test "delimiter_matching" =
let source = {|(a b c) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b c|}];
let source = {|(a b c) d|} in
let match_template = {|(:[1] b :[2]) d|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
let source = {|q(a b c) d|} in
let match_template = {|q(:[1] b :[2]) d|} in
let rewrite_template = {|(:[1]) (:[2])|} in
run source match_template rewrite_template;
[%expect_exact {|(a) (c)|}];
let source = {|((a) b)|} in
let match_template = {|(:[1] b)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|(a)|}];
let source = {|((a b c)) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
let source = {|((a b c)) d|} in
let match_template = {|(:[1]) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|(a b c)|}];
let source = {|((a b c) q) d|} in
let match_template = {|((:[1]) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b c|}];
let source = {|((a b c) q) d|} in
let match_template = {|((:[1] c) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|((a b () c) q) d|} in
let match_template = {|((:[1] () c) q) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a b|}];
let source = {|((a ((x) d) b c)) d|} in
let match_template = {|((a :[1] :[2] c)) d|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|((x) d)|}];
let source = {|((a ((x) d) b c)) d|} in
let match_template = {|((a (:[1]) :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|(x) d b|}];
let source = {|(b (c) d)|} in
let match_template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
let source = {|(b (c) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b (c) d|}];
let source = {|(b (c.) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b (c.) d|}];
let source = {|(b. (c) d.)|} in
let match_template = {|(:[1].)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b. (c) d|}];
let source = {|(b (c) d.)|} in
let match_template = {|(b :[1] d.)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|(c)|}];
let source = {|outer(inner(dst,src),src)|} in
let match_template = {|outer(:[1],src)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|inner(dst,src)|}];
let source = {|(b ((c)) d.)|} in
let match_template = {|(b :[1] d.)|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|((c))|}];
let source = {|a b c|} in
let match_template = {|a :[1] c|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|b|}];
let source = {|x = foo;|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|foo|}];
let source = {|((a {{x} d} b c)) d|} in
let match_template = {|((a {:[1] d} :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|{x} b|}];
let source = {|((a {([{x}]) d} b c)) d|} in
let match_template = {|((a {:[1] d} :[2] c)) d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|([{x}]) b|}];
let source = {|(((((x)))))|} in
let match_template = {|(((:[1])))|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|((x))|}];
let source = {|((((y(x)z))))|} in
let match_template = {|(((:[1])))|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|(y(x)z)|}];
let source = {|((((y(x)z))))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|(y(x)z) |}];
let source = {|(((x)z))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|x z|}];
let source = {|((((x))z))|} in
let match_template = {|(((:[1]):[2]))|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|(x) z|}];
let source = {|lolwtfbbq|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|wtf|}];
let source = {|x = foo; x = bar;|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|foo x = bar;|}];
let source = {|[ no match prefix ] x = foo; [ no match suffix ]|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|[ no match prefix ] foo [ no match suffix ]|}];
let source = {|x = a; x = b; x = c|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|a x = b; x = c|}];
let source = {|x = ( x = x; );|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|( x = x; )|}];
let source = {|( x = x = x; )|} in
let match_template = {|x = :[1];|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|( x = x )|}];
let source = {|xxx a b d c 1 2 3 b d d blah|} in
let match_template = {|a :[1] c :[2] d|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|xxx b d 1 2 3 b d blah|}];
let source = {|howevenlolwtfbbqispossible|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|howevenwtfispossible|}];
let source = {|lolhowevenlolwtfbbqispossiblebbq|} in
let match_template = {|lol:[1]bbq|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|howevenlolwtfispossiblebbq|}];
let source = {|hello my name is bob the builder|} in
let match_template = {|:[alongidentifiername] :[2] :[3] :[xyz] :[5] :[6]|} in
let rewrite_template = {|:[alongidentifiername] :[2] :[3] :[xyz] :[5] :[6]|} in
run source match_template rewrite_template;
[%expect_exact {|hello my name is bob the builder|}];
let source = {|www.testdofooname.com/picsinsideit/stunningpictureofkays1381737242g8k4n-280x428.jpg|} in
let match_template = {|www.:[1]-:[2].jpg|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|testdofooname.com/picsinsideit/stunningpictureofkays1381737242g8k4n 280x428|}];
let source = {|https://api.github.com/repos/dmjacobsen/slurm/commits/716c1499695c68afcab848a1b49653574b4fc167|} in
let match_template = {|:[1]api.:[2]/repos/:[3]s/:[4]|} in
let rewrite_template = {|:[1] :[2] :[3] :[4]|} in
run source match_template rewrite_template;
[%expect_exact {|https:// github.com dmjacobsen/slurm/commit 716c1499695c68afcab848a1b49653574b4fc167|}];
let source =
{|
assert(stream->md_len + md_len -
si.foo_data_begin <= MAD_BUFFER_MDLEN);
memcpy(*stream->foo_data + stream->md_len,
mad_bit_nextbyte(&stream->ptr),
frame_used = md_len - si.foo_data_begin);
stream->md_len += frame_used;
|} |> format
in
let match_template = {|memcpy(:[1], :[2], :[3]);|} in
let rewrite_template = {|:[1], :[2], :[3]|} in
run source match_template rewrite_template;
[%expect_exact {|assert(stream->md_len + md_len -
si.foo_data_begin <= MAD_BUFFER_MDLEN);
*stream->foo_data + stream->md_len, mad_bit_nextbyte(&stream->ptr), frame_used = md_len - si.foo_data_begin
stream->md_len += frame_used;|}]
let%expect_test "significant_whitespace" =
let configuration = Configuration.create ~match_kind:Fuzzy ~significant_whitespace:true () in
let run = run ~configuration in
let source = {|two spaces|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|two spaces|}];
(* FIXME: this should fail. also test case where separators do or do not need
whitespace. e.g., strict about strcpy(src,dst) matching a template
strcpy(:[1],:[2]) versus strcpy(:[1], :[2]) *)
let source = {|two spaces|} in
let match_template = {|:[1] :[2]|} in
let rewrite_template = {|:[1] :[2]|} in
run source match_template rewrite_template;
[%expect_exact {|two spaces|}]
let%expect_test "contextual_matching" =
let run = run_all in
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[1], :[2], :[3])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}];
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[1], :[2], :[3])|} in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}]
let%expect_test "contextual_matching_with_short_hole_syntax" =
let run = run_all in
let source = {|memcpy(dst1, src1, 1); memcpy(dst2, src2, 2);|} in
let match_template = {|memcpy(:[[1]], :[2], :[3])|} in
let rewrite_template = {|:[[1]]|} in
run source match_template rewrite_template;
[%expect_exact {|dst1; dst2;|}]
let%expect_test "trivial_empty_case" =
let source = "" in
let match_template = "" in
begin
Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string (Yojson.Safe.to_string (Match.to_yojson hd))
end;
[%expect_exact {|{"range":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":0,"line":1,"column":1}},"environment":[],"matched":""}|}]
let%expect_test "trivial_empty_case" =
let source = "" in
let match_template = "" in
begin
Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string (Yojson.Safe.to_string (Match.to_yojson hd))
end;
[%expect_exact {|{"range":{"start":{"offset":0,"line":1,"column":1},"end":{"offset":0,"line":1,"column":1}},"environment":[],"matched":""}|}]
let%expect_test "test_top_level_hole_stops_at_newline" =
let source =
{|
a = b
c = d
(
e = f
(
g = h
i = j
)
k = l
m = n
)
o = p
|}
in
let match_template = ":[1] = :[2]" in
let rewrite_template = "line" in
run_all source match_template rewrite_template;
[%expect_exact {|line|}]
let%expect_test "test_top_level_hole_stops_at_newline_for_example" =
let source =
{|
for i, x := range derp {
do not match
}
for i, x := range derp {
do match
}
|}
in
let match_template = "for i, x :[_] { do match }" in
let rewrite_template = "line" in
run_all source match_template rewrite_template;
[%expect_exact {|
line
|}]

View File

@ -1,18 +1,15 @@
open Core
open Match
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_alpha
let run ?(rule = "where true") source match_template rewrite_template =
let rule = Language.Rule.create rule |> Or_error.ok_exn in
Go.first ~configuration match_template source
let run ?(rule = "where true") (module E : Engine.S) source match_template rewrite_template =
let rule = Rule.create rule |> Or_error.ok_exn in
E.Go.first ~configuration match_template source
|> function
| Ok ({environment; _ } as result) ->
if Rule.(sat @@ apply rule environment) then
if Rule.(sat @@ apply ~match_all:(E.Go.all ~rule:[Ast.True] ~nested:false) rule environment) then
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
@ -47,12 +44,20 @@ let%expect_test "gosimple_s1000" =
:[3]
|}
in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|
x := <-ch
fmt.Println(x)
|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|
x := <-ch
fmt.Println(x)
|}]
let%expect_test "gosimple_s1001" =
let source =
{|
@ -78,7 +83,12 @@ let%expect_test "gosimple_s1001" =
let rule = {|where :[index_define] == :[index_use], :[src_element_define] == :[src_element_use]|} in
run ~rule source match_template rewrite_template;
run (module Alpha) ~rule source match_template rewrite_template;
[%expect_exact {|
copy(dst, src)
|}];
run (module Omega) ~rule source match_template rewrite_template;
[%expect_exact {|
copy(dst, src)
|}]
@ -98,5 +108,7 @@ let%expect_test "gosimple_s1003" =
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
run (module Alpha) source match_template rewrite_template;
[%expect_exact {|Index|}];
run (module Omega) source match_template rewrite_template;
[%expect_exact {|Index|}]

View File

@ -1,102 +0,0 @@
open Core
open Match
open Rewriter
open Test_helpers
include Test_omega
let run ?(rule = "where true") source match_template rewrite_template =
let rule = Language.Rule.create rule |> Or_error.ok_exn in
Go.first ~configuration match_template source
|> function
| Ok ({environment; _ } as result) ->
if Rule.(sat @@ apply rule environment) then
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
else
assert false
| Error _ ->
print_string rewrite_template
let%expect_test "gosimple_s1000" =
let source =
{|
select {
case x := <-ch:
fmt.Println(x)
}
|}
in
let match_template =
{|
select {
case :[1] := :[2]:
:[3]
}
|}
in
let rewrite_template =
{|
:[1] := :[2]
:[3]
|}
in
run source match_template rewrite_template;
[%expect_exact {|
x := <-ch
fmt.Println(x)
|}]
let%expect_test "gosimple_s1001" =
let source =
{|
for i, x := range src {
dst[i] = x
}
|}
in
let match_template =
{|
for :[index_define], :[src_element_define] := range :[src_array] {
:[dst_array][:[index_use]] = :[src_element_use]
}
|}
in
let rewrite_template =
{|
copy(:[dst_array], :[src_array])
|}
in
let rule = {|where :[index_define] == :[index_use], :[src_element_define] == :[src_element_use]|} in
run ~rule source match_template rewrite_template;
[%expect_exact {|
copy(dst, src)
|}]
let%expect_test "gosimple_s1003" =
let source =
{|
if strings.Index(x, y) != -1 { ignore }
|}
in
let match_template =
{|
if strings.:[1](x, y) != -1 { :[_] }
|}
in
let rewrite_template = {|:[1]|} in
run source match_template rewrite_template;
[%expect_exact {|Index|}]

View File

@ -1,8 +1,10 @@
open Core
open Rewriter
open Comby_kernel
let configuration = Matchers.Configuration.create ~match_kind:Fuzzy ()
open Matchers
let configuration = Configuration.create ~match_kind:Fuzzy ()
let format s =
let s = String.chop_prefix_exn ~prefix:"\n" s in
@ -28,11 +30,10 @@ let print_only_match matches =
let run ?(configuration = configuration) (module M : Matchers.Matcher.S) source match_template ?rule rewrite_template =
let rule =
match rule with
| Some rule -> Language.Rule.create rule |> Or_error.ok_exn
| None -> Language.Rule.create "where true" |> Or_error.ok_exn
| Some rule -> Matchers.Rule.create rule |> Or_error.ok_exn
| None -> Rule.create "where true" |> Or_error.ok_exn
in
M.all ~configuration ~template:match_template ~source ()
|> List.filter ~f:(fun { Match.environment; _ } -> Language.Rule.(sat @@ apply ~matcher:(module M) rule environment))
M.all ~rule ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| results ->
@ -51,7 +52,7 @@ let run_nested
match rule with
| None -> true
| Some rule ->
let options = Language.Rule.create rule |> Or_error.ok_exn |> Language.Rule.options in
let options = Rule.create rule |> Or_error.ok_exn |> Rule.options in
options.nested
in
M.all ~configuration ~nested ~template:match_template ~source ()
@ -63,10 +64,6 @@ let run_nested
|> print_string
(** Rule tests *)
let sat ?(env = Match.Environment.create ()) rule =
let rule = Language.Rule.create rule |> Or_error.ok_exn in
Format.sprintf "%b" (Language.Rule.(sat @@ apply rule env))
let make_env bindings =
List.fold bindings
~init:(Match.Environment.create ())

View File

@ -1,13 +1,11 @@
open Core
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_alpha
let run_all ?(configuration = configuration) source match_template rewrite_template =
Generic.all ~configuration ~template:match_template ~source ()
let run_all (module E : Engine.S) ?(configuration = configuration) source match_template rewrite_template =
E.Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| results ->
@ -16,23 +14,28 @@ let run_all ?(configuration = configuration) source match_template rewrite_templ
|> print_string
let%expect_test "non_space" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|:[x.]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {| {foo.} {foo.bar.quux} {derp}|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {| {foo.} {foo.bar.quux} {derp}|}]
let%expect_test "only_space" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|:[ x]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{ }foo.{ }foo.bar.quux{ }derp|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{ }foo.{ }foo.bar.quux{ }derp|}]
let%expect_test "up_to_newline" =
let run = run_all in
let source =
{|
foo.
@ -41,28 +44,42 @@ derp
|} in
let match_template = {|:[x\n]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{
}{foo.
}{foo.bar.quux
}{derp
}|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{
}{foo.
}{foo.bar.quux
}{derp
}|}]
let%expect_test "match_empty_in_newline_hole" =
let run = run_all in
let source =
{|stuff
after
|} in
let match_template = {|stuff:[x\n]|} in
let rewrite_template = {|{->:[x]<-}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{->
<-}after
|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{->
<-}after
|}]
let%expect_test "leading_indentation" =
let run = run_all in
let source =
{|
foo. bar bazz
@ -71,106 +88,149 @@ let%expect_test "leading_indentation" =
|} in
let match_template = {|:[ leading_indentation]:[rest\n]|} in
let rewrite_template = {|{:[leading_indentation]}:[rest]|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|
{ }foo. bar bazz
{ }foo.bar.quux
{ }derp
|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|
{ }foo. bar bazz
{ }foo.bar.quux
{ }derp
|}]
let%expect_test "non_space_partial_match" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|foo.:[x.]ux|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {| foo. {bar.qu} derp|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {| foo. {bar.qu} derp|}]
let%expect_test "non_space_does_not_match_reserved_delimiters" =
let run = run_all in
let source = {|fo.o(x)|} in
let match_template = {|:[f.]|} in
let rewrite_template = {|{:[f]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{fo.o}({x})|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{fo.o}({x})|}]
let%expect_test "non_space_only_hole" =
let run = run_all in
let source = {|a.b c.d|} in
let match_template = {|:[x.]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|>a.b< >c.d<|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|>a.b< >c.d<|}]
let%expect_test "alphanum_partial_match" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|foo.b:[x]r.quux|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {| foo. {a} derp|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {| foo. {a} derp|}]
let%expect_test "newline_matcher_should_not_be_sat_on_space" =
let run = run_all in
let source =
{|a b c d
e f g h|} in
let match_template = {|:[line\n] |} in
let rewrite_template = {|{:[line]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{a b c d
}e f g h|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{a b c d
}e f g h|}];
let run = run_all in
let source =
{|a b c d
e f g h|} in
let match_template = {|:[line\n]:[next]|} in
let rewrite_template = {|{:[line]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{a b c d
}|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{a b c d
}|}];
let run = run_all in
let source =
{|a b c d
e f g h
|} in
let match_template = {|:[line1\n]:[next\n]|} in
let rewrite_template = {|{:[line1]|:[next]}|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|{a b c d
|e f g h
}|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|{a b c d
|e f g h
}|}]
let%expect_test "implicit_equals" =
let run = run_all in
let source = {|a b a|} in
let match_template = {|:[[x]] :[[m]] :[[x]]|} in
let rewrite_template = {|:[m]|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|b|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|b|}]
let%expect_test "implicit_equals_does_not_apply_to_underscore" =
let run = run_all in
let source = {|a b c|} in
let match_template = {|:[[x]] :[[_]] :[[_]]|} in
let rewrite_template = {|:[x]|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|a|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|a|}]
let%expect_test "expression_hole" =
let run = run_all in
let source = {|(b, c, d) [ ] { { } } { } ()()|} in
let match_template = {|:[x:e]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|>(b, c, d)< >[ ]< >{ { } }< >{ }< >()()<|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|>(b, c, d)< >[ ]< >{ { } }< >{ }< >()()<|}]
let%expect_test "expression_hole" =
let run = run_all in
let source = {|a(b, c, d)e [][] { { } }|} in
let match_template = {|:[x:e]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
[%expect_exact {|>a(b, c, d)e< >[][]< >{ { } }<|}]
run_all (module Alpha) source match_template rewrite_template;
[%expect_exact {|>a(b, c, d)e< >[][]< >{ { } }<|}];
run_all (module Omega) source match_template rewrite_template;
[%expect_exact {|>a(b, c, d)e< >[][]< >{ { } }<|}];

View File

@ -1,176 +0,0 @@
open Core
open Rewriter
open Test_helpers
include Test_omega
let run_all ?(configuration = configuration) source match_template rewrite_template =
Generic.all ~configuration ~template:match_template ~source ()
|> function
| [] -> print_string "No matches."
| results ->
Option.value_exn (Rewrite.all ~source ~rewrite_template results)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let%expect_test "non_space" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|:[x.]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
[%expect_exact {| {foo.} {foo.bar.quux} {derp}|}]
let%expect_test "only_space" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|:[ x]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
[%expect_exact {|{ }foo.{ }foo.bar.quux{ }derp|}]
let%expect_test "up_to_newline" =
let run = run_all in
let source =
{|
foo.
foo.bar.quux
derp
|} in
let match_template = {|:[x\n]|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
[%expect_exact {|{
}{foo.
}{foo.bar.quux
}{derp
}|}]
let%expect_test "match_empty_in_newline_hole" =
let run = run_all in
let source =
{|stuff
after
|} in
let match_template = {|stuff:[x\n]|} in
let rewrite_template = {|{->:[x]<-}|} in
run source match_template rewrite_template;
[%expect_exact {|{->
<-}after
|}]
let%expect_test "leading_indentation" =
let run = run_all in
let source =
{|
foo. bar bazz
foo.bar.quux
derp
|} in
let match_template = {|:[ leading_indentation]:[rest\n]|} in
let rewrite_template = {|{:[leading_indentation]}:[rest]|} in
run source match_template rewrite_template;
[%expect_exact {|
{ }foo. bar bazz
{ }foo.bar.quux
{ }derp
|}]
let%expect_test "non_space_partial_match" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|foo.:[x.]ux|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
[%expect_exact {| foo. {bar.qu} derp|}]
let%expect_test "non_space_does_not_match_reserved_delimiters" =
let run = run_all in
let source = {|fo.o(x)|} in
let match_template = {|:[f.]|} in
let rewrite_template = {|{:[f]}|} in
run source match_template rewrite_template;
[%expect_exact {|{fo.o}({x})|}]
let%expect_test "non_space_only_hole" =
let run = run_all in
let source = {|a.b c.d|} in
let match_template = {|:[x.]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
[%expect_exact {|>a.b< >c.d<|}]
let%expect_test "alphanum_partial_match" =
let run = run_all in
let source = {| foo. foo.bar.quux derp|} in
let match_template = {|foo.b:[x]r.quux|} in
let rewrite_template = {|{:[x]}|} in
run source match_template rewrite_template;
[%expect_exact {| foo. {a} derp|}]
let%expect_test "newline_matcher_should_not_be_sat_on_space" =
let run = run_all in
let source =
{|a b c d
e f g h|} in
let match_template = {|:[line\n] |} in
let rewrite_template = {|{:[line]}|} in
run source match_template rewrite_template;
[%expect_exact {|{a b c d
}e f g h|}];
let run = run_all in
let source =
{|a b c d
e f g h|} in
let match_template = {|:[line\n]:[next]|} in
let rewrite_template = {|{:[line]}|} in
run source match_template rewrite_template;
[%expect_exact {|{a b c d
}|}];
let run = run_all in
let source =
{|a b c d
e f g h
|} in
let match_template = {|:[line1\n]:[next\n]|} in
let rewrite_template = {|{:[line1]|:[next]}|} in
run source match_template rewrite_template;
[%expect_exact {|{a b c d
|e f g h
}|}]
let%expect_test "implicit_equals" =
let run = run_all in
let source = {|a b a|} in
let match_template = {|:[[x]] :[[m]] :[[x]]|} in
let rewrite_template = {|:[m]|} in
run source match_template rewrite_template;
[%expect_exact {|b|}]
let%expect_test "implicit_equals_does_not_apply_to_underscore" =
let run = run_all in
let source = {|a b c|} in
let match_template = {|:[[x]] :[[_]] :[[_]]|} in
let rewrite_template = {|:[x]|} in
run source match_template rewrite_template;
[%expect_exact {|a|}]
let%expect_test "expression_hole" =
let run = run_all in
let source = {|(b, c, d) [ ] { { } } { } ()()|} in
let match_template = {|:[x:e]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
[%expect_exact {|>(b, c, d)< >[ ]< >{ { } }< >{ }< >()()<|}]
let%expect_test "expression_hole" =
let run = run_all in
let source = {|a(b, c, d)e [][] { { } }|} in
let match_template = {|:[x:e]|} in
let rewrite_template = {|>:[x]<|} in
run source match_template rewrite_template;
[%expect_exact {|>a(b, c, d)e< >[][]< >{ { } }<|}]

View File

@ -1,13 +1,17 @@
open Core
open Rewriter
open Comby_kernel
open Matchers
open Test_helpers
include Test_alpha
let all ?(configuration = configuration) (module E : Engine.S) template source =
E.Generic.all ~configuration ~template ~source ()
let all ?(configuration = configuration) template source =
Generic.all ~configuration ~template ~source ()
let rewrite_all engine template source rewrite_template =
all engine template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
let print_matches matches =
List.map matches ~f:Match.to_yojson
@ -18,15 +22,34 @@ let print_matches matches =
let%expect_test "dont_get_stuck" =
let template = "" in
let source = "a" in
let matches = all ~configuration template source in
print_matches matches;
all (module Alpha) ~configuration template source
|> print_matches;
[%expect_exact {|[]|}];
all (module Omega) ~configuration template source
|> print_matches;
[%expect_exact {|[]|}]
let%expect_test "dont_get_stuck" =
let template = "a" in
let source = "a" in
let matches = all template source in
print_matches matches;
all (module Alpha) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [],
"matched": "a"
}
]|}];
all (module Omega) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -41,8 +64,38 @@ let%expect_test "dont_get_stuck" =
let%expect_test "dont_get_stuck" =
let template = "a" in
let source = "aaa" in
let matches = all template source in
print_matches matches;
all (module Alpha) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [],
"matched": "a"
},
{
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
},
"environment": [],
"matched": "a"
},
{
"range": {
"start": { "offset": 2, "line": 1, "column": 3 },
"end": { "offset": 3, "line": 1, "column": 4 }
},
"environment": [],
"matched": "a"
}
]|}];
all (module Omega) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -75,9 +128,11 @@ let%expect_test "rewrite_awesome_1" =
let source = "xreplace this () end" in
let rewrite_template = "X" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "xX"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "xX"]
@ -86,17 +141,42 @@ let%expect_test "rewrite_whole_template_matches" =
let source = {|rewrite hello world <- this string|} in
let rewrite_template = "?" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "?"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "?"]
let%expect_test "single_token" =
let template = {|:[[1]] this|} in
let source = {|the problem is this|} in
let matches = all template source in
print_matches matches;
all (module Alpha) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 19, "line": 1, "column": 20 }
},
"environment": [
{
"variable": "1",
"value": "is",
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 14, "line": 1, "column": 15 }
}
}
],
"matched": "is this"
}
]|}];
all (module Omega) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -118,11 +198,35 @@ let%expect_test "single_token" =
]|}]
let%expect_test "single_token_with_preceding_whitespace" =
let template = {| :[[1]] this|} in
let source = {|the problem is this|} in
let matches = all template source in
print_matches matches;
all (module Alpha) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 11, "line": 1, "column": 12 },
"end": { "offset": 19, "line": 1, "column": 20 }
},
"environment": [
{
"variable": "1",
"value": "is",
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 14, "line": 1, "column": 15 }
}
}
],
"matched": " is this"
}
]|}];
all (module Omega) template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -147,9 +251,12 @@ let%expect_test "single_token_rewrite" =
let template = {| :[[1]] this|} in
let source = {|the problem is this|} in
let rewrite_template = ":[1]" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "the problemis"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "the problemis"]
@ -157,9 +264,12 @@ let%expect_test "single_token_match_inside_paren_no_succeeding_whitespace" =
let template = {|:[[1]](:[[2]])|} in
let source = {|foo(bar)|} in
let rewrite_template = ":[1] : :[2]" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "foo : bar"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "foo : bar"]
@ -167,9 +277,12 @@ let%expect_test "whitespace_hole_rewrite" =
let template = {|:[ w]this|} in
let rewrite_template = "space:[ w]here" in
let source = {| this|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "space here"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "space here"]
@ -177,9 +290,12 @@ let%expect_test "punctuation_hole_rewrite" =
let template = {|:[x.]|} in
let rewrite_template = "->:[x.]<-" in
let source = {|now.this. is,pod|racing|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "->now.this.<- ->is,pod|racing<-"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "->now.this.<- ->is,pod|racing<-"]
@ -189,21 +305,47 @@ let%expect_test "newline_hole_rewrite" =
let source = {|now.this.
is,pod|racing
|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact "->now.this.
<-->is,pod|racing
<-"];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact "->now.this.
<-->is,pod|racing
<-"]
let%expect_test "shift_or_at_least_dont_get_stuck" =
let template = ":[1]" in
let source = "a" in
let matches = all template source in
print_matches matches;
all (module Alpha) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
}
}
],
"matched": "a"
}
]|}];
all (module Omega) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -224,11 +366,35 @@ let%expect_test "shift_or_at_least_dont_get_stuck" =
}
]|}]
let%expect_test "shift_or_at_least_dont_get_stuck" =
let template = ":[1]" in
let source = "aa" in
let matches = all template source in
print_matches matches;
all (module Alpha) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 2, "line": 1, "column": 3 }
},
"environment": [
{
"variable": "1",
"value": "aa",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "aa"
}
]|}];
all (module Omega) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -262,8 +428,12 @@ let%expect_test "nested_rewrite1" =
|}
in
let matches = all template source in
print_matches matches;
all (module Alpha) ~configuration template source
|> print_matches;
[%expect_exact "[]"];
all (module Omega) ~configuration template source
|> print_matches;
[%expect_exact "[]"]
(* FIXME(RVT) nested rewrites *)
@ -289,9 +459,18 @@ let%expect_test "nested_rewrite2" =
|}
in
let rewrite_template = "for :[defines] := range :[var_use] {:[inner_body]}" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact {|for _, field := range fields.List {
if field.Names != nil {
for _, fieldName := range field.Names {
stuff with fields and things
}
}
}|}];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact {|for _, field := range fields.List {
if field.Names != nil {
@ -314,9 +493,14 @@ let%expect_test "match_:[[1]]" =
|}
in
let rewrite_template = "next(:[1])" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
rewrite_all (module Alpha) template source rewrite_template
|> print_string;
[%expect_exact {|
col_names =next(reader)}
|}];
rewrite_all (module Omega) template source rewrite_template
|> print_string;
[%expect_exact {|
col_names =next(reader)}

View File

@ -1,323 +0,0 @@
open Core
open Rewriter
open Test_helpers
include Test_omega
let all ?(configuration = configuration) template source =
Generic.all ~configuration ~template ~source ()
let print_matches matches =
List.map matches ~f:Match.to_yojson
|> (fun matches -> `List matches)
|> Yojson.Safe.pretty_to_string
|> print_string
let%expect_test "dont_get_stuck" =
let template = "" in
let source = "a" in
let matches = all ~configuration template source in
print_matches matches;
[%expect_exact {|[]|}]
let%expect_test "dont_get_stuck" =
let template = "a" in
let source = "a" in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [],
"matched": "a"
}
]|}]
let%expect_test "dont_get_stuck" =
let template = "a" in
let source = "aaa" in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [],
"matched": "a"
},
{
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
},
"environment": [],
"matched": "a"
},
{
"range": {
"start": { "offset": 2, "line": 1, "column": 3 },
"end": { "offset": 3, "line": 1, "column": 4 }
},
"environment": [],
"matched": "a"
}
]|}]
let%expect_test "rewrite_awesome_1" =
let template = "replace this :[1] end" in
let source = "xreplace this () end" in
let rewrite_template = "X" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "xX"]
let%expect_test "rewrite_whole_template_matches" =
let template = {|rewrite :[1] <- this string|} in
let source = {|rewrite hello world <- this string|} in
let rewrite_template = "?" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "?"]
let%expect_test "single_token" =
let template = {|:[[1]] this|} in
let source = {|the problem is this|} in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 19, "line": 1, "column": 20 }
},
"environment": [
{
"variable": "1",
"value": "is",
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 14, "line": 1, "column": 15 }
}
}
],
"matched": "is this"
}
]|}]
let%expect_test "single_token_with_preceding_whitespace" =
let template = {| :[[1]] this|} in
let source = {|the problem is this|} in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 11, "line": 1, "column": 12 },
"end": { "offset": 19, "line": 1, "column": 20 }
},
"environment": [
{
"variable": "1",
"value": "is",
"range": {
"start": { "offset": 12, "line": 1, "column": 13 },
"end": { "offset": 14, "line": 1, "column": 15 }
}
}
],
"matched": " is this"
}
]|}]
let%expect_test "single_token_rewrite" =
let template = {| :[[1]] this|} in
let source = {|the problem is this|} in
let rewrite_template = ":[1]" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "the problemis"]
let%expect_test "single_token_match_inside_paren_no_succeeding_whitespace" =
let template = {|:[[1]](:[[2]])|} in
let source = {|foo(bar)|} in
let rewrite_template = ":[1] : :[2]" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "foo : bar"]
let%expect_test "whitespace_hole_rewrite" =
let template = {|:[ w]this|} in
let rewrite_template = "space:[ w]here" in
let source = {| this|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "space here"]
let%expect_test "punctuation_hole_rewrite" =
let template = {|:[x.]|} in
let rewrite_template = "->:[x.]<-" in
let source = {|now.this. is,pod|racing|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "->now.this.<- ->is,pod|racing<-"]
let%expect_test "newline_hole_rewrite" =
let template = {|:[x\n]|} in
let rewrite_template = {|->:[x\n]<-|} in
let source = {|now.this.
is,pod|racing
|} in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact "->now.this.
<-->is,pod|racing
<-"]
let%expect_test "shift_or_at_least_dont_get_stuck" =
let template = ":[1]" in
let source = "a" in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 1, "line": 1, "column": 2 }
}
}
],
"matched": "a"
}
]|}]
let%expect_test "shift_or_at_least_dont_get_stuck" =
let template = ":[1]" in
let source = "aa" in
let matches = all template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 2, "line": 1, "column": 3 }
},
"environment": [
{
"variable": "1",
"value": "aa",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "aa"
}
]|}]
let%expect_test "nested_rewrite1" =
let source =
{|
x x y strcpy(strcpy(dst1, src1), src2); blah blah XXX
|}
in
let template =
{|
strcpy(:[1], :[2])
|}
in
let matches = all template source in
print_matches matches;
[%expect_exact "[]"]
(* FIXME(RVT) nested rewrites *)
let%expect_test "nested_rewrite2" =
let template =
{|
if :[var_check] != nil {
for :[defines] := range :[var_use] {:[inner_body]}
}
|}
in
let source =
{|
if fields.List != nil {
for _, field := range fields.List {
if field.Names != nil {
for _, fieldName := range field.Names {
stuff with fields and things
}
}
}
}
|}
in
let rewrite_template = "for :[defines] := range :[var_use] {:[inner_body]}" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|for _, field := range fields.List {
if field.Names != nil {
for _, fieldName := range field.Names {
stuff with fields and things
}
}
}|}]
let%expect_test "match_:[[1]]" =
let template =
{|
:[[1]].next()
|}
in
let source =
{|
col_names = reader.next()
}
|}
in
let rewrite_template = "next(:[1])" in
all template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|
col_names =next(reader)}
|}]

View File

@ -1,53 +1,82 @@
open Core
open Comby_kernel
open Matchers
open Match
open Test_helpers
include Test_alpha
let sat ?(env = Match.Environment.create ()) (module E : Engine.S) rule =
let rule = Rule.create rule |> Or_error.ok_exn in
Format.sprintf "%b" Rule.(sat @@ apply ~match_all:(E.Generic.all ~rule:[Ast.True] ~nested:false) rule env)
let run (module E : Engine.S) template source rule =
let (module M : Matcher.S) = (module E.Generic) in
M.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply ~match_all:(M.all ~rule:[Ast.True] ~nested:false) rule environment))
let%expect_test "rule_sat" =
let rule = {| where "x" != "y" |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|true|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where "x" != "x" |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|false|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where "x" == "x" |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|true|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where "x" == "y" |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|false|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where :[x] == "y" |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|false|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where :[x] == :[x] |} in
sat rule |> print_string;
sat (module Alpha) rule |> print_string;
[%expect_exact {|false|}];
sat (module Omega) rule |> print_string;
[%expect_exact {|false|}]
let%expect_test "rule_sat_with_env" =
let env = make_env ["1", "x"; "2", "y"; "3", "x"] in
let rule = {| where :[1] == :[3], :[1] != :[2] |} in
sat ~env rule |> print_string;
sat (module Alpha) ~env rule |> print_string;
[%expect_exact {|true|}];
sat (module Omega) ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[3], :[1] != "y" |} in
sat ~env rule |> print_string;
sat (module Alpha) ~env rule |> print_string;
[%expect_exact {|true|}];
sat (module Omega) ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[3], :[1] == "x" |} in
sat ~env rule |> print_string;
sat (module Alpha) ~env rule |> print_string;
[%expect_exact {|true|}];
sat (module Omega) ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[2], :[1] != :[2] |} in
sat ~env rule |> print_string;
sat (module Alpha) ~env rule |> print_string;
[%expect_exact {|false|}];
sat (module Omega) ~env rule |> print_string;
[%expect_exact {|false|}]
let%expect_test "where_true" =
@ -68,12 +97,34 @@ let%expect_test "where_true" =
let rule =
{| where true
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 11, "line": 1, "column": 12 }
},
"environment": [
{
"variable": "1",
"value": "b,c",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "(b,c) => {}"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -117,12 +168,15 @@ let%expect_test "match_sat" =
| ":[_],:[_]" -> false
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}];
@ -133,12 +187,11 @@ let%expect_test "match_sat" =
| ":[_],:[_]" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
@ -161,6 +214,30 @@ let%expect_test "match_sat" =
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 11, "line": 1, "column": 12 }
},
"environment": [
{
"variable": "1",
"value": "b,c",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "(b,c) => {}"
}
] |}];
let source =
{|
(a) => {}
@ -176,12 +253,34 @@ let%expect_test "match_sat" =
| ":[_]" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 9, "line": 1, "column": 10 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "(a) => {}"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -212,12 +311,34 @@ let%expect_test "match_sat" =
| ":[_]" -> :[1] == "a"
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 9, "line": 1, "column": 10 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "(a) => {}"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -247,17 +368,20 @@ let%expect_test "match_sat" =
| ":[_]" -> :[1] == "b"
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_s_suffix" =
let template = ":[1]s" in
@ -266,12 +390,34 @@ let%expect_test "match_s_suffix" =
let rule =
{| where true
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "name",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "names"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -302,12 +448,34 @@ let%expect_test "match_s_suffix" =
let rule =
{| where true
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "names",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
}
}
],
"matched": "names"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -330,6 +498,7 @@ let%expect_test "match_s_suffix" =
}
] |}]
let%expect_test "configuration_choice_based_on_case" =
let template = ":[1]" in
@ -340,12 +509,16 @@ let%expect_test "configuration_choice_based_on_case" =
| "ame" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}];
@ -359,12 +532,34 @@ let%expect_test "configuration_choice_based_on_case" =
| "names" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "names",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
}
}
],
"matched": "names"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -396,19 +591,20 @@ let%expect_test "configuration_choice_based_on_case" =
| "names" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_using_environment_merge" =
let template = "{:[1]}" in
@ -417,12 +613,11 @@ let%expect_test "match_using_environment_merge" =
let rule =
{| where match :[1] { | "{ :[x] : :[y] }" -> :[x] == :[y] }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
@ -445,6 +640,30 @@ let%expect_test "match_using_environment_merge" =
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 21, "line": 1, "column": 22 }
},
"environment": [
{
"variable": "1",
"value": "{ a : a } { a : a }",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 20, "line": 1, "column": 21 }
}
}
],
"matched": "{{ a : a } { a : a }}"
}
] |}];
let template = "{:[1]}" in
let source = "{{ a : a } { a : b }}" in
@ -452,17 +671,20 @@ let%expect_test "match_using_environment_merge" =
let rule =
{| where match :[1] { | "{ :[x] : :[y] }" -> :[x] == :[y] }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}]
let%expect_test "nested_matches" =
let template = ":[1]" in
@ -477,12 +699,34 @@ let%expect_test "nested_matches" =
}
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 37, "line": 1, "column": 38 }
},
"environment": [
{
"variable": "1",
"value": "{ { foo : { bar : { baz : qux } } } }",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 37, "line": 1, "column": 38 }
}
}
],
"matched": "{ { foo : { bar : { baz : qux } } } }"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -518,17 +762,20 @@ let%expect_test "nested_matches" =
}
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_on_template" =
let template = ":[1]" in
@ -539,12 +786,34 @@ let%expect_test "match_on_template" =
| "poodles" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
},
"environment": [
{
"variable": "1",
"value": "oodles",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
}
}
],
"matched": "oodles"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -576,12 +845,34 @@ let%expect_test "match_on_template" =
| "poodles" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
},
"environment": [
{
"variable": "1",
"value": "poodle",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
}
}
],
"matched": "poodle"
}
] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[
@ -613,12 +904,16 @@ let%expect_test "match_on_template" =
| "poodle" -> true
}
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
run (module Alpha) template source rule
|> print_matches;
[%expect {|
[] |}];
run (module Omega) template source rule
|> print_matches;
[%expect {|
[] |}]

View File

@ -1,624 +0,0 @@
open Core
open Match
open Test_helpers
include Test_omega
let%expect_test "rule_sat" =
let rule = {| where "x" != "y" |} in
sat rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where "x" != "x" |} in
sat rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where "x" == "x" |} in
sat rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where "x" == "y" |} in
sat rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where :[x] == "y" |} in
sat rule |> print_string;
[%expect_exact {|false|}];
let rule = {| where :[x] == :[x] |} in
sat rule |> print_string;
[%expect_exact {|false|}]
let%expect_test "rule_sat_with_env" =
let env = make_env ["1", "x"; "2", "y"; "3", "x"] in
let rule = {| where :[1] == :[3], :[1] != :[2] |} in
sat ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[3], :[1] != "y" |} in
sat ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[3], :[1] == "x" |} in
sat ~env rule |> print_string;
[%expect_exact {|true|}];
let rule = {| where :[1] == :[2], :[1] != :[2] |} in
sat ~env rule |> print_string;
[%expect_exact {|false|}]
let%expect_test "where_true" =
let template =
{|
(:[1]) => {}
|}
|> format
in
let source =
{|
(b,c) => {}
|}
|> format
in
let rule =
{| where true
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 11, "line": 1, "column": 12 }
},
"environment": [
{
"variable": "1",
"value": "b,c",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "(b,c) => {}"
}
] |}]
let%expect_test "match_sat" =
let template =
{|
(:[1]) => {}
|}
|> format
in
let source =
{|
(b,c) => {}
|}
|> format
in
let rule =
{| where
match :[1] {
| ":[_],:[_]" -> false
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}];
let rule =
{| where
match :[1] {
| ":[_],:[_]" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 11, "line": 1, "column": 12 }
},
"environment": [
{
"variable": "1",
"value": "b,c",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "(b,c) => {}"
}
] |}];
let source =
{|
(a) => {}
(b,c) => {}
|}
|> format
in
let rule =
{| where
match :[1] {
| ":[_],:[_]" -> false
| ":[_]" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 9, "line": 1, "column": 10 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "(a) => {}"
}
] |}];
let rule =
{|
where
match :[1] {
| ":[_],:[_]" -> false
| ":[_]" -> :[1] == "a"
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 9, "line": 1, "column": 10 }
},
"environment": [
{
"variable": "1",
"value": "a",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 2, "line": 1, "column": 3 }
}
}
],
"matched": "(a) => {}"
}
] |}];
let rule =
{| where
match :[1] {
| ":[_],:[_]" -> false
| ":[_]" -> :[1] == "b"
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_s_suffix" =
let template = ":[1]s" in
let source = "names" in
let rule =
{| where true
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "name",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 4, "line": 1, "column": 5 }
}
}
],
"matched": "names"
}
] |}]
let%expect_test "match_s_suffix" =
let template = ":[1]" in
let source = "names" in
let rule =
{| where true
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "names",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
}
}
],
"matched": "names"
}
] |}]
let%expect_test "configuration_choice_based_on_case" =
let template = ":[1]" in
let source = "names" in
let rule =
{| where match :[1] {
| "ame" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}];
let template = ":[1]" in
let source = "names" in
let rule =
{| where match :[1] {
| "names" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
},
"environment": [
{
"variable": "1",
"value": "names",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 5, "line": 1, "column": 6 }
}
}
],
"matched": "names"
}
] |}];
let template = ":[1]" in
let source = "namesXXXXX" in
let rule =
{| where match :[1] {
| "names" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_using_environment_merge" =
let template = "{:[1]}" in
let source = "{{ a : a } { a : a }}" in
let rule =
{| where match :[1] { | "{ :[x] : :[y] }" -> :[x] == :[y] }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 21, "line": 1, "column": 22 }
},
"environment": [
{
"variable": "1",
"value": "{ a : a } { a : a }",
"range": {
"start": { "offset": 1, "line": 1, "column": 2 },
"end": { "offset": 20, "line": 1, "column": 21 }
}
}
],
"matched": "{{ a : a } { a : a }}"
}
] |}];
let template = "{:[1]}" in
let source = "{{ a : a } { a : b }}" in
let rule =
{| where match :[1] { | "{ :[x] : :[y] }" -> :[x] == :[y] }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}]
let%expect_test "nested_matches" =
let template = ":[1]" in
let source = "{ { foo : { bar : { baz : qux } } } }" in
let rule =
{| where match :[1] {
| "{ :[foo] : :[tail1] }" -> match :[tail1] {
| "{ :[bar] : :[tail2] }" -> match :[tail2] {
| "{ baz : :[qux] }" -> :[qux] == "qux", :[bar] == "bar"
}
}
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 37, "line": 1, "column": 38 }
},
"environment": [
{
"variable": "1",
"value": "{ { foo : { bar : { baz : qux } } } }",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 37, "line": 1, "column": 38 }
}
}
],
"matched": "{ { foo : { bar : { baz : qux } } } }"
}
] |}];
let template = ":[1]" in
let source = "{ { foo : { bar : { baz : qux } } } }" in
let rule =
{| where match :[1] {
| "{ :[foo] : :[tail1] }" -> match :[tail1] {
| "{ :[bar] : :[tail2] }" -> match :[tail2] {
| "{ baz : :[qux] }" -> :[qux] == "fail"
}
}
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}]
let%expect_test "match_on_template" =
let template = ":[1]" in
let source = "oodles" in
let rule =
{| where match "p:[1]" {
| "poodles" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
},
"environment": [
{
"variable": "1",
"value": "oodles",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
}
}
],
"matched": "oodles"
}
] |}];
let template = ":[1]" in
let source = "poodle" in
let rule =
{| where match ":[1]s" {
| "poodles" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
},
"environment": [
{
"variable": "1",
"value": "poodle",
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 6, "line": 1, "column": 7 }
}
}
],
"matched": "poodle"
}
] |}];
let template = ":[1]" in
let source = "poodle" in
let rule =
{| where match ":[1]," {
| "poodle" -> true
}
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
Generic.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } -> Rule.(sat @@ apply rule environment))
|> print_matches;
[%expect {|
[] |}];

View File

@ -0,0 +1,27 @@
open Core
open Comby_kernel
open Matchers
open Test_helpers
(* See https://stackoverflow.com/questions/6698039/nested-comments-in-c-c *)
let%expect_test "nested_multiline_ocaml" =
let source = {|int nest = /*/*/ 0 */**/ 1;|} in
let template = {|0 * 1|} in
(* 0 is not commented out *)
Alpha.C.all ~configuration ~template ~source ()
|> print_only_match;
[%expect_exact {|[ "0 */**/ 1" ]|}];
Omega.C.all ~configuration ~template ~source ()
|> print_only_match;
[%expect_exact {|[ "0 */**/ 1" ]|}];
(* 0 is commented out *)
Alpha.C_nested_comments.all ~configuration ~template ~source ()
|> print_only_match;
[%expect_exact {|[]|}];
Omega.C_nested_comments.all ~configuration ~template ~source ()
|> print_only_match;
[%expect_exact {|[]|}];

View File

@ -1,19 +0,0 @@
open Core
open Test_helpers
include Test_alpha
(* See https://stackoverflow.com/questions/6698039/nested-comments-in-c-c *)
let%expect_test "nested_multiline_ocaml" =
let source = {|int nest = /*/*/ 0 */**/ 1;|} in
let template = {|0 * 1|} in
(* 0 is not commented out *)
let matches_no_nesting = C.all ~configuration ~template ~source () in
print_only_match matches_no_nesting;
[%expect_exact {|[ "0 */**/ 1" ]|}];
let matches_no_nesting = C_nested_comments.all ~configuration ~template ~source () in
(* 0 is commented out *)
print_only_match matches_no_nesting;
[%expect_exact {|[]|}];

View File

@ -1,19 +0,0 @@
open Core
open Test_helpers
include Test_omega
(* See https://stackoverflow.com/questions/6698039/nested-comments-in-c-c *)
let%expect_test "nested_multiline_ocaml" =
let source = {|int nest = /*/*/ 0 */**/ 1;|} in
let template = {|0 * 1|} in
(* 0 is not commented out *)
let matches_no_nesting = C.all ~configuration ~template ~source () in
print_only_match matches_no_nesting;
[%expect_exact {|[ "0 */**/ 1" ]|}];
let matches_no_nesting = C_nested_comments.all ~configuration ~template ~source () in
(* 0 is commented out *)
print_only_match matches_no_nesting;
[%expect_exact {|[]|}];

View File

@ -1,10 +1,11 @@
open Core
open Test_helpers
open Comby_kernel
include Test_alpha
open Matchers
let run = run_nested (module Matchers.Alpha.Generic)
let run (module E : Engine.S) = run_nested (module E.Generic)
let%expect_test "nested_matches" =
let source = {|
@ -23,7 +24,18 @@ q{
}
|} in
let match_template = {|:[[f]]{:[x]}|} in
run source match_template ();
run (module Alpha) source match_template ();
[%expect_exact {|2:a{\n b{\n c{\n d{e}\n }\n }\n }
3:b{\n c{\n d{e}\n }\n }
4:c{\n d{e}\n }
5:d{e}
10:q{\n b{\n f{}\n }\n}
11:b{\n f{}\n }
12:f{}
|}];
run (module Omega) source match_template ();
[%expect_exact {|2:a{\n b{\n c{\n d{e}\n }\n }\n }
3:b{\n c{\n d{e}\n }\n }
4:c{\n d{e}\n }
@ -33,21 +45,39 @@ q{
12:f{}
|}]
let%expect_test "nested_matches" =
let source = {|a(b(c(d(e))))|} in
let match_template = {|:[[f]](:[x])|} in
run source match_template ();
run (module Alpha) source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))
1:d(e)
|}];
run (module Omega) source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))
1:d(e)
|}]
let%expect_test "nested_matches_from_rule" =
let source = {|a(b(c(d(e))))|} in
let match_template = {|:[[f]](:[x])|} in
let rule = {|where nested|} in
run ~rule source match_template ();
run (module Alpha) ~rule source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))
1:d(e)
|}];
run (module Omega) ~rule source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))

View File

@ -1,53 +0,0 @@
open Core
open Test_helpers
let run = run_nested (module Matchers.Omega.Generic)
let%expect_test "nested_matches" =
let source = {|
a{
b{
c{
d{e}
}
}
}
q{
b{
f{}
}
}
|} in
let match_template = {|:[[f]]{:[x]}|} in
run source match_template ();
[%expect_exact {|2:a{\n b{\n c{\n d{e}\n }\n }\n }
3:b{\n c{\n d{e}\n }\n }
4:c{\n d{e}\n }
5:d{e}
10:q{\n b{\n f{}\n }\n}
11:b{\n f{}\n }
12:f{}
|}]
let%expect_test "nested_matches" =
let source = {|a(b(c(d(e))))|} in
let match_template = {|:[[f]](:[x])|} in
run source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))
1:d(e)
|}]
let%expect_test "nested_matches_from_rule" =
let source = {|a(b(c(d(e))))|} in
let match_template = {|:[[f]](:[x])|} in
let rule = {|where nested|} in
run ~rule source match_template ();
[%expect_exact {|1:a(b(c(d(e))))
1:b(c(d(e)))
1:c(d(e))
1:d(e)
|}]

View File

@ -1,9 +1,7 @@
open Core
open Test_helpers
module Alpha = Test_alpha
module Omega = Test_omega
open Comby_kernel
let to_string format matches =
let f = match format with
@ -13,11 +11,11 @@ let to_string format matches =
Format.asprintf "%a" f (Some "file", matches)
let run source match_template format : (string * string) =
let specification = Configuration.Specification.create ~match_template () in
let specification = Matchers.Specification.create ~match_template () in
let run ~fast =
let result =
Pipeline.process_single_source
(module Omega.C)
(module Matchers.Omega.C)
~fast_offset_conversion:fast
configuration
(String source)

View File

@ -1,2 +0,0 @@
include Matchers.Omega
module Rule = Language.Rule

View File

@ -1,5 +1,6 @@
open Core
open Matchers
open Rewriter
open Rewrite_template

View File

@ -1,6 +1,8 @@
open Core
open Language
open Comby_kernel
open Matchers
open Rule
let rule_parses rule =
match Rule.create rule with

View File

@ -1,10 +1,11 @@
open Configuration
open Command_configuration
include Test_alpha
open Comby_kernel
open Matchers
let configuration =
{ matcher = (module Generic : Matchers.Matcher.S)
let configuration (module E : Engine.S) =
{ matcher = (module E.Generic : Matchers.Matcher.S)
; sources = `String "source"
; specifications = []
; run_options =

View File

@ -1,56 +0,0 @@
open Configuration
open Command_configuration
include Test_omega
let configuration =
{ matcher = (module Generic : Matchers.Matcher.S)
; sources = `String "source"
; specifications = []
; run_options =
{ verbose = false
; match_timeout = 3
; dump_statistics = false
; substitute_in_place = true
; disable_substring_matching = false
; fast_offset_conversion = false
; match_newline_toplevel = false
; bound_count = None
; compute_mode = `Sequential
}
; output_printer = (fun _ -> ())
; interactive_review = None
; extension = None
; metasyntax = None
}
(* TODO restore this, can't access the Parallel_hack module *)
(*
let%expect_test "interactive_paths" =
let _, count =
let scheduler = Scheduler.create ~number_of_workers:1 () in
Pipeline.with_scheduler scheduler ~f:(
Pipeline.process_paths_for_interactive
~sequential:false
~f:(fun ~input: _ ~path:_ -> (None, 0)) [])
in
print_string (Format.sprintf "%d" count);
[%expect_exact {|0|}]
let%expect_test "launch_editor" =
let configuration =
{ configuration
with interactive_review =
Some
{ editor = "vim"
; default_is_accept = true
}
}
in
let result =
try Pipeline.run configuration; "passed"
with _exc -> "Not a tty"
in
print_string result;
[%expect_exact {|Not a tty|}]
*)

View File

@ -1,44 +1,78 @@
open Core
open Comby_kernel
open Matchers
open Test_helpers
include Test_alpha
let all (module E : Engine.S) ~template ~source =
E.Python.all ~configuration ~template ~source ()
let%expect_test "matched_contains_raw_literal_quotes" =
let source = {|"""blah"""|} in
let template = {|""":[[1]]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
all (module Alpha) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"blah\"\"\"" ]|}];
all (module Omega) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"blah\"\"\"" ]|}]
let%expect_test "interpreted_string_does_not_match_raw_literal" =
let source = {|"""blah""" "blah"|} in
let template = {|":[[1]]"|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
all (module Alpha) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"blah\"" ]|}];
all (module Omega) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"blah\"" ]|}]
let%expect_test "interpreted_string_does_not_match_raw_literal_containing_quote" =
let source = {|"""blah""" """bl"ah""" "blah"|} in
let template = {|":[[1]]"|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
all (module Alpha) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"blah\"" ]|}];
all (module Omega) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"blah\"" ]|}]
let%expect_test "raw_string_matches_string_containing_quote" =
let source = {|"""bl"ah"""|} in
let template = {|""":[1]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
all (module Alpha) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"bl\"ah\"\"\"" ]|}];
all (module Omega) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"bl\"ah\"\"\"" ]|}]
let%expect_test "invalid_raw_string_in_python_but_matches_because_ignores_after" =
let source = {|"""""""|} in
let template = {|""":[1]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
all (module Alpha) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"\"\"\"" ]|}];
all (module Omega) ~template ~source
|> print_only_match;
[%expect_exact {|[ "\"\"\"\"\"\"" ]|}]
(* Disabled: this works by luck in Alpha, but it shouldn't. It is empty list in Omega. Should be explicitly supported *)
(*
let%expect_test "raw_string_captures_escape_sequences" =

View File

@ -1,50 +0,0 @@
open Core
open Test_helpers
include Test_omega
let%expect_test "matched_contains_raw_literal_quotes" =
let source = {|"""blah"""|} in
let template = {|""":[[1]]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
[%expect_exact {|[ "\"\"\"blah\"\"\"" ]|}]
let%expect_test "interpreted_string_does_not_match_raw_literal" =
let source = {|"""blah""" "blah"|} in
let template = {|":[[1]]"|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
[%expect_exact {|[ "\"blah\"" ]|}]
let%expect_test "interpreted_string_does_not_match_raw_literal_containing_quote" =
let source = {|"""blah""" """bl"ah""" "blah"|} in
let template = {|":[[1]]"|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
[%expect_exact {|[ "\"blah\"" ]|}]
let%expect_test "raw_string_matches_string_containing_quote" =
let source = {|"""bl"ah"""|} in
let template = {|""":[1]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
[%expect_exact {|[ "\"\"\"bl\"ah\"\"\"" ]|}]
let%expect_test "invalid_raw_string_in_python_but_matches_because_ignores_after" =
let source = {|"""""""|} in
let template = {|""":[1]"""|} in
let matches = Python.all ~configuration ~template ~source () in
print_only_match matches;
[%expect_exact {|[ "\"\"\"\"\"\"" ]|}]
(* Disabled: this works by luck in Alpha, but it shouldn't. It is empty list in Omega. Should be explicitly supported *)
(*
let%expect_test "raw_string_captures_escape_sequences" =
let source = {|"""\""""|} in
let template = {|""":[1]"""|} in
let matches = Python.all ~configuration ~template ~source in
print_only_match matches;
[%expect_exact {|[ "\"\"\"\\\"\"\"" ]|}]
*)

View File

@ -1,111 +1,149 @@
open Core
open Comby_kernel
open Test_helpers
open Matchers.Alpha
open Matchers
let%expect_test "regex_holes_simple" =
let source = {|foo|} in
let match_template = {|:[x~\w+]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(foo)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(foo)|}]
let%expect_test "regex_holes_simple_posix" =
let source = {|foo|} in
let match_template = {|:[x~[[:alpha:]]]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(f)(o)(o)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(f)(o)(o)|}]
let%expect_test "regex_holes_substring" =
let source = {|foo()|} in
let match_template = {|:[x~o\w]()|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|f(oo)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|f(oo)|}]
let%expect_test "regex_holes_empty_string_terminates" =
let source = {|foo()|} in
let match_template = {|:[x~|]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o()(())|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o()(())|}]
let%expect_test "regex_holes_repetition_takes_precedence" =
let source = {|foobar()|} in
(* this will _not_ match because bar is consumed by \w before we look ahead *)
let match_template = {|:[x~\w+]bar()|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|No matches.|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|No matches.|}]
let%expect_test "regex_holes_negated_match" =
let source = {|(literally_anyting_except_close_paren?!@#$%^&*[])|} in
let match_template = {|(:[x~[^)]+])|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(literally_anyting_except_close_paren?!@#$%^&*[])|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(literally_anyting_except_close_paren?!@#$%^&*[])|}];
let source = {|(arg1, arg2, arg3)|} in
let match_template = {|:[x~[^,() ]+]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|((arg1), (arg2), (arg3))|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|((arg1), (arg2), (arg3))|}]
let%expect_test "regex_holes_dot_star_ok_and_this_is_for_newline" =
let source = "foo()\nbar()" in
let match_template = {|:[x~.*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(foo())()
(bar())|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(foo())()
(bar())|}]
let%expect_test "regex_holes_optional" =
let source = "nonovember no november no vember" in
let match_template = {|:[x~no(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}]
let%expect_test "regex_holes_optional_spaces" =
let source = "nonovember no november no vember" in
let match_template = {|no :[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|nonovember ()november (vember)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|nonovember ()november (vember)|}]
(* Note: Known limitation: this behavior does _not_ allow (optional)? to match
empty string to sat template. Because of something tricky. *)
let%expect_test "regex_holes_optional_doesnt_work_outside_regex" =
let source = "no" in
let match_template = {|no:[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
(* Note: Known Alpha limitation: this behavior does _not_ allow (optional)? to match
empty string to sat template. Because of something tricky. *)
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|No matches.|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|()|}];
let source = "foo bar foobar" in
let match_template = {|:[x~\s*?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o() ()b()a()r() ()f()o()o()b()a()r|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o() ()b()a()r() ()f()o()o()b()a()r|}];
let source = "foo bar foobar" in
let match_template = {|:[x~\s*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o( )()b()a()r( )()f()o()o()b()a()r|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o( )()b()a()r( )()f()o()o()b()a()r|}]
@ -114,17 +152,23 @@ let%expect_test "regex_holes_optional_strip_no_from_november_outside_regex" =
let match_template = {|no:[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|()(vember) () (vember) () vember|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|()(vember) () (vember) () vember|}]
let%expect_test "regex_holes_optional_strip_no_from_november_inside_regex" =
let source = "nonovember no november no vember" in
let match_template = {|:[x~no(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}]
let%expect_test "leading_spaces_beginning_line_anchor" =
let source = {|
a
@ -135,10 +179,14 @@ let%expect_test "leading_spaces_beginning_line_anchor" =
let match_template = {|:[x~^(\s+)]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|( )a( )b( )c
|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|( )a( )b( )c
|}]
let%expect_test "spaces_star" =
let source = {|
a
@ -150,8 +198,18 @@ let%expect_test "spaces_star" =
let match_template = {|:[x~\s*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
(* The <spaces><empty space>chars is how this behaves on https://regexr.com/59ft0 as well, see replace *)
(* The <spaces><empty space>chars is how this behaves on
https://regexr.com/59ft0 as well, see replace *)
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(
)()a(
)()b(
)()c(
)()d(
)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(
)()a(
)()b(
@ -159,6 +217,7 @@ let%expect_test "spaces_star" =
)()d(
)|}]
let%expect_test "end_line_anchor" =
let source = {|
aaa bbb
@ -169,12 +228,19 @@ ccc ddd
let match_template = {|:[x~\w+ bbb$]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|
(aaa bbb)aaa bbb ccc
ccc ddd
|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|
(aaa bbb)aaa bbb ccc
ccc ddd
|}]
let%expect_test "word_boundaries" =
let source = {|
foo(bar, baz(),
@ -186,7 +252,15 @@ foo(bar, baz(),
let match_template = {|:[x~\b\w+\b]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo<)((>bar<), (>baz<)(),
(>qux<).(>derp<))
|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo<)((>bar<), (>baz<)(),
@ -194,6 +268,7 @@ foo(bar, baz(),
(>qux<).(>derp<))
|}]
(* I previously assumed [^ ] would not match newlines, but it does, and is the
same as regexr https://regexr.com/59fst. To not match newlines, see the next
test with [^\s] *)
@ -208,7 +283,15 @@ foo(bar, baz(),
let match_template = {|:[x~[^, ]+]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|(>
foo(bar<), (>baz()<),(>
<) (>qux.derp)
<)|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|(>
foo(bar<), (>baz()<),(>
@ -216,6 +299,7 @@ foo(bar<), (>baz()<),(>
<) (>qux.derp)
<)|}]
let%expect_test "do_not_match_whitespace" =
let source = {|
foo(bar, baz(),
@ -227,7 +311,15 @@ foo(bar, baz(),
let match_template = {|:[x~[^,\s]+]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
run (module Alpha.Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo(bar<), (>baz()<),
(>qux.derp)<)
|}];
run (module Omega.Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo(bar<), (>baz()<),
@ -235,6 +327,7 @@ foo(bar, baz(),
(>qux.derp)<)
|}]
let%expect_test "eof_anchor" =
let source = {|
setScore(5)
@ -261,7 +354,23 @@ setScore(4/3)
in
let rewrite_template = "setScore( /*CHECK ME*/ :[1])" in
run (module Generic) source match_template ~rule rewrite_template;
run (module Alpha.Generic) source match_template ~rule rewrite_template;
[%expect_exact {|
setScore(5)
setScore(6)
setScore( /*CHECK ME*/ 6.5)
setScore( /*CHECK ME*/ "")
setScore( /*CHECK ME*/ "hi")
setScore( /*CHECK ME*/ "hi" + "there")
setScore( /*CHECK ME*/ 'ho')
setScore( /*CHECK ME*/ x)
setScore( /*CHECK ME*/ null)
setScore( /*CHECK ME*/ 4/3.0)
setScore( /*CHECK ME*/ 4.0/3.0)
setScore( /*CHECK ME*/ 4/3)
|}];
run (module Omega.Generic) source match_template ~rule rewrite_template;
[%expect_exact {|
setScore(5)
setScore(6)

View File

@ -1,286 +0,0 @@
open Core
open Test_helpers
open Matchers.Omega
let%expect_test "regex_holes_simple" =
let source = {|foo|} in
let match_template = {|:[x~\w+]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(foo)|}]
let%expect_test "regex_holes_simple_posix" =
let source = {|foo|} in
let match_template = {|:[x~[[:alpha:]]]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(f)(o)(o)|}]
let%expect_test "regex_holes_substring" =
let source = {|foo()|} in
let match_template = {|:[x~o\w]()|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|f(oo)|}]
let%expect_test "regex_holes_empty_string_terminates" =
let source = {|foo()|} in
let match_template = {|:[x~|]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o()(())|}]
let%expect_test "regex_holes_repetition_takes_precedence" =
let source = {|foobar()|} in
(* this will _not_ match because bar is consumed by \w before we look ahead *)
let match_template = {|:[x~\w+]bar()|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|No matches.|}]
let%expect_test "regex_holes_negated_match" =
let source = {|(literally_anyting_except_close_paren?!@#$%^&*[])|} in
let match_template = {|(:[x~[^)]+])|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(literally_anyting_except_close_paren?!@#$%^&*[])|}];
let source = {|(arg1, arg2, arg3)|} in
let match_template = {|:[x~[^,() ]+]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|((arg1), (arg2), (arg3))|}]
let%expect_test "regex_holes_dot_star_ok_and_this_is_for_newline" =
let source = "foo()\nbar()" in
let match_template = {|:[x~.*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(foo())()
(bar())|}]
let%expect_test "regex_holes_optional" =
let source = "nonovember no november no vember" in
let match_template = {|:[x~no(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}]
let%expect_test "regex_holes_optional_spaces" =
let source = "nonovember no november no vember" in
let match_template = {|no :[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|nonovember ()november (vember)|}]
let%expect_test "regex_holes_optional_doesnt_work_outside_regex" =
let source = "no" in
let match_template = {|no:[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|()|}];
let source = "foo bar foobar" in
let match_template = {|:[x~\s*?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o() ()b()a()r() ()f()o()o()b()a()r|}];
let source = "foo bar foobar" in
let match_template = {|:[x~\s*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|()f()o()o( )()b()a()r( )()f()o()o()b()a()r|}]
let%expect_test "regex_holes_optional_strip_no_from_november_outside_regex" =
let source = "nonovember no november no vember" in
let match_template = {|no:[x~(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|()(vember) () (vember) () vember|}]
let%expect_test "regex_holes_optional_strip_no_from_november_inside_regex" =
let source = "nonovember no november no vember" in
let match_template = {|:[x~no(vember)?]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(no)(november) (no) (november) (no) vember|}]
let%expect_test "leading_spaces_beginning_line_anchor" =
let source = {|
a
b
c
|}
in
let match_template = {|:[x~^(\s+)]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|( )a( )b( )c
|}]
let%expect_test "spaces_star" =
let source = {|
a
b
c
d
|}
in
let match_template = {|:[x~\s*]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
(* The <spaces><empty space>chars is how this behaves on https://regexr.com/59ft0 as well, see replace *)
[%expect_exact {|(
)()a(
)()b(
)()c(
)()d(
)|}]
let%expect_test "end_line_anchor" =
let source = {|
aaa bbb
aaa bbb ccc
ccc ddd
|}
in
let match_template = {|:[x~\w+ bbb$]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|
(aaa bbb)aaa bbb ccc
ccc ddd
|}]
let%expect_test "start_of_input_and_exact" =
let source = {|aaa bbb|}
in
let match_template = {|:[x~^\w+ bbb$]|} in
let rewrite_template = {|(:[x])|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(aaa bbb)|}]
let%expect_test "word_boundaries" =
let source = {|
foo(bar, baz(),
qux.derp)
|}
in
let match_template = {|:[x~\b\w+\b]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo<)((>bar<), (>baz<)(),
(>qux<).(>derp<))
|}]
(* I previously assumed [^ ] would not match newlines, but it does, and is the
same as regexr https://regexr.com/59fst. To not match newlines, see the next
test with [^\s] *)
let%expect_test "do_not_match_space" =
let source = {|
foo(bar, baz(),
qux.derp)
|}
in
let match_template = {|:[x~[^, ]+]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|(>
foo(bar<), (>baz()<),(>
<) (>qux.derp)
<)|}]
let%expect_test "do_not_match_whitespace" =
let source = {|
foo(bar, baz(),
qux.derp)
|}
in
let match_template = {|:[x~[^,\s]+]|} in
let rewrite_template = {|(>:[x]<)|} in
run (module Generic) source match_template rewrite_template;
[%expect_exact {|
(>foo(bar<), (>baz()<),
(>qux.derp)<)
|}]
let%expect_test "eof_anchor" =
let source = {|
setScore(5)
setScore(6)
setScore(6.5)
setScore("")
setScore("hi")
setScore("hi" + "there")
setScore('ho')
setScore(x)
setScore(null)
setScore(4/3.0)
setScore(4.0/3.0)
setScore(4/3)
|}
in
let match_template = {|setScore(:[1])|} in
let rule = {|
where match :[1] {
| ":[~^\\d+$]" -> false
| ":[_]" -> true
}
|}
in
let rewrite_template = "setScore( /*CHECK ME*/ :[1])" in
run (module Generic) source match_template ~rule rewrite_template;
[%expect_exact {|
setScore(5)
setScore(6)
setScore( /*CHECK ME*/ 6.5)
setScore( /*CHECK ME*/ "")
setScore( /*CHECK ME*/ "hi")
setScore( /*CHECK ME*/ "hi" + "there")
setScore( /*CHECK ME*/ 'ho')
setScore( /*CHECK ME*/ x)
setScore( /*CHECK ME*/ null)
setScore( /*CHECK ME*/ 4/3.0)
setScore( /*CHECK ME*/ 4.0/3.0)
setScore( /*CHECK ME*/ 4/3)
|}]

View File

@ -1,21 +1,19 @@
open Core
open Match
open Rewriter
open Test_helpers
include Test_alpha
open Comby_kernel
open Matchers
open Match
let all ?(configuration = configuration) template source =
C.all ~configuration ~template ~source ()
Alpha.C.all ~configuration ~template ~source ()
module Template_parser = Rewrite_template.Make(Matchers.Metasyntax.Default)
module Template_parser = Rewrite.Make(Metasyntax.Default)
let%expect_test "get_offsets_for_holes" =
let rewrite_template = {|1234:[1]1234:[2]|} in
let variables = Template_parser.variables rewrite_template in
let offsets = Rewrite_template.get_offsets_for_holes variables rewrite_template in
let offsets = Rewrite.get_offsets_for_holes variables rewrite_template in
print_s [%message (offsets : (string * int) list)];
[%expect_exact {|(offsets ((2 8) (1 4)))
|}]
@ -23,13 +21,13 @@ let%expect_test "get_offsets_for_holes" =
let%expect_test "get_offsets_for_holes_after_substitution_1" =
let rewrite_template = {|1234:[1]1234:[2]|} in
let variables = Template_parser.variables rewrite_template in
let offsets = Rewrite_template.get_offsets_for_holes variables rewrite_template in
let offsets = Rewrite.get_offsets_for_holes variables rewrite_template in
let environment =
Environment.create ()
|> (fun environment -> Environment.add environment "1" "333")
|> (fun environment -> Environment.add environment "2" "22")
in
let result = Rewrite_template.get_offsets_after_substitution offsets environment in
let result = Rewrite.get_offsets_after_substitution offsets environment in
print_s [%message (result : (string * int) list)];
[%expect_exact {|(result ((2 11) (1 4)))
|}]
@ -37,14 +35,14 @@ let%expect_test "get_offsets_for_holes_after_substitution_1" =
let%expect_test "get_offsets_for_holes_after_substitution_1" =
let rewrite_template = {|1234:[1]1234:[3]11:[2]|} in
let variables = Template_parser.variables rewrite_template in
let offsets = Rewrite_template.get_offsets_for_holes variables rewrite_template in
let offsets = Rewrite.get_offsets_for_holes variables rewrite_template in
let environment =
Environment.create ()
|> (fun environment -> Environment.add environment "1" "333")
|> (fun environment -> Environment.add environment "3" "333")
|> (fun environment -> Environment.add environment "2" "22")
in
let result = Rewrite_template.get_offsets_after_substitution offsets environment in
let result = Rewrite.get_offsets_after_substitution offsets environment in
print_s [%message (result : (string * int) list)];
[%expect_exact {|(result ((2 16) (3 11) (1 4)))
|}]

View File

@ -1,20 +1,18 @@
open Core
open Match
open Rewriter
open Test_helpers
open Comby_kernel
open Matchers
include Test_alpha
let run_rule source match_template rewrite_template rule =
Generic.first ~configuration match_template source
let run_rule (module E : Engine.S) source match_template rewrite_template rule =
let (module M : Matcher.S) = (module E.Generic) in
M.first ~configuration match_template source
|> function
| Error _ -> print_string "bad"
| Ok result ->
match result with
| ({ environment; _ } as m) ->
let e = Rule.(result_env @@ apply rule environment) in
let e = Rule.(result_env @@ apply ~match_all:(M.all ~rule:[Ast.True] ~nested:false) rule environment) in
match e with
| None -> print_string "bad bad"
| Some e ->
@ -34,11 +32,14 @@ let%expect_test "rewrite_rule" =
{|
where rewrite :[1] { "int" -> "expect" }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|expect|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|expect|}]
let%expect_test "sequenced_rewrite_rule" =
@ -52,11 +53,14 @@ let%expect_test "sequenced_rewrite_rule" =
rewrite :[a] { "a" -> "qqq" },
rewrite :[rest] { "{ b : { :[other] } }" -> "{ :[other] }" }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|{ { qqq : { c : d } } }|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|{ { qqq : { c : d } } }|}]
let%expect_test "rewrite_rule_for_list" =
@ -68,11 +72,14 @@ let%expect_test "rewrite_rule_for_list" =
{|
where rewrite :[contents] { ":[[x]]," -> ":[[x]];" }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4;]|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4;]|}]
let%expect_test "rewrite_rule_for_list_strip_last" =
@ -84,11 +91,14 @@ let%expect_test "rewrite_rule_for_list_strip_last" =
{|
where rewrite :[contents] { ":[x], " -> ":[x]; " }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4]|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4]|}]
let%expect_test "haskell_example" =
@ -105,17 +115,25 @@ let%expect_test "haskell_example" =
{|
where rewrite :[contents] { "," -> "++" }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|
( "blah blah blah"
++ "blah"
)
|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|
( "blah blah blah"
++ "blah"
)
|}]
let%expect_test "rewrite_freeform_antecedent_pattern" =
let source = {|
(concat
@ -129,11 +147,16 @@ let%expect_test "rewrite_freeform_antecedent_pattern" =
{|
where rewrite :[contents] { concat [:[x]] -> "nice" }
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
run_rule (module Alpha) source match_template rewrite_template rule;
[%expect_exact {|(
(nice)
)|}];
run_rule (module Omega) source match_template rewrite_template rule;
[%expect_exact {|(
(nice)
)|}]

View File

@ -1,139 +0,0 @@
open Core
open Match
open Rewriter
open Test_helpers
include Test_omega
let run_rule source match_template rewrite_template rule =
Generic.first ~configuration match_template source
|> function
| Error _ -> print_string "bad"
| Ok result ->
match result with
| ({ environment; _ } as m) ->
let e = Rule.(result_env @@ apply rule environment) in
match e with
| None -> print_string "bad bad"
| Some e ->
{ m with environment = e }
|> List.return
|> Rewrite.all ~source ~rewrite_template
|> (fun x -> Option.value_exn x)
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let%expect_test "rewrite_rule" =
let source = {|int|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
let rule =
{|
where rewrite :[1] { "int" -> "expect" }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|expect|}]
let%expect_test "sequenced_rewrite_rule" =
let source = {|{ { a : { b : { c : d } } } }|} in
let match_template = {|{ :[a] : :[rest] }|} in
let rewrite_template = {|{ :[a] : :[rest] }|} in
let rule =
{|
where
rewrite :[a] { "a" -> "qqq" },
rewrite :[rest] { "{ b : { :[other] } }" -> "{ :[other] }" }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|{ { qqq : { c : d } } }|}]
let%expect_test "rewrite_rule_for_list" =
let source = {|[1, 2, 3, 4,]|} in
let match_template = {|[:[contents]]|} in
let rewrite_template = {|[:[contents]]|} in
let rule =
{|
where rewrite :[contents] { ":[[x]]," -> ":[[x]];" }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4;]|}]
let%expect_test "rewrite_rule_for_list_strip_last" =
let source = {|[1, 2, 3, 4]|} in
let match_template = {|[:[contents]]|} in
let rewrite_template = {|[:[contents]]|} in
let rule =
{|
where rewrite :[contents] { ":[x], " -> ":[x]; " }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|[1; 2; 3; 4]|}]
let%expect_test "haskell_example" =
let source = {|
(concat
[ "blah blah blah"
, "blah"
])
|} in
let match_template = {|(concat [:[contents]])|} in
let rewrite_template = {|(:[contents])|} in
let rule =
{|
where rewrite :[contents] { "," -> "++" }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|
( "blah blah blah"
++ "blah"
)
|}]
let%expect_test "rewrite_freeform_antecedent_pattern" =
let source = {|
(concat
[ "blah blah blah"
, "blah"
])
|} in
let match_template = {|:[contents]|} in
let rewrite_template = {|(:[contents])|} in
let rule =
{|
where rewrite :[contents] { concat [:[x]] -> "nice" }
|}
|> Language.Rule.create
|> Or_error.ok_exn
in
run_rule source match_template rewrite_template rule;
[%expect_exact {|(
(nice)
)|}]

View File

@ -1,7 +1,9 @@
open Matchers
let run input =
let result =
match Language.Script.parse input with
| Ok result -> Language.Script.to_string result
match Script.parse input with
| Ok result -> Script.to_string result
| Error _ -> "ERROR"
in
print_string result

View File

@ -1,10 +1,9 @@
open Core
open Match
open Test_helpers
include Test_alpha
open Comby_kernel
open Matchers
open Match
let %expect_test "statistics" =
let template =
@ -28,12 +27,12 @@ let %expect_test "statistics" =
let rule =
{| where true
|}
|> Language.Rule.create
|> Rule.create
|> Or_error.ok_exn
in
Go.all ~configuration ~template ~source ()
Alpha.Go.all ~configuration ~template ~source ()
|> List.filter ~f:(fun { environment; _ } ->
Rule.(sat @@ apply rule environment))
Rule.(sat @@ apply ~match_all:(Alpha.Generic.all ~rule:[Ast.True] ~nested:false) rule environment))
|> fun matches ->
let statistics =
Statistics.

View File

@ -1,41 +1,78 @@
open Core
open Rewriter
open Comby_kernel
open Matchers
open Test_helpers
include Test_alpha
let all ?(configuration = configuration) (module M : Matchers.Matcher.S) template source =
M.all ~configuration ~template ~source ()
let all ?(configuration = configuration) template source =
C.all ~configuration ~template ~source ()
let rewrite_all engine template source rewrite_template =
all engine template source
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT")
let rewrite_all_want_fail_case engine template source rewrite_template =
all engine ~configuration template source
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "EXPECT SUCCESS")
let rewrite_all' engine template source rewrite_template =
all engine template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string
let head_match (module M : Matchers.Matcher.S) template source =
M.all ~configuration ~template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string hd.matched
let%expect_test "comments_in_string_literals_should_not_be_treated_as_comments_by_fuzzy" =
let source = {|"/*"(x)|} in
let template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
all template source
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.C) template source rewrite_template;
[%expect_exact {|"/*"x|}];
rewrite_all (module Omega.C) template source rewrite_template;
[%expect_exact {|"/*"x|}]
let%expect_test "comments_in_string_literals_should_not_be_treated_as_comments_by_fuzzy_go_raw" =
let source = {|`//`(x)|} in
let template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.Go) template source rewrite_template;
[%expect_exact {|`//`x|}];
rewrite_all (module Omega.Go) template source rewrite_template;
[%expect_exact {|`//`x|}]
let%expect_test "tolerate_unbalanced_stuff_in_string_literals" =
let template = {|"("|} in
let source = {|"("|} in
let matches = all ~configuration template source in
print_matches matches;
all (module Alpha.C) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 3, "line": 1, "column": 4 }
},
"environment": [],
"matched": "\"(\""
}
]|}];
all (module Omega.C) ~configuration template source
|> print_matches;
[%expect_exact {|[
{
"range": {
@ -47,116 +84,127 @@ let%expect_test "tolerate_unbalanced_stuff_in_string_literals" =
}
]|}]
let%expect_test "base_literal_matching" =
let source = {|"hello"|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|hello|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|hello|}]
let%expect_test "base_literal_matching" =
let source = {|rewrite ("hello") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|hello|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|hello|}]
let%expect_test "match_string_literals" =
let source = {|rewrite (".") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|.|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|.|}]
let%expect_test "match_string_literals" =
let source = {|rewrite ("") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {||}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {||}]
let%expect_test "match_string_literals" =
let source = {|"(" match "a""a" this "(" |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|"(" "a""a" "(" |}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|"(" "a""a" "(" |}]
(* this tests special functionality in non-literal hole parser
but which must still ignore unbalanced delims within strings *)
let%expect_test "match_string_literals" =
let source = {|"(" match "(""(" this "(" |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|"(" "(""(" "(" |}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|"(" "(""(" "(" |}]
let%expect_test "match_string_literals" =
let source = {|rewrite ("") this string|} in
let match_template = {|rewrite (:[1]) this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|""|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|""|}]
let%expect_test "base_literal_matching" =
let source = {|"("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|(|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|(|}]
let%expect_test "base_literal_matching" =
let source = {|"(""("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|((|}]
let%expect_test "base_literal_matching" =
let source = {|"(""("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|((|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|((|}]
let%expect_test "base_literal_matching" =
let source = {|"(""("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|((|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|((|}]
let%expect_test "base_literal_matching" =
let source = {|"hello world"|} in
let match_template = {|":[x] :[y]"|} in
let rewrite_template = {|:[x] :[y]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|hello world|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|hello world|}]
(* complex test: basically, we are checking that the inside of this literal is only matched by the val b part *)
@ -164,75 +212,76 @@ let%expect_test "base_literal_matching" =
let source = {|val a = "class = ${String::class}" val b = "not $a"|} in
let match_template = {|":[x]$:[[y]]"|} in
let rewrite_template = {|(rewritten part: (:[x]) ([y]))|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|val a = "class = ${String::class}" val b = (rewritten part: (not ) ([y]))|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|val a = "class = ${String::class}" val b = (rewritten part: (not ) ([y]))|}]
let%expect_test "base_literal_matching" =
let source = {|get("type") rekt ("enabled", True)|} in
let match_template = {|(":[1]", :[[3]])|} in
let rewrite_template = {|(rewritten part: (:[1]) (:[3]))|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|get("type") rekt (rewritten part: (enabled) (True))|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|get("type") rekt (rewritten part: (enabled) (True))|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"" this|} in
let match_template = {|match "\"" this|} in
let rewrite_template = "" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {||}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {||}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|"\""|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|"\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|"\"\""|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|"\"\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"(\"" "(\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|"\"(\"" "(\""|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|"\"(\"" "(\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"(\"" "(\"" this|} in
let match_template = {|match ":[1]" ":[2]" this|} in
let rewrite_template = {|:[1] :[2]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|\"(\" (\"|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|\"(\" (\"|}]
let%expect_test "rewrite_string_literals_8" =
@ -240,10 +289,9 @@ let%expect_test "rewrite_string_literals_8" =
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|match 'sin(gle' 'quo(tes' this|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|match 'sin(gle' 'quo(tes' this|}]
let%expect_test "rewrite_string_literals_8" =
@ -251,10 +299,9 @@ let%expect_test "rewrite_string_literals_8" =
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|match '\''|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|match '\''|}]
let%expect_test "rewrite_string_literals_8" =
@ -262,10 +309,9 @@ let%expect_test "rewrite_string_literals_8" =
let match_template = {|':[1]'|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|match asdf|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|match asdf|}]
let%expect_test "rewrite_string_literals_8" =
@ -273,10 +319,9 @@ let%expect_test "rewrite_string_literals_8" =
let match_template = {|':[1]'|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.C) match_template source rewrite_template;
[%expect_exact {|match \'|}];
rewrite_all' (module Omega.C) match_template source rewrite_template;
[%expect_exact {|match \'|}]
@ -293,10 +338,17 @@ let%expect_test "go_raw_string_literals" =
let match_template = {|`:[1]`|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.Go) match_template source rewrite_template;
[%expect_exact {|
x = x
y = multi-line
raw str(ing literal
z = other multi-line
raw stri(ng literal
|}];
rewrite_all' (module Omega.Go) match_template source rewrite_template;
[%expect_exact {|
x = x
y = multi-line
@ -305,25 +357,25 @@ let%expect_test "go_raw_string_literals" =
raw stri(ng literal
|}]
let%expect_test "go_raw_string_literals" =
let source = {|blah `(` quux|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.Go) match_template source rewrite_template;
[%expect_exact {|blah `(` quux|}];
rewrite_all' (module Omega.Go) match_template source rewrite_template;
[%expect_exact {|blah `(` quux|}]
let%expect_test "match_string_literals" =
let source = {|`(` match `(``(` this `(` |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template:match_template ~source ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.Go) match_template source rewrite_template;
[%expect_exact {|`(` `(``(` `(` |}];
rewrite_all' (module Omega.Go) match_template source rewrite_template;
[%expect_exact {|`(` `(``(` `(` |}]
@ -340,10 +392,16 @@ let%expect_test "go_raw_string_literals" =
let match_template = {|`:[1]`|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
rewrite_all' (module Alpha.Go) match_template source rewrite_template;
[%expect_exact {|
x = x
y = multi-line
raw "str"(ing literal
z = other multi-line
raw '"'\"\\s\\\\\tr\ni(ng literal
|}];
rewrite_all' (module Omega.Go) match_template source rewrite_template;
[%expect_exact {|
x = x
y = multi-line
@ -352,15 +410,15 @@ let%expect_test "go_raw_string_literals" =
raw '"'\"\\s\\\\\tr\ni(ng literal
|}]
let%expect_test "regression_matching_kubernetes" =
let source = {|"\n" y = 5|} in
let template = {|y = :[1]|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.Go) template source rewrite_template;
[%expect_exact {|"\n" 5|}];
rewrite_all (module Omega.Go) template source rewrite_template;
[%expect_exact {|"\n" 5|}]
@ -368,33 +426,30 @@ let%expect_test "match_escaped_any_char" =
let source = {|printf("hello world\n");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.Go) template source rewrite_template;
[%expect_exact {|hello world\n|}];
rewrite_all (module Omega.Go) template source rewrite_template;
[%expect_exact {|hello world\n|}]
let%expect_test "match_escaped_escaped" =
let source = {|printf("hello world\n\\");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.Go) template source rewrite_template;
[%expect_exact {|hello world\n\\|}];
rewrite_all (module Omega.Go) template source rewrite_template;
[%expect_exact {|hello world\n\\|}]
let%expect_test "match_escaped_escaped" =
let source = {|printf("hello world\n\");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "EXPECT SUCCESS");
rewrite_all_want_fail_case (module Alpha.Go) template source rewrite_template;
[%expect_exact {|EXPECT SUCCESS|}];
rewrite_all_want_fail_case (module Omega.Go) template source rewrite_template;
[%expect_exact {|EXPECT SUCCESS|}]
let%expect_test "holes_in_raw_literals" =
@ -416,13 +471,17 @@ let%expect_test "holes_in_raw_literals" =
)
|} in
let template = {|`:[1]`|} in
begin
Typescript.all ~configuration ~template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string hd.matched
end;
head_match (module Alpha.Typescript) template source;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`|}];
head_match (module Omega.Typescript) template source;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
@ -431,6 +490,7 @@ let%expect_test "holes_in_raw_literals" =
}
`|}]
let%expect_test "holes_in_raw_literals_partial" =
let source = {|
return expect(
@ -450,13 +510,19 @@ let%expect_test "holes_in_raw_literals_partial" =
)
|} in
let template = {|` query ResolveRepo(:[1]) {:[2]} `|} in
begin
Typescript.all ~configuration ~template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string hd.matched
end;
head_match (module Alpha.Typescript) template source;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`|}];
head_match (module Omega.Typescript) template source;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
@ -465,15 +531,15 @@ let%expect_test "holes_in_raw_literals_partial" =
}
`|}]
let%expect_test "dont_detect_comments_in_strings_with_hole_matcher" =
let source = {|"// not a comment"|} in
let template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
rewrite_all (module Alpha.Go) template source rewrite_template;
[%expect_exact {|// not a comment|}];
rewrite_all (module Omega.Go) template source rewrite_template;
[%expect_exact {|// not a comment|}]
(* Deactivated: this will conflict with division syntax *)

View File

@ -1,491 +0,0 @@
open Core
open Rewriter
open Test_helpers
include Test_omega
let all ?(configuration = configuration) template source =
C.all ~configuration ~template ~source ()
let%expect_test "comments_in_string_literals_should_not_be_treated_as_comments_by_fuzzy" =
let source = {|"/*"(x)|} in
let template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
all template source
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|"/*"x|}]
let%expect_test "comments_in_string_literals_should_not_be_treated_as_comments_by_fuzzy_go_raw" =
let source = {|`//`(x)|} in
let template = {|(:[1])|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|`//`x|}]
let%expect_test "tolerate_unbalanced_stuff_in_string_literals" =
let template = {|"("|} in
let source = {|"("|} in
let matches = all ~configuration template source in
print_matches matches;
[%expect_exact {|[
{
"range": {
"start": { "offset": 0, "line": 1, "column": 1 },
"end": { "offset": 3, "line": 1, "column": 4 }
},
"environment": [],
"matched": "\"(\""
}
]|}]
let%expect_test "base_literal_matching" =
let source = {|"hello"|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|hello|}]
let%expect_test "base_literal_matching" =
let source = {|rewrite ("hello") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|hello|}]
let%expect_test "match_string_literals" =
let source = {|rewrite (".") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|.|}]
let%expect_test "match_string_literals" =
let source = {|rewrite ("") this string|} in
let match_template = {|rewrite (":[1]") this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {||}]
let%expect_test "match_string_literals" =
let source = {|"(" match "a""a" this "(" |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|"(" "a""a" "(" |}]
(* this tests special functionality in non-literal hole parser
but which must still ignore unbalanced delims within strings *)
let%expect_test "match_string_literals" =
let source = {|"(" match "(""(" this "(" |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|"(" "(""(" "(" |}]
let%expect_test "match_string_literals" =
let source = {|rewrite ("") this string|} in
let match_template = {|rewrite (:[1]) this string|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|""|}]
let%expect_test "base_literal_matching" =
let source = {|"("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|(|}]
let%expect_test "base_literal_matching" =
let source = {|"(""("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|((|}]
let%expect_test "base_literal_matching" =
let source = {|"(""("|} in
let match_template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|((|}]
let%expect_test "base_literal_matching" =
let source = {|"hello world"|} in
let match_template = {|":[x] :[y]"|} in
let rewrite_template = {|:[x] :[y]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|hello world|}]
(* complex test: basically, we are checking that the inside of this literal is only matched by the val b part *)
let%expect_test "base_literal_matching" =
let source = {|val a = "class = ${String::class}" val b = "not $a"|} in
let match_template = {|":[x]$:[[y]]"|} in
let rewrite_template = {|(rewritten part: (:[x]) ([y]))|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|val a = "class = ${String::class}" val b = (rewritten part: (not ) ([y]))|}]
let%expect_test "base_literal_matching" =
let source = {|get("type") rekt ("enabled", True)|} in
let match_template = {|(":[1]", :[[3]])|} in
let rewrite_template = {|(rewritten part: (:[1]) (:[3]))|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|get("type") rekt (rewritten part: (enabled) (True))|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"" this|} in
let match_template = {|match "\"" this|} in
let rewrite_template = "" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {||}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|"\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|"\"\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"(\"" "(\"" this|} in
let match_template = {|match :[1] this|} in
let rewrite_template = ":[1]" in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|"\"(\"" "(\""|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match "\"(\"" "(\"" this|} in
let match_template = {|match ":[1]" ":[2]" this|} in
let rewrite_template = {|:[1] :[2]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|\"(\" (\"|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match 'sin(gle' 'quo(tes' this|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|match 'sin(gle' 'quo(tes' this|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match '\''|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|match '\''|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match 'asdf'|} in
let match_template = {|':[1]'|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|match asdf|}]
let%expect_test "rewrite_string_literals_8" =
let source = {|match '\''|} in
let match_template = {|':[1]'|} in
let rewrite_template = {|:[1]|} in
all match_template source
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|match \'|}]
let%expect_test "go_raw_string_literals" =
let source =
{|
x = x
y = `multi-line
raw str(ing literal`
z = `other multi-line
raw stri(ng literal`
|}
in
let match_template = {|`:[1]`|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|
x = x
y = multi-line
raw str(ing literal
z = other multi-line
raw stri(ng literal
|}]
let%expect_test "go_raw_string_literals" =
let source = {|blah `(` quux|} in
let match_template = {|:[1]|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|blah `(` quux|}]
let%expect_test "match_string_literals" =
let source = {|`(` match `(``(` this `(` |} in
let match_template = {|match :[1] this|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template:match_template ~source ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|`(` `(``(` `(` |}]
let%expect_test "go_raw_string_literals" =
let source =
{|
x = x
y = `multi-line
raw "str"(ing literal`
z = `other multi-line
raw '"'\"\\s\\\\\tr\ni(ng literal`
|}
in
let match_template = {|`:[1]`|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~source ~template:match_template ()
|> (fun matches -> Option.value_exn (Rewrite.all ~source ~rewrite_template matches))
|> (fun { rewritten_source; _ } -> rewritten_source)
|> print_string;
[%expect_exact {|
x = x
y = multi-line
raw "str"(ing literal
z = other multi-line
raw '"'\"\\s\\\\\tr\ni(ng literal
|}]
let%expect_test "regression_matching_kubernetes" =
let source = {|"\n" y = 5|} in
let template = {|y = :[1]|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|"\n" 5|}]
let%expect_test "match_escaped_any_char" =
let source = {|printf("hello world\n");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|hello world\n|}]
let%expect_test "match_escaped_escaped" =
let source = {|printf("hello world\n\\");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|hello world\n\\|}]
let%expect_test "match_escaped_escaped" =
let source = {|printf("hello world\n\");|} in
let template = {|printf(":[1]");|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "EXPECT SUCCESS");
[%expect_exact {|EXPECT SUCCESS|}]
let%expect_test "holes_in_raw_literals" =
let source = {|
return expect(
extensionsController.executeCommand({
command: 'queryGraphQL',
arguments: [
`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`,
{ repoName: 'foo' },
],
})
)
|} in
let template = {|`:[1]`|} in
begin
Typescript.all ~configuration ~template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string hd.matched
end;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`|}]
let%expect_test "holes_in_raw_literals_partial" =
let source = {|
return expect(
extensionsController.executeCommand({
command: 'queryGraphQL',
arguments: [
`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`,
{ repoName: 'foo' },
],
})
)
|} in
let template = {|` query ResolveRepo(:[1]) {:[2]} `|} in
begin
Typescript.all ~configuration ~template ~source ()
|> function
| [] -> print_string "No matches."
| hd :: _ ->
print_string hd.matched
end;
[%expect_exact {|`
query ResolveRepo($repoName: String!) {
repository(name: $repoName) {
url
}
}
`|}]
let%expect_test "dont_detect_comments_in_strings_with_hole_matcher" =
let source = {|"// not a comment"|} in
let template = {|":[1]"|} in
let rewrite_template = {|:[1]|} in
Go.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "BROKEN EXPECT");
[%expect_exact {|// not a comment|}]
(* Deactivated: this will conflict with division syntax *)
(*
let%expect_test "match_regex_delimiters" =
let source = {|/f\/oo/ "/bar/"|} in
let template = {|/:[1]/|} in
let rewrite_template = {|:[1]|} in
Typescript.all ~configuration ~template ~source ()
|> Rewrite.all ~source ~rewrite_template
|> (function
| Some { rewritten_source; _ } -> print_string rewritten_source
| None -> print_string "EXPECT SUCCESS");
[%expect_exact {|f\/oo "/bar/"|}]
*)

View File

@ -1,6 +1,8 @@
open Core
open Match
open Matchers
open Rewriter
open Rewrite_template

View File

@ -1,12 +1,11 @@
open Core
open Matchers
open Rewriter
open Comby_kernel
open Matchers
open Test_helpers
let create = Matchers.Alpha.create
let run (module M : Matchers.Matcher.S) source match_template rewrite_template =
let run (module E : Engine.S) user_lang source match_template rewrite_template =
let (module M) = E.create user_lang in
M.first ~configuration match_template source
|> function
| Ok result ->
@ -18,7 +17,7 @@ let run (module M : Matchers.Matcher.S) source match_template rewrite_template =
print_string rewrite_template
let%expect_test "user_defined_language" =
let c =
let user_lang =
Syntax.
{ user_defined_delimiters = [("case", "esac")]
; escapable_string_literals = None
@ -26,7 +25,7 @@ let%expect_test "user_defined_language" =
; comments = [Multiline ("/*", "*/"); Until_newline "//"]
}
in
let user_lang = create c in
let source =
{|
case
@ -50,7 +49,21 @@ let%expect_test "user_defined_language" =
in
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run user_lang source match_template rewrite_template ;
run (module Alpha) user_lang source match_template rewrite_template ;
[%expect_exact {|
case nuked blocks esac
/*
case
ignore this
esac
*/
// case
// ignore this
// esac
|}];
run (module Omega) user_lang source match_template rewrite_template ;
[%expect_exact {|
case nuked blocks esac
/*
@ -63,6 +76,7 @@ let%expect_test "user_defined_language" =
// esac
|}]
let%expect_test "user_defined_language_from_json" =
let json =
{|{
@ -85,14 +99,17 @@ let%expect_test "user_defined_language_from_json" =
Yojson.Safe.from_string json
|> Matchers.Syntax.of_yojson
|> Result.ok_or_failwith
|> create
in
let source = "" in
let match_template = {|""|} in
let rewrite_template = {|""|} in
run user_lang source match_template rewrite_template ;
run (module Alpha) user_lang source match_template rewrite_template ;
[%expect_exact {|""|}];
run (module Omega) user_lang source match_template rewrite_template ;
[%expect_exact {|""|}]
let%expect_test "user_defined_language_from_json_optional_escapable" =
let json =
{|{
@ -111,10 +128,12 @@ let%expect_test "user_defined_language_from_json_optional_escapable" =
Yojson.Safe.from_string json
|> Matchers.Syntax.of_yojson
|> Result.ok_or_failwith
|> create
in
let source = "" in
let match_template = {|""|} in
let rewrite_template = {|""|} in
run user_lang source match_template rewrite_template ;
run (module Alpha) user_lang source match_template rewrite_template ;
[%expect_exact {|""|}];
run (module Omega) user_lang source match_template rewrite_template ;
[%expect_exact {|""|}]

View File

@ -1,120 +0,0 @@
open Core
open Matchers
open Rewriter
open Test_helpers
let create = Matchers.Omega.create
let run (module M : Matchers.Matcher.S) source match_template rewrite_template =
M.first ~configuration match_template source
|> function
| Ok result ->
Rewrite.all ~source ~rewrite_template [result]
|> (fun x -> Option.value_exn x)
|> (fun {rewritten_source; _} -> rewritten_source)
|> print_string
| Error _ ->
print_string rewrite_template
let%expect_test "user_defined_language" =
let c =
Syntax.
{ user_defined_delimiters = [("case", "esac")]
; escapable_string_literals = None
; raw_string_literals = []
; comments = [Multiline ("/*", "*/"); Until_newline "//"]
}
in
let user_lang = create c in
let source =
{|
case
case
block 1
esac
case
block 2
esac
esac
/*
case
ignore this
esac
*/
// case
// ignore this
// esac
|}
in
let match_template = {|case :[1] esac|} in
let rewrite_template = {|case nuked blocks esac|} in
run user_lang source match_template rewrite_template ;
[%expect_exact {|
case nuked blocks esac
/*
case
ignore this
esac
*/
// case
// ignore this
// esac
|}]
let%expect_test "user_defined_language_from_json" =
let json =
{|{
"user_defined_delimiters": [
["case", "esac"]
],
"escapable_string_literals": {
"delimiters": ["\""],
"escape_character": "\\"
},
"raw_string_literals": [],
"comments": [
[ "Multiline", "/*", "*/" ],
[ "Until_newline", "//" ]
]
}
|}
in
let user_lang =
Yojson.Safe.from_string json
|> Matchers.Syntax.of_yojson
|> Result.ok_or_failwith
|> create
in
let source = "" in
let match_template = {|""|} in
let rewrite_template = {|""|} in
run user_lang source match_template rewrite_template ;
[%expect_exact {|""|}]
let%expect_test "user_defined_language_from_json_optional_escapable" =
let json =
{|{
"user_defined_delimiters": [
["case", "esac"]
],
"raw_string_literals": [],
"comments": [
[ "Multiline", "/*", "*/" ],
[ "Until_newline", "//" ]
]
}
|}
in
let user_lang =
Yojson.Safe.from_string json
|> Matchers.Syntax.of_yojson
|> Result.ok_or_failwith
|> create
in
let source = "" in
let match_template = {|""|} in
let rewrite_template = {|""|} in
run user_lang source match_template rewrite_template ;
[%expect_exact {|""|}]