1 | // |
2 | // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. |
3 | // Use of this source code is governed by a BSD-style license that can be |
4 | // found in the LICENSE file. |
5 | // |
6 | |
7 | #include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h" |
8 | |
9 | #include "compiler/translator/IntermNode.h" |
10 | #include "compiler/translator/tree_util/IntermNode_util.h" |
11 | #include "compiler/translator/tree_util/IntermTraverse.h" |
12 | |
13 | namespace sh |
14 | { |
15 | |
16 | namespace |
17 | { |
18 | |
19 | // "x || y" is equivalent to "x ? true : y". |
20 | TIntermTernary *UnfoldOR(TIntermTyped *x, TIntermTyped *y) |
21 | { |
22 | return new TIntermTernary(x, CreateBoolNode(true), y); |
23 | } |
24 | |
25 | // "x && y" is equivalent to "x ? y : false". |
26 | TIntermTernary *UnfoldAND(TIntermTyped *x, TIntermTyped *y) |
27 | { |
28 | return new TIntermTernary(x, y, CreateBoolNode(false)); |
29 | } |
30 | |
31 | // This traverser identifies all the short circuit binary nodes that need to |
32 | // be replaced, and creates the corresponding replacement nodes. However, |
33 | // the actual replacements happen after the traverse through updateTree(). |
34 | |
35 | class UnfoldShortCircuitASTTraverser : public TIntermTraverser |
36 | { |
37 | public: |
38 | UnfoldShortCircuitASTTraverser() : TIntermTraverser(true, false, false) {} |
39 | |
40 | bool visitBinary(Visit visit, TIntermBinary *) override; |
41 | }; |
42 | |
43 | bool UnfoldShortCircuitASTTraverser::visitBinary(Visit visit, TIntermBinary *node) |
44 | { |
45 | TIntermTernary *replacement = nullptr; |
46 | |
47 | switch (node->getOp()) |
48 | { |
49 | case EOpLogicalOr: |
50 | replacement = UnfoldOR(node->getLeft(), node->getRight()); |
51 | break; |
52 | case EOpLogicalAnd: |
53 | replacement = UnfoldAND(node->getLeft(), node->getRight()); |
54 | break; |
55 | default: |
56 | break; |
57 | } |
58 | if (replacement) |
59 | { |
60 | queueReplacement(replacement, OriginalNode::IS_DROPPED); |
61 | } |
62 | return true; |
63 | } |
64 | |
65 | } // anonymous namespace |
66 | |
67 | void UnfoldShortCircuitAST(TIntermBlock *root) |
68 | { |
69 | UnfoldShortCircuitASTTraverser traverser; |
70 | root->traverse(&traverser); |
71 | traverser.updateTree(); |
72 | } |
73 | |
74 | } // namespace sh |
75 | |