1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_STATEMENT
9#define SKSL_STATEMENT
10
11#include "include/private/SkSLIRNode.h"
12#include "include/private/SkSLSymbol.h"
13
14namespace SkSL {
15
16/**
17 * Abstract supertype of all statements.
18 */
19class Statement : public IRNode {
20public:
21    enum Kind {
22        kBlock = (int) Symbol::Kind::kLast + 1,
23        kBreak,
24        kContinue,
25        kDiscard,
26        kDo,
27        kExpression,
28        kFor,
29        kIf,
30        kInlineMarker,
31        kNop,
32        kReturn,
33        kSwitch,
34        kSwitchCase,
35        kVarDeclaration,
36
37        kFirst = kBlock,
38        kLast = kVarDeclaration,
39    };
40
41    Statement(int line, Kind kind)
42    : INHERITED(line, (int) kind) {
43        SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
44    }
45
46    Kind kind() const {
47        return (Kind) fKind;
48    }
49
50    /**
51     *  Use is<T> to check the type of a statement.
52     *  e.g. replace `s.kind() == Statement::Kind::kReturn` with `s.is<ReturnStatement>()`.
53     */
54    template <typename T>
55    bool is() const {
56        return this->fKind == T::kStatementKind;
57    }
58
59    /**
60     *  Use as<T> to downcast statements.
61     *  e.g. replace `(ReturnStatement&) s` with `s.as<ReturnStatement>()`.
62     */
63    template <typename T>
64    const T& as() const {
65        SkASSERT(this->is<T>());
66        return static_cast<const T&>(*this);
67    }
68
69    template <typename T>
70    T& as() {
71        SkASSERT(this->is<T>());
72        return static_cast<T&>(*this);
73    }
74
75    virtual bool isEmpty() const {
76        return false;
77    }
78
79    virtual std::unique_ptr<Statement> clone() const = 0;
80
81private:
82    using INHERITED = IRNode;
83};
84
85}  // namespace SkSL
86
87#endif
88