Implement exponential operator (**) to GDScript/Expressions
This commit is contained in:
parent
9963ae3553
commit
dbd7a31507
|
@ -703,6 +703,7 @@ void register_global_constants() {
|
|||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_NEGATE", Variant::OP_NEGATE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POSITIVE", Variant::OP_POSITIVE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_MODULE", Variant::OP_MODULE);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_POWER", Variant::OP_POWER);
|
||||
//bitwise
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_LEFT", Variant::OP_SHIFT_LEFT);
|
||||
BIND_CORE_ENUM_CONSTANT_CUSTOM("OP_SHIFT_RIGHT", Variant::OP_SHIFT_RIGHT);
|
||||
|
|
|
@ -114,6 +114,7 @@ typedef enum {
|
|||
GDNATIVE_VARIANT_OP_NEGATE,
|
||||
GDNATIVE_VARIANT_OP_POSITIVE,
|
||||
GDNATIVE_VARIANT_OP_MODULE,
|
||||
GDNATIVE_VARIANT_OP_POWER,
|
||||
/* bitwise */
|
||||
GDNATIVE_VARIANT_OP_SHIFT_LEFT,
|
||||
GDNATIVE_VARIANT_OP_SHIFT_RIGHT,
|
||||
|
|
|
@ -155,7 +155,12 @@ Error Expression::_get_token(Token &r_token) {
|
|||
return OK;
|
||||
}
|
||||
case '*': {
|
||||
r_token.type = TK_OP_MUL;
|
||||
if (expression[str_ofs] == '*') {
|
||||
r_token.type = TK_OP_POW;
|
||||
str_ofs++;
|
||||
} else {
|
||||
r_token.type = TK_OP_MUL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
case '%': {
|
||||
|
@ -542,6 +547,7 @@ const char *Expression::token_name[TK_MAX] = {
|
|||
"OP MUL",
|
||||
"OP DIV",
|
||||
"OP MOD",
|
||||
"OP POW",
|
||||
"OP SHIFT LEFT",
|
||||
"OP SHIFT RIGHT",
|
||||
"OP BIT AND",
|
||||
|
@ -1013,6 +1019,9 @@ Expression::ENode *Expression::_parse_expression() {
|
|||
case TK_OP_MOD:
|
||||
op = Variant::OP_MODULE;
|
||||
break;
|
||||
case TK_OP_POW:
|
||||
op = Variant::OP_POWER;
|
||||
break;
|
||||
case TK_OP_SHIFT_LEFT:
|
||||
op = Variant::OP_SHIFT_LEFT;
|
||||
break;
|
||||
|
@ -1066,56 +1075,59 @@ Expression::ENode *Expression::_parse_expression() {
|
|||
bool unary = false;
|
||||
|
||||
switch (expression[i].op) {
|
||||
case Variant::OP_BIT_NEGATE:
|
||||
case Variant::OP_POWER:
|
||||
priority = 0;
|
||||
break;
|
||||
case Variant::OP_BIT_NEGATE:
|
||||
priority = 1;
|
||||
unary = true;
|
||||
break;
|
||||
case Variant::OP_NEGATE:
|
||||
priority = 1;
|
||||
priority = 2;
|
||||
unary = true;
|
||||
break;
|
||||
case Variant::OP_MULTIPLY:
|
||||
case Variant::OP_DIVIDE:
|
||||
case Variant::OP_MODULE:
|
||||
priority = 2;
|
||||
priority = 3;
|
||||
break;
|
||||
case Variant::OP_ADD:
|
||||
case Variant::OP_SUBTRACT:
|
||||
priority = 3;
|
||||
priority = 4;
|
||||
break;
|
||||
case Variant::OP_SHIFT_LEFT:
|
||||
case Variant::OP_SHIFT_RIGHT:
|
||||
priority = 4;
|
||||
break;
|
||||
case Variant::OP_BIT_AND:
|
||||
priority = 5;
|
||||
break;
|
||||
case Variant::OP_BIT_XOR:
|
||||
case Variant::OP_BIT_AND:
|
||||
priority = 6;
|
||||
break;
|
||||
case Variant::OP_BIT_OR:
|
||||
case Variant::OP_BIT_XOR:
|
||||
priority = 7;
|
||||
break;
|
||||
case Variant::OP_BIT_OR:
|
||||
priority = 8;
|
||||
break;
|
||||
case Variant::OP_LESS:
|
||||
case Variant::OP_LESS_EQUAL:
|
||||
case Variant::OP_GREATER:
|
||||
case Variant::OP_GREATER_EQUAL:
|
||||
case Variant::OP_EQUAL:
|
||||
case Variant::OP_NOT_EQUAL:
|
||||
priority = 8;
|
||||
priority = 9;
|
||||
break;
|
||||
case Variant::OP_IN:
|
||||
priority = 10;
|
||||
priority = 11;
|
||||
break;
|
||||
case Variant::OP_NOT:
|
||||
priority = 11;
|
||||
priority = 12;
|
||||
unary = true;
|
||||
break;
|
||||
case Variant::OP_AND:
|
||||
priority = 12;
|
||||
priority = 13;
|
||||
break;
|
||||
case Variant::OP_OR:
|
||||
priority = 13;
|
||||
priority = 14;
|
||||
break;
|
||||
default: {
|
||||
_set_error("Parser bug, invalid operator in expression: " + itos(expression[i].op));
|
||||
|
|
|
@ -85,6 +85,7 @@ private:
|
|||
TK_OP_MUL,
|
||||
TK_OP_DIV,
|
||||
TK_OP_MOD,
|
||||
TK_OP_POW,
|
||||
TK_OP_SHIFT_LEFT,
|
||||
TK_OP_SHIFT_RIGHT,
|
||||
TK_OP_BIT_AND,
|
||||
|
|
|
@ -473,6 +473,7 @@ public:
|
|||
OP_NEGATE,
|
||||
OP_POSITIVE,
|
||||
OP_MODULE,
|
||||
OP_POWER,
|
||||
//bitwise
|
||||
OP_SHIFT_LEFT,
|
||||
OP_SHIFT_RIGHT,
|
||||
|
|
|
@ -361,6 +361,11 @@ void Variant::_register_variant_operators() {
|
|||
register_op<OperatorEvaluatorStringModT<PackedVector3Array>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_VECTOR3_ARRAY);
|
||||
register_op<OperatorEvaluatorStringModT<PackedColorArray>>(Variant::OP_MODULE, Variant::STRING, Variant::PACKED_COLOR_ARRAY);
|
||||
|
||||
register_op<OperatorEvaluatorPow<int64_t, int64_t, int64_t>>(Variant::OP_POWER, Variant::INT, Variant::INT);
|
||||
register_op<OperatorEvaluatorPow<double, int64_t, double>>(Variant::OP_POWER, Variant::INT, Variant::FLOAT);
|
||||
register_op<OperatorEvaluatorPow<double, double, double>>(Variant::OP_POWER, Variant::FLOAT, Variant::FLOAT);
|
||||
register_op<OperatorEvaluatorPow<double, double, int64_t>>(Variant::OP_POWER, Variant::FLOAT, Variant::INT);
|
||||
|
||||
register_op<OperatorEvaluatorNeg<int64_t, int64_t>>(Variant::OP_NEGATE, Variant::INT, Variant::NIL);
|
||||
register_op<OperatorEvaluatorNeg<double, double>>(Variant::OP_NEGATE, Variant::FLOAT, Variant::NIL);
|
||||
register_op<OperatorEvaluatorNeg<Vector2, Vector2>>(Variant::OP_NEGATE, Variant::VECTOR2, Variant::NIL);
|
||||
|
@ -929,6 +934,7 @@ static const char *_op_names[Variant::OP_MAX] = {
|
|||
"unary-",
|
||||
"unary+",
|
||||
"%",
|
||||
"**",
|
||||
"<<",
|
||||
">>",
|
||||
"&",
|
||||
|
|
|
@ -91,6 +91,24 @@ public:
|
|||
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
|
||||
};
|
||||
|
||||
template <class R, class A, class B>
|
||||
class OperatorEvaluatorPow {
|
||||
public:
|
||||
static void evaluate(const Variant &p_left, const Variant &p_right, Variant *r_ret, bool &r_valid) {
|
||||
const A &a = *VariantGetInternalPtr<A>::get_ptr(&p_left);
|
||||
const B &b = *VariantGetInternalPtr<B>::get_ptr(&p_right);
|
||||
*r_ret = R(Math::pow((double)a, (double)b));
|
||||
r_valid = true;
|
||||
}
|
||||
static inline void validated_evaluate(const Variant *left, const Variant *right, Variant *r_ret) {
|
||||
*VariantGetInternalPtr<R>::get_ptr(r_ret) = R(Math::pow((double)*VariantGetInternalPtr<A>::get_ptr(left), (double)*VariantGetInternalPtr<B>::get_ptr(right)));
|
||||
}
|
||||
static void ptr_evaluate(const void *left, const void *right, void *r_ret) {
|
||||
PtrToArg<R>::encode(R(Math::pow((double)PtrToArg<A>::convert(left), (double)PtrToArg<B>::convert(right))), r_ret);
|
||||
}
|
||||
static Variant::Type get_return_type() { return GetTypeInfo<R>::VARIANT_TYPE; }
|
||||
};
|
||||
|
||||
template <class R, class A, class B>
|
||||
class OperatorEvaluatorXForm {
|
||||
public:
|
||||
|
|
|
@ -2799,40 +2799,43 @@
|
|||
<constant name="OP_MODULE" value="12" enum="Variant.Operator">
|
||||
Remainder/modulo operator ([code]%[/code]).
|
||||
</constant>
|
||||
<constant name="OP_SHIFT_LEFT" value="13" enum="Variant.Operator">
|
||||
<constant name="OP_POWER" value="13" enum="Variant.Operator">
|
||||
Power operator ([code]**[/code]).
|
||||
</constant>
|
||||
<constant name="OP_SHIFT_LEFT" value="14" enum="Variant.Operator">
|
||||
Left shift operator ([code]<<[/code]).
|
||||
</constant>
|
||||
<constant name="OP_SHIFT_RIGHT" value="14" enum="Variant.Operator">
|
||||
<constant name="OP_SHIFT_RIGHT" value="15" enum="Variant.Operator">
|
||||
Right shift operator ([code]>>[/code]).
|
||||
</constant>
|
||||
<constant name="OP_BIT_AND" value="15" enum="Variant.Operator">
|
||||
<constant name="OP_BIT_AND" value="16" enum="Variant.Operator">
|
||||
Bitwise AND operator ([code]&[/code]).
|
||||
</constant>
|
||||
<constant name="OP_BIT_OR" value="16" enum="Variant.Operator">
|
||||
<constant name="OP_BIT_OR" value="17" enum="Variant.Operator">
|
||||
Bitwise OR operator ([code]|[/code]).
|
||||
</constant>
|
||||
<constant name="OP_BIT_XOR" value="17" enum="Variant.Operator">
|
||||
<constant name="OP_BIT_XOR" value="18" enum="Variant.Operator">
|
||||
Bitwise XOR operator ([code]^[/code]).
|
||||
</constant>
|
||||
<constant name="OP_BIT_NEGATE" value="18" enum="Variant.Operator">
|
||||
<constant name="OP_BIT_NEGATE" value="19" enum="Variant.Operator">
|
||||
Bitwise NOT operator ([code]~[/code]).
|
||||
</constant>
|
||||
<constant name="OP_AND" value="19" enum="Variant.Operator">
|
||||
<constant name="OP_AND" value="20" enum="Variant.Operator">
|
||||
Logical AND operator ([code]and[/code] or [code]&&[/code]).
|
||||
</constant>
|
||||
<constant name="OP_OR" value="20" enum="Variant.Operator">
|
||||
<constant name="OP_OR" value="21" enum="Variant.Operator">
|
||||
Logical OR operator ([code]or[/code] or [code]||[/code]).
|
||||
</constant>
|
||||
<constant name="OP_XOR" value="21" enum="Variant.Operator">
|
||||
<constant name="OP_XOR" value="22" enum="Variant.Operator">
|
||||
Logical XOR operator (not implemented in GDScript).
|
||||
</constant>
|
||||
<constant name="OP_NOT" value="22" enum="Variant.Operator">
|
||||
<constant name="OP_NOT" value="23" enum="Variant.Operator">
|
||||
Logical NOT operator ([code]not[/code] or [code]![/code]).
|
||||
</constant>
|
||||
<constant name="OP_IN" value="23" enum="Variant.Operator">
|
||||
<constant name="OP_IN" value="24" enum="Variant.Operator">
|
||||
Logical IN operator ([code]in[/code]).
|
||||
</constant>
|
||||
<constant name="OP_MAX" value="24" enum="Variant.Operator">
|
||||
<constant name="OP_MAX" value="25" enum="Variant.Operator">
|
||||
Represents the size of the [enum Variant.Operator] enum.
|
||||
</constant>
|
||||
</constants>
|
||||
|
|
|
@ -124,6 +124,18 @@
|
|||
Multiplies a [float] and an [int]. The result is a [float].
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator **">
|
||||
<return type="float" />
|
||||
<argument index="0" name="right" type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator **">
|
||||
<return type="float" />
|
||||
<argument index="0" name="right" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator +">
|
||||
<return type="float" />
|
||||
<argument index="0" name="right" type="float" />
|
||||
|
|
|
@ -171,6 +171,18 @@
|
|||
Multiplies two [int]s.
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator **">
|
||||
<return type="float" />
|
||||
<argument index="0" name="right" type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator **">
|
||||
<return type="int" />
|
||||
<argument index="0" name="right" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</operator>
|
||||
<operator name="operator +">
|
||||
<return type="String" />
|
||||
<argument index="0" name="right" type="String" />
|
||||
|
|
|
@ -1409,6 +1409,8 @@ def sanitize_operator_name(dirty_name, state): # type: (str, State) -> str
|
|||
clear_name = "div"
|
||||
elif clear_name == "%":
|
||||
clear_name = "mod"
|
||||
elif clear_name == "**":
|
||||
clear_name = "pow"
|
||||
|
||||
elif clear_name == "unary+":
|
||||
clear_name = "unplus"
|
||||
|
|
|
@ -2320,6 +2320,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression
|
|||
operation->operation = BinaryOpNode::OP_MODULO;
|
||||
operation->variant_op = Variant::OP_MODULE;
|
||||
break;
|
||||
case GDScriptTokenizer::Token::STAR_STAR:
|
||||
operation->operation = BinaryOpNode::OP_POWER;
|
||||
operation->variant_op = Variant::OP_POWER;
|
||||
break;
|
||||
case GDScriptTokenizer::Token::LESS_LESS:
|
||||
operation->operation = BinaryOpNode::OP_BIT_LEFT_SHIFT;
|
||||
operation->variant_op = Variant::OP_SHIFT_LEFT;
|
||||
|
@ -2483,6 +2487,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode
|
|||
assignment->operation = AssignmentNode::OP_MULTIPLICATION;
|
||||
assignment->variant_op = Variant::OP_MULTIPLY;
|
||||
break;
|
||||
case GDScriptTokenizer::Token::STAR_STAR_EQUAL:
|
||||
assignment->operation = AssignmentNode::OP_POWER;
|
||||
assignment->variant_op = Variant::OP_POWER;
|
||||
break;
|
||||
case GDScriptTokenizer::Token::SLASH_EQUAL:
|
||||
assignment->operation = AssignmentNode::OP_DIVISION;
|
||||
assignment->variant_op = Variant::OP_DIVIDE;
|
||||
|
@ -3265,6 +3273,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
|
|||
{ &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // PLUS,
|
||||
{ &GDScriptParser::parse_unary_operator, &GDScriptParser::parse_binary_operator, PREC_ADDITION_SUBTRACTION }, // MINUS,
|
||||
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // STAR,
|
||||
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // STAR_STAR,
|
||||
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // SLASH,
|
||||
{ nullptr, &GDScriptParser::parse_binary_operator, PREC_FACTOR }, // PERCENT,
|
||||
// Assignment
|
||||
|
@ -3272,6 +3281,7 @@ GDScriptParser::ParseRule *GDScriptParser::get_rule(GDScriptTokenizer::Token::Ty
|
|||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PLUS_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // MINUS_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // STAR_STAR_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // SLASH_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // PERCENT_EQUAL,
|
||||
{ nullptr, &GDScriptParser::parse_assignment, PREC_ASSIGNMENT }, // LESS_LESS_EQUAL,
|
||||
|
@ -3896,6 +3906,9 @@ void GDScriptParser::TreePrinter::print_assignment(AssignmentNode *p_assignment)
|
|||
case AssignmentNode::OP_MODULO:
|
||||
push_text("%");
|
||||
break;
|
||||
case AssignmentNode::OP_POWER:
|
||||
push_text("**");
|
||||
break;
|
||||
case AssignmentNode::OP_BIT_SHIFT_LEFT:
|
||||
push_text("<<");
|
||||
break;
|
||||
|
@ -3944,6 +3957,9 @@ void GDScriptParser::TreePrinter::print_binary_op(BinaryOpNode *p_binary_op) {
|
|||
case BinaryOpNode::OP_MODULO:
|
||||
push_text(" % ");
|
||||
break;
|
||||
case BinaryOpNode::OP_POWER:
|
||||
push_text(" ** ");
|
||||
break;
|
||||
case BinaryOpNode::OP_BIT_LEFT_SHIFT:
|
||||
push_text(" << ");
|
||||
break;
|
||||
|
|
|
@ -360,6 +360,7 @@ public:
|
|||
OP_MULTIPLICATION,
|
||||
OP_DIVISION,
|
||||
OP_MODULO,
|
||||
OP_POWER,
|
||||
OP_BIT_SHIFT_LEFT,
|
||||
OP_BIT_SHIFT_RIGHT,
|
||||
OP_BIT_AND,
|
||||
|
@ -393,6 +394,7 @@ public:
|
|||
OP_MULTIPLICATION,
|
||||
OP_DIVISION,
|
||||
OP_MODULO,
|
||||
OP_POWER,
|
||||
OP_BIT_LEFT_SHIFT,
|
||||
OP_BIT_RIGHT_SHIFT,
|
||||
OP_BIT_AND,
|
||||
|
|
|
@ -67,6 +67,7 @@ static const char *token_names[] = {
|
|||
"+", // PLUS,
|
||||
"-", // MINUS,
|
||||
"*", // STAR,
|
||||
"**", // STAR_STAR,
|
||||
"/", // SLASH,
|
||||
"%", // PERCENT,
|
||||
// Assignment
|
||||
|
@ -74,6 +75,7 @@ static const char *token_names[] = {
|
|||
"+=", // PLUS_EQUAL,
|
||||
"-=", // MINUS_EQUAL,
|
||||
"*=", // STAR_EQUAL,
|
||||
"**=", // STAR_STAR_EQUAL,
|
||||
"/=", // SLASH_EQUAL,
|
||||
"%=", // PERCENT_EQUAL,
|
||||
"<<=", // LESS_LESS_EQUAL,
|
||||
|
@ -1403,6 +1405,14 @@ GDScriptTokenizer::Token GDScriptTokenizer::scan() {
|
|||
if (_peek() == '=') {
|
||||
_advance();
|
||||
return make_token(Token::STAR_EQUAL);
|
||||
} else if (_peek() == '*') {
|
||||
if (_peek(1) == '=') {
|
||||
_advance();
|
||||
_advance(); // Advance both '*' and '='
|
||||
return make_token(Token::STAR_STAR_EQUAL);
|
||||
}
|
||||
_advance();
|
||||
return make_token(Token::STAR_STAR);
|
||||
} else {
|
||||
return make_token(Token::STAR);
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
PLUS,
|
||||
MINUS,
|
||||
STAR,
|
||||
STAR_STAR,
|
||||
SLASH,
|
||||
PERCENT,
|
||||
// Assignment
|
||||
|
@ -85,6 +86,7 @@ public:
|
|||
PLUS_EQUAL,
|
||||
MINUS_EQUAL,
|
||||
STAR_EQUAL,
|
||||
STAR_STAR_EQUAL,
|
||||
SLASH_EQUAL,
|
||||
PERCENT_EQUAL,
|
||||
LESS_LESS_EQUAL,
|
||||
|
|
Loading…
Reference in New Issue