diff --git a/src/atom_finder/classifier/operator-precedence.clj b/src/atom_finder/classifier/operator-precedence.clj index d12715c..bbe3694 100644 --- a/src/atom_finder/classifier/operator-precedence.clj +++ b/src/atom_finder/classifier/operator-precedence.clj @@ -78,7 +78,9 @@ (order-insensitive-opt-combination (sort combination)) ;;SPECIAL CASE 1: Comma operator in any combination; - (some (partial = :comma) combination))) + (some (partial = :comma) combination) + ;SPECIAL CASE 2: note that the pair name is not [:bitwise_bin :bitwise-bin] + (= [:bitwise--bin :bitwise--bin] combination))) (defn operator-group-pair? [node] @@ -105,12 +107,18 @@ (defn group-pairs-in-node "Returns all operator group pairs in a node" - [node child-groups] - (let [node-group (operator-group node)] + [node child-nodes] + (let [node-group (operator-group node) child-groups (map operator-group child-nodes)] (cond (instance? IASTUnaryExpression node) [[node-group (safe-nth child-groups 0)]] + ;;SPECIAL CASE 2: Two bitwise_bins that are not the same, note that the group pair name is not [:bitwise_bin and bitwise_bin] + (and (and (= :bitwise_bin node-group) + (= :bitwise_bin (safe-nth child-groups 1))) + (not (= (.getOperator node) (.getOperator (safe-nth child-nodes 1))))) + [[:bitwise--bin :bitwise--bin]] + (instance? IASTBinaryExpression node) (-> node unary-before-binary-pairs @@ -129,16 +137,14 @@ ([node collection] (->> collection - (map operator-group) (group-pairs-in-node node) (remove (partial some nil?))))) (defn operator-precedence-atom? "Is this node an operator-precedence-atom?" [node] - (and - (operator-group-pair? node) + (and (operator-group-pair? node) - (not (= :assign (operator-group node))) + (not (= :assign (operator-group node))) - (some confusing-operator-combination? (group-pair node)))) + (some confusing-operator-combination? (group-pair node)))) diff --git a/src/atom_finder/questions/redundant_parentheses.clj b/src/atom_finder/questions/redundant_parentheses.clj new file mode 100644 index 0000000..cf3d8e2 --- /dev/null +++ b/src/atom_finder/questions/redundant_parentheses.clj @@ -0,0 +1,112 @@ +(ns atom-finder.questions.redundant-parentheses + (:require + [clj-jgit.internal :as giti] + [clj-jgit.porcelain :as gitp] + [clj-jgit.querying :as gitq] + [atom-finder.patch :refer :all] + [atom-finder.atom-patch :refer :all] + [atom-finder.constants :refer :all] + [atom-finder.util :refer :all] + [atom-finder.classifier :refer [operator-group confusing-operator-combination? + operator-precedence-atom?]] + [clojure.pprint :refer [pprint]] + [clojure.string :as string] + ) + (:import + [org.eclipse.cdt.core.dom.ast IASTBinaryExpression] + [org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTConditionalExpression] + )) + +(defn paren-in-children + [node] + (find-first paren-node? (children node))) + +(defn redundant-paren? + [node] + (when-let* [paren-test (paren-node? node) + parent-level (precedence-level (safe-parent node)) + children-level (precedence-level(first (children node)))] + (or (< children-level parent-level) + (and (= children-level parent-level) + (= node (first (children (safe-parent node)))))))) + +(defn atom-without-paren? + "Given a parenthesis node, would this be an operator-precedence-atom without the parentheses?" + [node] + (when-let* [parent-node (safe-parent node) + parent-group (operator-group parent-node) + child-group (operator-group (first (children node))) + opt-group-combination [parent-group child-group]] + + (cond + + (and (and (= :bitwise_bin parent-group) + (= parent-group child-group)) + (not (= (.getOperator parent-node) (.getOperator (first (children node)))))) + [:bitwise_bin :bitwise_bin] + + + (and (or (instance? IASTBinaryExpression parent-node) + (instance? CPPASTConditionalExpression parent-node)) + (= node (first (children parent-node)))) + (confusing-operator-combination? (reverse opt-group-combination)) + + :else(confusing-operator-combination? opt-group-combination)))) + +; +;========GENERAL TESTING============== +; +(->> "(fclose(f1a) | EOF) & (fclose(f1b) | EOF)" parse-expr + ;print-tree + (get-in-tree [0]) + ;print-tree + ;redundant-paren? + atom-without-paren? +) + +(->> "a | b & c" parse-expr + ;(get-in-tree [0]) + operator-precedence-atom? + ) + +(def codebase_name "wcdb") + +; +;=======CODEBASE DATA GATHERING========== +; +(->> (str "d:/Codebases/" codebase_name) + (pmap-dir-trees (fn [root] (filter-tree + redundant-paren? + ;#(and (redundant-paren? %)(atom-without-paren? %)) + ;operator-precedence-atom? + root))) + flatten + (remove nil?) + ;(map safe-parent) + ;(map write-ast) + ;(map #(spit "underclas-atom-without.txt" (str % "\r\n") :append true)) + ;(take 100) + + ;((fn [a] (prn (count a)) a)) + (map atom-without-paren?) + ;(map operator-precedence-atom?) + (remove (fn [input] (or (nil? input) (false? input)))) + frequencies + (sort-by last) + (map #(spit (str "c:/Users/Henry/Desktop/stuff/would-be-atoms/" (str codebase_name "-rpa.txt")) (str % "\r\n") :append true)) + + count + prn + dorun + time-mins) + +;IASTNode total: 31886519 + +;redundant-total: 392166 + +;Underclassify: +;would-be-atom: 66037 + +;Overclassify: +;would-be-atom: 75855 + diff --git a/src/atom_finder/util/10_clj_util.clj b/src/atom_finder/util/10_clj_util.clj index b93d08e..caad384 100644 --- a/src/atom_finder/util/10_clj_util.clj +++ b/src/atom_finder/util/10_clj_util.clj @@ -96,6 +96,13 @@ ~else) then))) +(defmacro when-let* + [bindings & then] + (if (seq bindings) + `(when-let [~(first bindings) ~(second bindings)] + (when-let* ~(drop 2 bindings) ~@then)) + `(do ~@then))) + (defn bin "Convert a value to 1 or 0 based on its truthiness" [bool] (if bool 1 0)) diff --git a/src/atom_finder/util/cdt_util.clj b/src/atom_finder/util/cdt_util.clj index 5902aec..742d0bc 100644 --- a/src/atom_finder/util/cdt_util.clj +++ b/src/atom_finder/util/cdt_util.clj @@ -248,20 +248,6 @@ (defn all-comments [node] (->> node root-ancestor .getComments (into []))) -(defn print-node-context - "Print the line that contains the node and the lines around it" - ([node] (print-node-context 2 node)) - ([n-lines node] - (with-open [rdr (clojure.java.io/reader (.getContainingFilename node))] - (let [line-num (start-line node) - file-seq (line-seq rdr) - first-line (max 0 (- line-num n-lines 1)) - lines-to-print (->> file-seq (drop first-line) (take (+ n-lines 1 n-lines)))] - (println "===================================================") - (doseq-indexed [line lines-to-print idx] - (println (str (+ idx first-line) (if (= (+ idx first-line 1) line-num) " >> " " ") line))) - (println "==================================================="))))) - (defn count-nodes "Count the size of the ast" [node] diff --git a/src/atom_finder/util/classifier_util.clj b/src/atom_finder/util/classifier_util.clj index c2fc104..ae1af88 100644 --- a/src/atom_finder/util/classifier_util.clj +++ b/src/atom_finder/util/classifier_util.clj @@ -4,7 +4,7 @@ IASTBinaryExpression IASTLiteralExpression IASTForStatement IASTFunctionDefinition IASTArraySubscriptExpression IASTCastExpression IASTFunctionCallExpression IASTFieldReference IASTFunctionDefinition) - '(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTExpressionList CPPASTConditionalExpression)) + '(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTQualifiedName CPPASTExpressionList CPPASTConditionalExpression CPPASTNewExpression CPPASTDeleteExpression)) (defn function-node? [node] (instance? IASTFunctionDefinition node)) @@ -214,14 +214,16 @@ (defn in-function? [node] (ancestral-instance? IASTFunctionDefinition node)) -;;Note: Operators missing from the list: (scope/ resolution ::) (memory allocation/ new new[] delete delete[]) (pointer-to-member/ ->* .*) (defmulti precedence-level "returns the precedence level of the node" class) (defmethod precedence-level :default [node] (let [precedence-list - {IASTArraySubscriptExpression 2 + {CPPASTQualifiedName 1 + IASTArraySubscriptExpression 2 IASTFieldReference 2 IASTCastExpression 2 IASTFunctionCallExpression 2 + CPPASTNewExpression 3 + CPPASTDeleteExpression 3 CPPASTConditionalExpression 15 CPPASTExpressionList 16}] (precedence-list (type node)))) @@ -242,7 +244,9 @@ (precedence-list (.getOperator node)))) (defmethod precedence-level IASTBinaryExpression [node] (let [precedence-list - {IASTBinaryExpression/op_modulo 5 + {IASTBinaryExpression/op_pmdot 4 + IASTBinaryExpression/op_pmarrow 4 + IASTBinaryExpression/op_modulo 5 IASTBinaryExpression/op_multiply 5 IASTBinaryExpression/op_divide 5 IASTBinaryExpression/op_plus 6 diff --git a/src/atom_finder/util/writer-util.clj b/src/atom_finder/util/writer-util.clj index b03fcbc..e40749f 100644 --- a/src/atom_finder/util/writer-util.clj +++ b/src/atom_finder/util/writer-util.clj @@ -23,6 +23,21 @@ node 1 [])) +(defn print-node-context + "Print the line that contains the node and the lines around it" + ([node] (print-node-context 2 node)) + ([n-lines node] + (with-open [rdr (clojure.java.io/reader (.getContainingFilename node))] + (let [line-num (start-line node) + file-seq (line-seq rdr) + first-line (max 0 (- line-num n-lines 1)) + lines-to-print (->> file-seq (drop first-line) (take (+ n-lines 1 n-lines)))] + (println "===================================================") + (doseq-indexed [line lines-to-print idx] + (println (str (+ idx first-line) (if (= (+ idx first-line 1) line-num) " >> " " ") line))) + (println "==================================================="))))) + + (def ast-writer (ASTWriter.)) (defn write-ast [node] (.write ast-writer node)) diff --git a/src/conf/henry.edn b/src/conf/henry.edn index 68e76b2..47278eb 100644 --- a/src/conf/henry.edn +++ b/src/conf/henry.edn @@ -1,5 +1,5 @@ { - :gcc-path "~/opt/src/gcc", - :ag-path "~/opt/src/the_silver_searcher", - :github-top-c "~/opt/src/github-top-c" + :gcc-path "d:/Codebases/gcc/opt/src/gcc", + :ag-path "d:/Codebases/gcc/opt/src/the_silver_searcher", + :github-top-c "d:/Codebases/gcc/opt/src/github-top-c" } diff --git a/src/test/resources/operator-precedence.c b/src/test/resources/operator-precedence.c index af73e65..e570e82 100644 --- a/src/test/resources/operator-precedence.c +++ b/src/test/resources/operator-precedence.c @@ -166,4 +166,7 @@ int main(){ ~str++;// --~str; + + a = a << 1 << 2; //, underclassify + a = a | 2 & 3; // }