GDevelop Core
Core library for developing platforms and tools compatible with GDevelop.
ExpressionTypeFinder.h
1 /*
2  * GDevelop Core
3  * Copyright 2008-present Florian Rival ([email protected]). All rights
4  * reserved. This project is released under the MIT License.
5  */
6 #ifndef GDCORE_EXPRESSIONTYPEFINDER_H
7 #define GDCORE_EXPRESSIONTYPEFINDER_H
8 
9 #include <memory>
10 #include <vector>
11 #include "GDCore/Events/Parsers/ExpressionParser2Node.h"
12 #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
13 #include "GDCore/IDE/Events/ExpressionLeftSideTypeFinder.h"
14 #include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
15 #include "GDCore/Extensions/Metadata/MetadataProvider.h"
16 #include "GDCore/Extensions/Metadata/ObjectMetadata.h"
17 #include "GDCore/Extensions/Metadata/ParameterMetadata.h"
18 #include "GDCore/Project/ProjectScopedContainers.h"
20 
21 namespace gd {
22 class Expression;
23 class ObjectsContainer;
24 class Platform;
25 class ParameterMetadata;
26 class ExpressionMetadata;
27 } // namespace gd
28 
29 namespace gd {
30 
46  public:
47 
52  static const gd::String GetType(const gd::Platform &platform,
53  const gd::ProjectScopedContainers &projectScopedContainers,
54  const gd::String &rootType,
55  gd::ExpressionNode& node) {
56  gd::ExpressionTypeFinder typeFinder(
57  platform, projectScopedContainers, rootType);
58  node.Visit(typeFinder);
59  return typeFinder.GetType();
60  }
61 
62  virtual ~ExpressionTypeFinder(){};
63 
64  protected:
65  ExpressionTypeFinder(const gd::Platform &platform_,
66  const gd::ProjectScopedContainers &projectScopedContainers_,
67  const gd::String &rootType_)
68  : platform(platform_),
69  projectScopedContainers(projectScopedContainers_),
70  rootType(rootType_),
71  type(ExpressionTypeFinder::unknownType),
72  child(nullptr) {};
73 
74  const gd::String &GetType() {
76  };
77 
78  void OnVisitSubExpressionNode(SubExpressionNode& node) override {
79  VisitParent(node);
80  }
81  void OnVisitOperatorNode(OperatorNode& node) override {
82  VisitParent(node);
83  }
84  void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
85  VisitParent(node);
86  }
87  void OnVisitNumberNode(NumberNode& node) override {
88  type = ExpressionTypeFinder::numberType;
89  }
90  void OnVisitTextNode(TextNode& node) override {
91  type = ExpressionTypeFinder::stringType;
92  }
93  void OnVisitVariableNode(VariableNode& node) override {
94  VisitParent(node);
95  }
96  void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
97  VisitParent(node);
98  }
99  void OnVisitIdentifierNode(IdentifierNode& node) override {
100  VisitParent(node);
101  }
102  void OnVisitEmptyNode(EmptyNode& node) override {
103  VisitParent(node);
104  }
105  void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
106  VisitParent(node);
107  }
108  void OnVisitVariableBracketAccessorNode(
109  VariableBracketAccessorNode& node) override {
110  if (child == nullptr) {
111  type = ExpressionTypeFinder::unknownType;
112  }
113  auto leftSideType = gd::ExpressionLeftSideTypeFinder::GetType(
114  platform,
115  projectScopedContainers,
116  node);
117 
118  // If we can infer a definitive number or string type, use it.
119  // Otherwise, we only know that it's number or string, and this can even
120  // be used as is at runtime.
121  if (leftSideType == ExpressionTypeFinder::numberType
122  || leftSideType == ExpressionTypeFinder::stringType) {
123  type = leftSideType;
124  }
125  else {
126  type = ExpressionTypeFinder::numberOrStringType;
127  }
128  }
129  void OnVisitFunctionCallNode(FunctionCallNode& node) override {
130  if (child == nullptr) {
131  const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
132  platform, projectScopedContainers.GetObjectsContainersList(), node);
133  if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
134  VisitParent(node);
135  }
136  else {
137  type = metadata.GetReturnType();
138  }
139  }
140  else {
141  const gd::ParameterMetadata* parameterMetadata =
142  gd::MetadataProvider::GetFunctionCallParameterMetadata(
143  platform,
144  projectScopedContainers.GetObjectsContainersList(),
145  node,
146  *child);
147  if (parameterMetadata == nullptr || parameterMetadata->GetType().empty()) {
148  type = ExpressionTypeFinder::unknownType;
149  }
150  else {
151  type = parameterMetadata->GetType();
152  }
153  }
154  }
155 
156  private:
157  inline void VisitParent(ExpressionNode& node) {
158  child = &node;
159  if (node.parent != nullptr) {
160  node.parent->Visit(*this);
161  }
162  else if (rootType == ExpressionTypeFinder::numberOrStringType) {
163  auto leftSideType = gd::ExpressionLeftSideTypeFinder::GetType(
164  platform,
165  projectScopedContainers,
166  node);
167  if (leftSideType == ExpressionTypeFinder::numberType
168  || leftSideType == ExpressionTypeFinder::stringType) {
169  type = leftSideType;
170  }
171  else {
172  type = rootType;
173  }
174  }
175  else {
176  type = rootType;
177  }
178  }
179 
180  static const gd::String unknownType;
181  static const gd::String numberType;
182  static const gd::String stringType;
183  static const gd::String numberOrStringType;
184 
185  gd::String type;
186  ExpressionNode *child;
187 
188  const gd::Platform &platform;
189  const gd::ProjectScopedContainers &projectScopedContainers;
190  const gd::String rootType;
191 };
192 
193 } // namespace gd
194 
195 #endif // GDCORE_EXPRESSIONTYPEFINDER_H
static const gd::String GetType(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, gd::ExpressionNode &node)
Helper function to find the type of the node at the left side of operations.
Definition: ExpressionLeftSideTypeFinder.h:42
Describe user-friendly information about an expression, its parameters and the function name as well ...
Definition: ExpressionMetadata.h:47
The interface for any worker class ("visitor" pattern) that want to interact with the nodes of a pars...
Definition: ExpressionParser2NodeWorker.h:36
Find the type of the expression or sub-expression that a given node represents.
Definition: ExpressionTypeFinder.h:45
static const gd::String GetType(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, const gd::String &rootType, gd::ExpressionNode &node)
Helper function to find the type of the expression or sub-expression that a given node represents.
Definition: ExpressionTypeFinder.h:52
Describe a parameter of an instruction (action, condition) or of an expression: type,...
Definition: ParameterMetadata.h:27
static const gd::String & GetExpressionValueType(const gd::String &parameterType)
Return the expression type from the parameter type. Declinations of "number" and "string" types (like...
Definition: ParameterMetadata.h:219
const gd::String & GetType() const
Return the type of the parameter.
Definition: ParameterMetadata.h:55
Base class for implementing a platform.
Definition: Platform.h:42
Holds references to variables, objects, properties and other containers.
Definition: ProjectScopedContainers.h:30
String represents an UTF8 encoded string.
Definition: String.h:31
bool empty() const
Returns true if the string is empty.
Definition: String.h:155
Definition: CommonTools.h:24
The base node, from which all nodes in the tree of an expression inherits from.
Definition: ExpressionParser2Node.h:93