NOTE: this code is made available for the interest of the community, but is provided with absolutely no WARRANTY or SUPPORT of any kind. If you have questions about the code, feel free to contact us, but we may not be able to help you. Suggestions for improvements are also likely to be ignored. Instead, we encourage you to take the approach (and the code) and develop it into a proper, user-friendly, powerful, code refactoring tool.
Thanks! - LexiFi
grep_cmt is a command-line tool written at LexiFi to perform structural search
of OCaml code.
The code is released as-is in case it is of interest to the community. The present code is extracted from a version used internally at LexiFi and we do not pretend that it is ready for public consumption, but we are making the code available to publicize the approach.
dune buildThe tool requires OCaml 5.2 (since it depends on compiler-libs, compilation
aginst other versions of OCaml will require some adjustments).
This produces an executable _build/install/bin/grep_cmt.exe which can be run
from the command line.
grep_cmt PATTERNThe tool assumes that it is executed within a Dune workspace, as it has a number of heuristics that will not work otherwise. The tool will search the files under the current directory subtree.
You will need to run dune build @check in your project to ensure all .cmt
files are up-to-date before using grep_cmt.
PATTERN: The pattern to search for. This should be a valid OCaml expression.
-
The wildcard
__matches any expression or any record field. -
A numbered wildcard
__1,__2, ... matches any expression or record field and enforce strict equality of all the matching occurrences for the same number. -
An identifier (value or class) is matched as a suffix of the fully qualified path in the typed expression.
-
Labels and constructors identifiers are matched as a suffix of the identifier in the typed expression.
-
For function applications, it is allowed to omit in the pattern any argument of the actual function call; special forms are recognized to enforce that a given optional argument present or missing:
foo ?arg:PRESENT foo ?arg:MISSING -
An expression
(... : typexpr)matches any expression matching...and whose type is equal totypexpr. -
For
try..with/match..with/functionsexpressions, the order of clauses doesn't matter. A single clause of the searched expression can match several clauses of the code. Same set-semantics for record expressions. -
An expression
e1.lid1matchese2.lid2 <- e3ife1matchese2and the labellid1matcheslid2. -
The expression
__.idmatches any pattern of the form{...; P.id; ...}for any prefixP. This rule was added so that grepping for__.foowill return every "get" and "set" of the record fieldfoo, including reads in patterns.
grep_cmt 'List.filter'
grep_cmt '(__ (__ : floatarray): float array)'
grep_cmt 'List.rev __ @ __'
grep_cmt 'match __ with None -> __ | Some __1 -> Some __1'
grep_cmt 'List.fold_left __ __ (List.map __ __)'
grep_cmt 'Stdlib.max (__:float) __'