mirror of
https://github.com/comby-tools/comby.git
synced 2024-08-16 16:50:37 +03:00
recursive rules with matcher and merge tests
This commit is contained in:
parent
3512864079
commit
55c793f48f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }
|
3
lib/app/configuration/regex.mli
Normal file
3
lib/app/configuration/regex.mli
Normal file
@ -0,0 +1,3 @@
|
||||
open Comby_kernel
|
||||
|
||||
val to_regex : Matchers.specification -> string
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
@ -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))
|
@ -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)
|
@ -1,5 +0,0 @@
|
||||
type t =
|
||||
{ nested : bool
|
||||
}
|
||||
|
||||
val of_rule : Ast.t -> t
|
@ -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
|
@ -1,5 +0,0 @@
|
||||
include Types
|
||||
|
||||
let create = Parser.create
|
||||
|
||||
include Evaluate
|
@ -1,7 +0,0 @@
|
||||
open Core_kernel
|
||||
|
||||
include module type of Types
|
||||
|
||||
val create : string -> t Or_error.t
|
||||
|
||||
include Engine
|
@ -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
@ -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))
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -1,4 +1,3 @@
|
||||
open Matchers
|
||||
open Match
|
||||
|
||||
type syntax = { variable: string; pattern: string }
|
235
lib/kernel/matchers/rule.ml
Normal file
235
lib/kernel/matchers/rule.ml
Normal 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)
|
@ -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)
|
12
lib/kernel/matchers/specification.ml
Normal file
12
lib/kernel/matchers/specification.ml
Normal 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 }
|
8
lib/kernel/matchers/specification.mli
Normal file
8
lib/kernel/matchers/specification.mli
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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))
|
@ -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 ->
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
open Core
|
||||
|
||||
open Comby
|
||||
open Comby_kernel
|
||||
open Match
|
||||
|
||||
module In = struct
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -1,2 +0,0 @@
|
||||
include Matchers.Alpha
|
||||
module Rule = Language.Rule
|
@ -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
|
||||
|
@ -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
|
||||
|}]
|
@ -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 */|}]
|
@ -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 */|}]
|
@ -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|}]
|
@ -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|}]
|
@ -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|}]
|
@ -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|}]
|
@ -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
|
||||
|
@ -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|.)*?(\})|}];
|
||||
|
@ -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
|
@ -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
|
||||
|}]
|
@ -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|}]
|
@ -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|}]
|
@ -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 ())
|
||||
|
@ -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< >[][]< >{ { } }<|}];
|
@ -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< >[][]< >{ { } }<|}]
|
@ -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)}
|
@ -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)}
|
||||
|}]
|
@ -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 {|
|
||||
[] |}]
|
@ -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 {|
|
||||
[] |}];
|
27
test/common/test_nested_comments.ml
Normal file
27
test/common/test_nested_comments.ml
Normal 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 {|[]|}];
|
@ -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 {|[]|}];
|
@ -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 {|[]|}];
|
@ -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))
|
@ -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)
|
||||
|}]
|
@ -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)
|
||||
|
@ -1,2 +0,0 @@
|
||||
include Matchers.Omega
|
||||
module Rule = Language.Rule
|
@ -1,5 +1,6 @@
|
||||
open Core
|
||||
|
||||
open Matchers
|
||||
open Rewriter
|
||||
open Rewrite_template
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
open Core
|
||||
|
||||
open Language
|
||||
open Comby_kernel
|
||||
open Matchers
|
||||
open Rule
|
||||
|
||||
let rule_parses rule =
|
||||
match Rule.create rule with
|
||||
|
@ -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 =
|
@ -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|}]
|
||||
*)
|
@ -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" =
|
@ -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 {|[ "\"\"\"\\\"\"\"" ]|}]
|
||||
*)
|
@ -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)
|
@ -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)
|
||||
|}]
|
@ -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)))
|
||||
|}]
|
||||
|
@ -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)
|
||||
)|}]
|
@ -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)
|
||||
)|}]
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 *)
|
@ -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/"|}]
|
||||
*)
|
@ -1,6 +1,8 @@
|
||||
open Core
|
||||
|
||||
open Match
|
||||
|
||||
open Matchers
|
||||
open Rewriter
|
||||
open Rewrite_template
|
||||
|
||||
|
@ -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 {|""|}]
|
@ -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 {|""|}]
|
Loading…
Reference in New Issue
Block a user