evaluating_expressions.rst 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. .. _doc_evaluating_expressions:
  2. Evaluating expressions
  3. ======================
  4. Godot provides an :ref:`class_Expression` class you can use to evaluate expressions.
  5. An expression can be:
  6. - A mathematical expression such as ``(2 + 4) * 16/4.0``.
  7. - A built-in method call like ``deg_to_rad(90)``.
  8. - A method call on a user-provided script like ``update_health()``,
  9. if ``base_instance`` is set to a value other than ``null`` when calling
  10. :ref:`Expression.execute() <class_Expression_method_execute>`.
  11. .. note::
  12. The Expression class is independent from GDScript.
  13. It's available even if you compile Godot with the GDScript module disabled.
  14. Basic usage
  15. -----------
  16. To evaluate a mathematical expression, use::
  17. var expression = Expression.new()
  18. expression.parse("20 + 10*2 - 5/2.0")
  19. var result = expression.execute()
  20. print(result) # 37.5
  21. The following operators are available:
  22. +------------------------+-------------------------------------------------------------------------------------+
  23. | Operator | Notes |
  24. +========================+=====================================================================================+
  25. | Addition ``+`` | Can also be used to concatenate strings and arrays: |
  26. | | - ``"hello" + " world"`` = ``hello world`` |
  27. | | - ``[1, 2] + [3, 4]`` = ``[1, 2, 3, 4]`` |
  28. +------------------------+-------------------------------------------------------------------------------------+
  29. | Subtraction (``-``) | |
  30. +------------------------+-------------------------------------------------------------------------------------+
  31. | Multiplication (``*``) | |
  32. +------------------------+-------------------------------------------------------------------------------------+
  33. | Division (``/``) | Performs and integer division if both operands are integers. |
  34. | | If at least one of them is a floating-point number, returns a floating-point value. |
  35. +------------------------+-------------------------------------------------------------------------------------+
  36. | Remainder (``%``) | Returns the remainder of an integer division (modulo). |
  37. | | The result will always have the sign of the dividend. |
  38. +------------------------+-------------------------------------------------------------------------------------+
  39. Spaces around operators are optional. Also, keep in mind the usual
  40. `order of operations <https://en.wikipedia.org/wiki/Order_of_operations>`__
  41. applies. Use parentheses to override the order of operations if needed.
  42. All the Variant types supported in Godot can be used: integers, floating-point
  43. numbers, strings, arrays, dictionaries, colors, vectors, …
  44. Arrays and dictionaries can be indexed like in GDScript::
  45. # Returns 1.
  46. [1, 2][0]
  47. # Returns 3. Negative indices can be used to count from the end of the array.
  48. [1, 3][-1]
  49. # Returns "green".
  50. {"favorite_color": "green"}["favorite_color"]
  51. # All 3 lines below return 7.0 (Vector3 is floating-point).
  52. Vector3(5, 6, 7)[2]
  53. Vector3(5, 6, 7)["z"]
  54. Vector3(5, 6, 7).z
  55. Passing variables to an expression
  56. ----------------------------------
  57. You can pass variables to an expression. These variables will then
  58. become available in the expression's "context" and will be substituted when used
  59. in the expression::
  60. var expression = Expression.new()
  61. # Define the variable names first in the second parameter of `parse()`.
  62. # In this example, we use `x` for the variable name.
  63. expression.parse("20 + 2 * x", ["x"])
  64. # Then define the variable values in the first parameter of `execute()`.
  65. # Here, `x` is assigned the integer value 5.
  66. var result = expression.execute([5])
  67. print(result) # 30
  68. Both the variable names and variable values **must** be specified as an array,
  69. even if you only define one variable. Also, variable names are **case-sensitive**.
  70. Setting a base instance for the expression
  71. ------------------------------------------
  72. By default, an expression has a base instance of ``null``. This means the
  73. expression has no base instance associated to it.
  74. When calling :ref:`Expression.execute() <class_Expression_method_execute>`,
  75. you can set the value of the ``base_instance`` parameter to a specific object
  76. instance such as ``self``, another script instance or even a singleton::
  77. func double(number):
  78. return number * 2
  79. func _ready():
  80. var expression = Expression.new()
  81. expression.parse("double(10)")
  82. # This won't work since we're not passing the current script as the base instance.
  83. var result = expression.execute([], null)
  84. print(result) # null
  85. # This will work since we're passing the current script (i.e. self)
  86. # as the base instance.
  87. result = expression.execute([], self)
  88. print(result) # 20
  89. Associating a base instance allows doing the following:
  90. - Reference the instance's constants (``const``) in the expression.
  91. - Reference the instance's member variables (``var``) in the expression.
  92. - Call methods defined in the instance and use their return values in the expression.
  93. .. warning::
  94. Setting a base instance to a value other than ``null`` allows referencing
  95. constants, member variables, and calling all methods defined in the script
  96. attached to the instance. Allowing users to enter expressions may allow
  97. cheating in your game, or may even introduce security vulnerabilities if you
  98. allow arbitrary clients to run expressions on other players' devices.
  99. Example script
  100. --------------
  101. The script below demonstrates what the Expression class is capable of::
  102. const DAYS_IN_YEAR = 365
  103. var script_member_variable = 1000
  104. func _ready():
  105. # Constant mathexpression.
  106. evaluate("2 + 2")
  107. # Math expression with variables.
  108. evaluate("x + y", ["x", "y"], [60, 100])
  109. # Call built-in method (built-in math function call).
  110. evaluate("deg_to_rad(90)")
  111. # Call user method (defined in the script).
  112. # We can do this because the expression execution is bound to `self`
  113. # in the `evaluate()` method.
  114. # Since this user method returns a value, we can use it in math expressions.
  115. evaluate("call_me() + DAYS_IN_YEAR + script_member_variable")
  116. evaluate("call_me(42)")
  117. evaluate("call_me('some string')")
  118. func evaluate(command, variable_names = [], variable_values = []) -> void:
  119. var expression = Expression.new()
  120. var error = expression.parse(command, variable_names)
  121. if error != OK:
  122. push_error(expression.get_error_text())
  123. return
  124. var result = expression.execute(variable_values, self)
  125. if not expression.has_execute_failed():
  126. print(str(result))
  127. func call_me(argument = null):
  128. print("\nYou called 'call_me()' in the expression text.")
  129. if argument:
  130. print("Argument passed: %s" % argument)
  131. # The method's return value is also the expression's return value.
  132. return 0
  133. The output from the script will be::
  134. 4
  135. 160
  136. 1.5707963267949
  137. You called 'call_me()' in the expression text.
  138. 1365
  139. You called 'call_me()' in the expression text.
  140. Argument passed: 42
  141. 0
  142. You called 'call_me()' in the expression text.
  143. Argument passed: some string
  144. 0
  145. Built-in functions
  146. ------------------
  147. All methods in the :ref:`Global Scope<class_@GlobalScope>` are available in the
  148. Expression class, even if no base instance is bound to the expression.
  149. The same parameters and return types are available.
  150. However, unlike GDScript, parameters are **always required** even if they're
  151. specified as being optional in the class reference. In contrast, this
  152. restriction on arguments doesn't apply to user-made functions when you bind a
  153. base instance to the expression.