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_PROGRAMELEMENT
9 #define SKSL_PROGRAMELEMENT
10 
11 #include "include/private/SkSLIRNode.h"
12 
13 #include <memory>
14 
15 namespace SkSL {
16 
17 /**
18  * Represents a top-level element (e.g. function or global variable) in a program.
19  */
20 class ProgramElement : public IRNode {
21 public:
22     enum class Kind {
23         kEnum = 0,
24         kExtension,
25         kFunction,
26         kFunctionPrototype,
27         kGlobalVar,
28         kInterfaceBlock,
29         kModifiers,
30         kSection,
31         kStructDefinition,
32 
33         kFirst = kEnum,
34         kLast = kStructDefinition
35     };
36 
ProgramElement(int offset,Kind kind)37     ProgramElement(int offset, Kind kind)
38         : INHERITED(offset, (int) kind) {
39         SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
40     }
41 
kind()42     Kind kind() const {
43         return (Kind) fKind;
44     }
45 
46     /**
47      *  Use is<T> to check the type of a program element.
48      *  e.g. replace `el.kind() == ProgramElement::Kind::kEnum` with `el.is<Enum>()`.
49      */
50     template <typename T>
is()51     bool is() const {
52         return this->kind() == T::kProgramElementKind;
53     }
54 
55     /**
56      *  Use as<T> to downcast program elements. e.g. replace `(Enum&) el` with `el.as<Enum>()`.
57      */
58     template <typename T>
as()59     const T& as() const {
60         SkASSERT(this->is<T>());
61         return static_cast<const T&>(*this);
62     }
63 
64     template <typename T>
as()65     T& as() {
66         SkASSERT(this->is<T>());
67         return static_cast<T&>(*this);
68     }
69 
70     virtual std::unique_ptr<ProgramElement> clone() const = 0;
71 
72 private:
73     using INHERITED = IRNode;
74 };
75 
76 }  // namespace SkSL
77 
78 #endif
79