[go: nahoru, domu]

1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/*
2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License.
6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at
7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar *
10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software
11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and
14d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License.
15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */
16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.expr;
18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer;
20fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
21e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mountimport android.databinding.tool.writer.KCode;
22d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
232611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport java.util.ArrayList;
24d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet;
25d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
26d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
27d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class TernaryExpr extends Expr {
28d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    TernaryExpr(Expr pred, Expr ifTrue, Expr ifFalse) {
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        super(pred, ifTrue, ifFalse);
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr getPred() {
337920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        return getChildren().get(0);
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr getIfTrue() {
377920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        return getChildren().get(1);
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public Expr getIfFalse() {
417920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        return getChildren().get(2);
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
44d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
45d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    protected String computeUniqueKey() {
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return "?:" + super.computeUniqueKey();
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
50d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public String getInvertibleError() {
51d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        if (getPred().isDynamic()) {
52d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            return "The condition of a ternary operator must be constant: " +
53d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                    getPred().toFullCode();
54d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
55d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        final String trueInvertible = getIfTrue().getInvertibleError();
56d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        if (trueInvertible != null) {
57d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            return trueInvertible;
58d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        } else {
59d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            return getIfFalse().getInvertibleError();
60d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
61d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
62d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
63d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    @Override
6479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
6591beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        final Expr ifTrue = getIfTrue();
6691beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        final Expr ifFalse = getIfFalse();
6791beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        if (isNullLiteral(ifTrue)) {
6891beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount            return ifFalse.getResolvedType();
6991beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        } else if (isNullLiteral(ifFalse)) {
7091beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount            return ifTrue.getResolvedType();
7191beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        }
7279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return modelAnalyzer.findCommonParentOf(getIfTrue().getResolvedType(),
737920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount                getIfFalse().getResolvedType());
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
7691beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount    private static boolean isNullLiteral(Expr expr) {
7791beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        final ModelClass type = expr.getResolvedType();
7891beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount        return (type.isObject() && (expr instanceof SymbolExpr) &&
7991beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount                "null".equals(((SymbolExpr)expr).getText()));
8091beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount    }
8191beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
83d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    protected List<Dependency> constructDependencies() {
849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        List<Dependency> deps = new ArrayList<Dependency>();
857920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        Expr predExpr = getPred();
8609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar        final Dependency pred = new Dependency(this, predExpr);
8709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar        pred.setMandatory(true);
8809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar        deps.add(pred);
8909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar
907920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        Expr ifTrueExpr = getIfTrue();
917920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        if (ifTrueExpr.isDynamic()) {
927920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount            deps.add(new Dependency(this, ifTrueExpr, predExpr, true));
93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
947920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        Expr ifFalseExpr = getIfFalse();
957920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        if (ifFalseExpr.isDynamic()) {
967920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount            deps.add(new Dependency(this, ifFalseExpr, predExpr, false));
97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return deps;
99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    protected BitSet getPredicateInvalidFlags() {
1037920e17f7b501d5792e7e3250e9dbb69eca86adeGeorge Mount        return getPred().getInvalidFlags();
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Override
107d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    protected KCode generateCode(boolean expand) {
108e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount        return new KCode()
109d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .app("", getPred().toCode(expand))
110d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .app(" ? ", getIfTrue().toCode(expand))
111d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .app(" : ", getIfFalse().toCode(expand));
112e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount
113e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount    }
114e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount
115e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount    @Override
116d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    public KCode toInverseCode(KCode variable) {
117d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        return new KCode()
118d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .app("if (", getPred().toCode(true))
119d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .app(") {")
120d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .tab(getIfTrue().toInverseCode(variable))
121d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .nl(new KCode("} else {"))
122d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .tab(getIfFalse().toInverseCode(variable))
123d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                .nl(new KCode("}"));
124d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    }
125d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
126d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount    @Override
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public boolean isConditional() {
128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        return true;
129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
131