1b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/*
2b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Copyright 2016 Google Inc.
3b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas *
4b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * Use of this source code is governed by a BSD-style license that can be
5b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas * found in the LICENSE file.
6b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */
786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas
8b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#ifndef SKSL_EXPRESSION
9b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#define SKSL_EXPRESSION
10b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
11b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#include "SkSLType.h"
1286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas#include "SkSLVariable.h"
1386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas
1486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas#include <unordered_map>
15b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
16b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasnamespace SkSL {
17b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
1886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasstruct Expression;
1986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholasclass IRGenerator;
2086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas
2186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholastypedef std::unordered_map<const Variable*, std::unique_ptr<Expression>*> DefinitionMap;
2286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas
23b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas/**
2486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas * Abstract supertype of all expressions.
25b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas */
26b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholasstruct Expression : public IRNode {
27b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    enum Kind {
28b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kBinary_Kind,
29b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kBoolLiteral_Kind,
30b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kConstructor_Kind,
31b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kIntLiteral_Kind,
32b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kFieldAccess_Kind,
33b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kFloatLiteral_Kind,
34b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kFunctionReference_Kind,
35b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kFunctionCall_Kind,
36b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kIndex_Kind,
37b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kPrefix_Kind,
38b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kPostfix_Kind,
39762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas        kSetting_Kind,
40b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kSwizzle_Kind,
41b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kVariableReference_Kind,
42b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kTernary_Kind,
43b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        kTypeReference_Kind,
4422f939e849013b7fc51374c289b5bf37e63dfdb1ethannicholas        kDefined_Kind
45b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    };
46b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
475b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    Expression(int offset, Kind kind, const Type& type)
485b5f096a038259b8d9084834f877588a0db80250Ethan Nicholas    : INHERITED(offset)
49b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    , fKind(kind)
50b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    , fType(std::move(type)) {}
51b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
523deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    /**
533deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     * Returns true if this expression is constant. compareConstant must be implemented for all
543deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     * constants!
553deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     */
56b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    virtual bool isConstant() const {
57b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas        return false;
58b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    }
59b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
6086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas    /**
613deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     * Compares this constant expression against another constant expression of the same type. It is
623deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     * an error to call this on non-constant expressions, or if the types of the expressions do not
633deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     * match.
643deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas     */
653deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    virtual bool compareConstant(const Context& context, const Expression& other) const {
663deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas        ABORT("cannot call compareConstant on this type");
673deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    }
683deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas
693deaeb2dc0cfddfdf2e3b64736c860132619a051Ethan Nicholas    /**
708f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     * For an expression which evaluates to a constant int, returns the value. Otherwise calls
718f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     * ABORT.
728f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     */
738f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    virtual int64_t getConstantInt() const {
748f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas        ABORT("not a constant int");
758f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    }
768f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas
778f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    /**
788f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     * For an expression which evaluates to a constant float, returns the value. Otherwise calls
798f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     * ABORT.
808f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas     */
818f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    virtual double getConstantFloat() const {
828f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas        ABORT("not a constant float");
838f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    }
848f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas
858f6c2aba638c9397e9987fca7cbd8d0ff4b23e8fEthan Nicholas    /**
86cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas     * Returns true if evaluating the expression potentially has side effects. Expressions may never
87cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas     * return false if they actually have side effects, but it is legal (though suboptimal) to
88cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas     * return true if there are not actually any side effects.
89cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas     */
90cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    virtual bool hasSideEffects() const = 0;
91cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas
92cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas    /**
9386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     * Given a map of known constant variable values, substitute them in for references to those
9486a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     * variables occurring in this expression and its subexpressions.  Similar simplifications, such
9586a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     * as folding a constant binary expression down to a single value, may also be performed.
9686a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     * Returns a new expression which replaces this expression, or null if no replacements were
9786a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     * made. If a new expression is returned, this expression is no longer valid.
9886a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas     */
9986a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas    virtual std::unique_ptr<Expression> constantPropagate(const IRGenerator& irGenerator,
10086a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas                                                          const DefinitionMap& definitions) {
10186a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas        return nullptr;
10286a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas    }
10386a43405fb3f83f6d45581959df5f7321487ae7eEthan Nicholas
104dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    virtual int coercionCost(const Type& target) const {
105dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas        return fType.coercionCost(target);
106dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas    }
107dcba08e891f1766b047cf0dbe8bbd275d9f55d2bEthan Nicholas
108b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    const Kind fKind;
109d598f7981f34811e6f2a949207dc13638852f3f7ethannicholas    const Type& fType;
110b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
111b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas    typedef IRNode INHERITED;
112b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas};
113b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
114b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas} // namespace
115b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas
116b3058bdb1049ca75d526eb9f11e1a42a49e63585ethannicholas#endif
117