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
13namespace sh
14{
15
16namespace
17{
18
19// "x || y" is equivalent to "x ? true : y".
20TIntermTernary *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".
26TIntermTernary *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
35class UnfoldShortCircuitASTTraverser : public TIntermTraverser
36{
37 public:
38 UnfoldShortCircuitASTTraverser() : TIntermTraverser(true, false, false) {}
39
40 bool visitBinary(Visit visit, TIntermBinary *) override;
41};
42
43bool 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
67void UnfoldShortCircuitAST(TIntermBlock *root)
68{
69 UnfoldShortCircuitASTTraverser traverser;
70 root->traverse(&traverser);
71 traverser.updateTree();
72}
73
74} // namespace sh
75