Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

infix-operator-precedence atom #10

Merged
merged 23 commits into from
Jul 11, 2017
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
319 changes: 319 additions & 0 deletions hs_err_pid10868.log

Large diffs are not rendered by default.

327 changes: 327 additions & 0 deletions hs_err_pid7776.log

Large diffs are not rendered by default.

2,383 changes: 2,383 additions & 0 deletions replay_pid10868.log

Large diffs are not rendered by default.

3,125 changes: 3,125 additions & 0 deletions replay_pid7776.log

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion src/atom_finder/atoms_in_dir.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
))

(defn print-atoms-in-dir
"Find all preprocessor directives not at the top level in directory"
[dirname atoms]
(->> dirname
(pmap-dir-files
Expand Down
2 changes: 1 addition & 1 deletion src/atom_finder/classifier.clj
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
(ValidatedAtom :omitted-curly-braces omitted-curly-braces-atom? (default-finder omitted-curly-braces-atom?))
(ValidatedAtom :assignment-as-value assignment-as-value-atom? (default-finder assignment-as-value-atom?))
(ValidatedAtom :macro-operator-precedence macro-def-precedence-atom? macro-operator-precedence-atoms)
]
(ValidatedAtom :operator-precedence operator-precedence-atom? (default-finder operator-precedence-atom?))]
)

(def atom-lookup (into {} (map #(vector (:name %1) %1) atoms)))
10 changes: 0 additions & 10 deletions src/atom_finder/classifier/assignment-as-value.clj
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
(in-ns 'atom-finder.classifier)

(defn assignment?
"Is this node an assignment expression"
[node]
(and (instance? IASTBinaryExpression node)
(contains? #{IASTBinaryExpression/op_assign IASTBinaryExpression/op_binaryAndAssign IASTBinaryExpression/op_binaryXorAssign
IASTBinaryExpression/op_divideAssign IASTBinaryExpression/op_minusAssign
IASTBinaryExpression/op_moduloAssign IASTBinaryExpression/op_multiplyAssign IASTBinaryExpression/op_plusAssign
IASTBinaryExpression/op_shiftLeftAssign IASTBinaryExpression/op_shiftRightAssign}
(.getOperator node))))

(defn assignment-as-value-atom? [node]
(and (not (any-pred? #(% node) [(partial instance? IASTExpressionList)
(partial instance? IASTExpressionStatement)
Expand Down
10 changes: 2 additions & 8 deletions src/atom_finder/classifier/logic-as-control-flow.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@
(defn mutatable-op?
"can this AST node change program state?"
[node]
(let [b-ops #{ ; binary operators with side-effects
IASTBinaryExpression/op_assign IASTBinaryExpression/op_binaryAndAssign
IASTBinaryExpression/op_binaryXorAssign IASTBinaryExpression/op_divideAssign
IASTBinaryExpression/op_minusAssign IASTBinaryExpression/op_moduloAssign
IASTBinaryExpression/op_multiplyAssign IASTBinaryExpression/op_plusAssign
IASTBinaryExpression/op_shiftLeftAssign IASTBinaryExpression/op_shiftRightAssign}
u-ops #{ ; unary operators with side-effects
(let [u-ops #{ ; unary operators with side-effects
IASTUnaryExpression/op_postFixDecr IASTUnaryExpression/op_postFixIncr
IASTUnaryExpression/op_prefixDecr IASTUnaryExpression/op_prefixIncr}]
(cond
(leaf? node) false
(instance? IASTBinaryExpression node) (contains? b-ops (.getOperator node))
(instance? IASTBinaryExpression node) (assignment? node)
(instance? IASTUnaryExpression node) (contains? u-ops (.getOperator node))
:else (= (typename node) "FunctionCallExpression"))))

Expand Down
130 changes: 130 additions & 0 deletions src/atom_finder/classifier/operator-precedence.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
(in-ns 'atom-finder.classifier)
(import '(org.eclipse.cdt.core.dom.ast IASTBinaryExpression IASTConditionalExpression IASTUnaryExpression)
'(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTConditionalExpression CPPASTExpressionList CPPASTFieldReference))

(defmulti operator-group"Returns the name of the operator group that the node belongs to, nil not defined in this operator-group" class)
(defmethod operator-group :default [node]
(let [operator-group-table
{CPPASTConditionalExpression :cond
CPPASTExpressionList :comma
CPPASTFieldReference :field_ref}]
(->> node type operator-group-table)))
(defmethod operator-group IASTUnaryExpression [node]
(let [operator-group-table
{IASTUnaryExpression/op_postFixDecr :de_incr
IASTUnaryExpression/op_postFixIncr :de_incr
IASTUnaryExpression/op_minus :arith_unary
IASTUnaryExpression/op_plus :arith_unary
IASTUnaryExpression/op_prefixDecr :de_incr
IASTUnaryExpression/op_prefixIncr :de_incr
IASTUnaryExpression/op_amper :pointer
IASTUnaryExpression/op_star :pointer
IASTUnaryExpression/op_not :not
IASTUnaryExpression/op_tilde :bitwise}]
(->> node .getOperator operator-group-table)))
(defmethod operator-group IASTBinaryExpression [node]
(if (assignment? node)
:assign

(let [operator-group-table
{IASTBinaryExpression/op_modulo :non-asso
IASTBinaryExpression/op_multiply :multiply
IASTBinaryExpression/op_divide :non-asso
IASTBinaryExpression/op_plus :add
IASTBinaryExpression/op_minus :non-asso
IASTBinaryExpression/op_shiftLeft :bitwise
IASTBinaryExpression/op_shiftRight :bitwise
IASTBinaryExpression/op_greaterThan :compare
IASTBinaryExpression/op_greaterEqual :compare
IASTBinaryExpression/op_lessThan :compare
IASTBinaryExpression/op_lessEqual :compare
IASTBinaryExpression/op_equals :compare
IASTBinaryExpression/op_notequals :compare
IASTBinaryExpression/op_binaryAnd :bitwise
IASTBinaryExpression/op_binaryXor :bitwise
IASTBinaryExpression/op_binaryOr :bitwise
IASTBinaryExpression/op_logicalAnd :and
IASTBinaryExpression/op_logicalOr :or}]
(->> node .getOperator operator-group-table))))


(defn specific-confusing-operator-combination?
"if the combination of groups of operators exists in this set, then the combination is confusing"
[combination]
(some #(= % combination) (map sort [[:de_incr :pointer] [:multiply :add] [:arith_unary :add] [:arith_unary :multiply]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure it's not wrong to not sort combination I feel like it'll actually get the wrong answer 50% of the time?

Also, this function has to do 60 comparisons or something. But if you put all the operator combinations into a set and store that using def, then use a set lookup, it's only a single comparison. 60x speedup.

(def confusing-combinations (into #{} (map sort [[:de_incr :pointer] [:multiply :add] ...])))
(defn specific-confusing-operator-combination? [combination] (confusing-combinations (sort combination)))

[:and :add] [:and :multiply] [:and :arith_unary] [:or :add]
[:or :multiply] [:or :arith_unary] [:or :and] [:not :add]
[:not :multiply] [:not :arith_unary] [:not :and] [:not :or]
;;[:compare :and] [:compare :or] // Underclassify
[:compare :not] [:compare :compare] [:pointer :add] [:cond :arith_unary]
[:cond :and] [:cond :or] [:cond :not] [:cond :compare]
[:cond :cond] [:non-asso :add] [:non-asso :multiply] [:non-asso :arith_unary]
[:non-asso :and] [:non-asso :or] [:non-asso :not] [:non-asso :non-asso]
[:field_ref :pointer]])))

(def always-confusing-operator-groups
"If any of these operator groups is used along with another operator, then it is confusing"
#{:bitwise :comma})

(defn confusing-operator-combination?
"Is this combination of the operator groups confusing?"
[combination]
(or (specific-confusing-operator-combination? combination)
(some (partial contains? always-confusing-operator-groups) combination)))

(defn operator-group-pair?
[node]
(and (operator-group node)
(some operator-group (children node))))

(defn group-pair
"returns a collection of operator group pairs between the node and its children
, if a second parameter is passed, use that as the collection instead of the children"
([node]
(group-pair node (children node)))

([node collection]
(->> collection
(map operator-group)
(remove nil?)
(map (fn [child-group] (sort [(operator-group node) child-group]))))))

;;====================================
;;For binary operator special case
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you really mean binary, not unary here?? if so, please explain more, I don't understand

;;====================================
(def rvalue-unary-ops?
"Is this a unary operator that can operate on an rvalue? (! - + *)"
(comp #{:arith_unary :not :pointer} operator-group))

(defn unparenthesized-unary-in-children
"Is this node not a bracket and constains unary operator in its children?"
[node]
(if (not (paren-node? node))
(filter-tree #(rvalue-unary-ops? %) node)))

(defn group-pairs-in-binary-ops
"Special function for returning a collection of operator group in binary operator's children, binary operator should ignore some groups of operators in its second operand"
[node]
(->> (concat [(get-in-tree [0] node)
(if (not (rvalue-unary-ops? (get-in-tree [1] node)))
(get-in-tree [1] node) nil)]

(unparenthesized-unary-in-children (get-in-tree [0] node)))
(map operator-group)
(remove nil?)
(map (fn [child-group] (sort [(operator-group node) child-group])))))
;;====================================
;;


(defn operator-precedence-atom?
"Is this node an operator-precedence-atom?"
[node]
(and
(operator-group-pair? node)

(not (= :assign (operator-group node)))

(if (instance? IASTBinaryExpression node)
(some confusing-operator-combination? (group-pairs-in-binary-ops node))
(some confusing-operator-combination? (group-pair node)))))
71 changes: 70 additions & 1 deletion src/atom_finder/util/classifier_util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
(import '(org.eclipse.cdt.core.dom.ast
IASTNode IASTExpression IASTExpressionList IASTUnaryExpression
IASTBinaryExpression IASTLiteralExpression IASTForStatement
IASTFunctionDefinition))
IASTFunctionDefinition IASTArraySubscriptExpression IASTCastExpression
IASTFunctionCallExpression IASTFieldReference)
'(org.eclipse.cdt.internal.core.dom.parser.cpp CPPASTExpressionList CPPASTConditionalExpression))

(defn default-finder [classifier] (partial filter-tree classifier))
(defn default-finder-context [classifier] (partial filter-tree-context classifier))
Expand Down Expand Up @@ -192,3 +194,70 @@
(recur start-line end-line container))))

(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
IASTFieldReference 2
IASTCastExpression 2
IASTFunctionCallExpression 2
CPPASTConditionalExpression 15
CPPASTExpressionList 16}]
(precedence-list (type node))))
(defmethod precedence-level IASTUnaryExpression [node]
(let [precedence-list
{IASTUnaryExpression/op_postFixDecr 2
IASTUnaryExpression/op_postFixIncr 2
IASTUnaryExpression/op_minus 3
IASTUnaryExpression/op_plus 3
IASTUnaryExpression/op_prefixDecr 3
IASTUnaryExpression/op_prefixIncr 3
IASTUnaryExpression/op_sizeof 3
IASTUnaryExpression/op_amper 3
IASTUnaryExpression/op_star 3
IASTUnaryExpression/op_not 3
IASTUnaryExpression/op_tilde 3
IASTUnaryExpression/op_throw 15}]
(precedence-list (.getOperator node))))
(defmethod precedence-level IASTBinaryExpression [node]
(let [precedence-list
{IASTBinaryExpression/op_modulo 5
IASTBinaryExpression/op_multiply 5
IASTBinaryExpression/op_divide 5
IASTBinaryExpression/op_plus 6
IASTBinaryExpression/op_minus 6
IASTBinaryExpression/op_shiftLeft 7
IASTBinaryExpression/op_shiftRight 7
IASTBinaryExpression/op_greaterThan 8
IASTBinaryExpression/op_greaterEqual 8
IASTBinaryExpression/op_lessThan 8
IASTBinaryExpression/op_lessEqual 8
IASTBinaryExpression/op_equals 9
IASTBinaryExpression/op_notequals 9
IASTBinaryExpression/op_binaryAnd 10
IASTBinaryExpression/op_binaryXor 11
IASTBinaryExpression/op_binaryOr 12
IASTBinaryExpression/op_logicalAnd 13
IASTBinaryExpression/op_logicalOr 14
IASTBinaryExpression/op_assign 15
IASTBinaryExpression/op_binaryAndAssign 15
IASTBinaryExpression/op_binaryOrAssign 15
IASTBinaryExpression/op_binaryXorAssign 15
IASTBinaryExpression/op_divideAssign 15
IASTBinaryExpression/op_minusAssign 15
IASTBinaryExpression/op_moduloAssign 15
IASTBinaryExpression/op_multiplyAssign 15
IASTBinaryExpression/op_plusAssign 15
IASTBinaryExpression/op_shiftLeftAssign 15
IASTBinaryExpression/op_shiftRightAssign 15}]
(precedence-list (.getOperator node))))

(defn assignment?
"Returns true if the operator is an assignment operator"
[node]
(let [assignment-list
#{IASTBinaryExpression/op_assign IASTBinaryExpression/op_binaryAndAssign IASTBinaryExpression/op_binaryOrAssign IASTBinaryExpression/op_binaryXorAssign IASTBinaryExpression/op_divideAssign IASTBinaryExpression/op_minusAssign IASTBinaryExpression/op_moduloAssign IASTBinaryExpression/op_multiplyAssign IASTBinaryExpression/op_plusAssign IASTBinaryExpression/op_shiftLeftAssign IASTBinaryExpression/op_shiftRightAssign}]

(and (instance? IASTBinaryExpression node) (contains? assignment-list (.getOperator node)))))
1 change: 1 addition & 0 deletions src/atom_finder/util/writer-util.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
(.replaceAll "\n" " \\ ")))))
node 1 []))


(def ast-writer (ASTWriter.))
(defn write-ast [node] (.write ast-writer node))

Expand Down
Loading