GDScript: Add typed iterate instructions
This commit is contained in:
parent
52ab64db69
commit
e0dca3c6b6
4 changed files with 944 additions and 89 deletions
|
@ -864,8 +864,95 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre
|
|||
append(container_pos);
|
||||
append(p_list);
|
||||
|
||||
GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
|
||||
GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
|
||||
|
||||
if (p_list.type.has_type) {
|
||||
if (p_list.type.kind == GDScriptDataType::BUILTIN) {
|
||||
switch (p_list.type.builtin_type) {
|
||||
case Variant::INT:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_INT;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_INT;
|
||||
break;
|
||||
case Variant::FLOAT:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_FLOAT;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_FLOAT;
|
||||
break;
|
||||
case Variant::VECTOR2:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2;
|
||||
break;
|
||||
case Variant::VECTOR2I:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2I;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2I;
|
||||
break;
|
||||
case Variant::VECTOR3:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3;
|
||||
break;
|
||||
case Variant::VECTOR3I:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3I;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3I;
|
||||
break;
|
||||
case Variant::STRING:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_STRING;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_STRING;
|
||||
break;
|
||||
case Variant::DICTIONARY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_DICTIONARY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_DICTIONARY;
|
||||
break;
|
||||
case Variant::ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_BYTE_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_BYTE_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT32_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT64_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT32_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_FLOAT64_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT64_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_STRING_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_STRING_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_VECTOR2_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR2_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_VECTOR3_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR3_ARRAY;
|
||||
break;
|
||||
case Variant::PACKED_COLOR_ARRAY:
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_COLOR_ARRAY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_OBJECT;
|
||||
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
// Begin loop.
|
||||
append(GDScriptFunction::OPCODE_ITERATE_BEGIN, 3);
|
||||
append(begin_opcode, 3);
|
||||
append(counter_pos);
|
||||
append(container_pos);
|
||||
append(p_variable);
|
||||
|
@ -877,7 +964,7 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre
|
|||
// Next iteration.
|
||||
int continue_addr = opcodes.size();
|
||||
continue_addrs.push_back(continue_addr);
|
||||
append(GDScriptFunction::OPCODE_ITERATE, 3);
|
||||
append(iterate_opcode, 3);
|
||||
append(counter_pos);
|
||||
append(container_pos);
|
||||
append(p_variable);
|
||||
|
|
|
@ -674,6 +674,58 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||
|
||||
incr = 2;
|
||||
} break;
|
||||
|
||||
#define DISASSEMBLE_ITERATE(m_type) \
|
||||
case OPCODE_ITERATE_##m_type: { \
|
||||
text += "for-loop (typed "; \
|
||||
text += #m_type; \
|
||||
text += ") "; \
|
||||
text += DADDR(3); \
|
||||
text += " in "; \
|
||||
text += DADDR(2); \
|
||||
text += " counter "; \
|
||||
text += DADDR(1); \
|
||||
text += " end "; \
|
||||
text += itos(_code_ptr[ip + 4]); \
|
||||
incr += 5; \
|
||||
} break
|
||||
|
||||
#define DISASSEMBLE_ITERATE_BEGIN(m_type) \
|
||||
case OPCODE_ITERATE_BEGIN_##m_type: { \
|
||||
text += "for-init (typed "; \
|
||||
text += #m_type; \
|
||||
text += ") "; \
|
||||
text += DADDR(3); \
|
||||
text += " in "; \
|
||||
text += DADDR(2); \
|
||||
text += " counter "; \
|
||||
text += DADDR(1); \
|
||||
text += " end "; \
|
||||
text += itos(_code_ptr[ip + 4]); \
|
||||
incr += 5; \
|
||||
} break
|
||||
|
||||
#define DISASSEMBLE_ITERATE_TYPES(m_macro) \
|
||||
m_macro(INT); \
|
||||
m_macro(FLOAT); \
|
||||
m_macro(VECTOR2); \
|
||||
m_macro(VECTOR2I); \
|
||||
m_macro(VECTOR3); \
|
||||
m_macro(VECTOR3I); \
|
||||
m_macro(STRING); \
|
||||
m_macro(DICTIONARY); \
|
||||
m_macro(ARRAY); \
|
||||
m_macro(PACKED_BYTE_ARRAY); \
|
||||
m_macro(PACKED_INT32_ARRAY); \
|
||||
m_macro(PACKED_INT64_ARRAY); \
|
||||
m_macro(PACKED_FLOAT32_ARRAY); \
|
||||
m_macro(PACKED_FLOAT64_ARRAY); \
|
||||
m_macro(PACKED_STRING_ARRAY); \
|
||||
m_macro(PACKED_VECTOR2_ARRAY); \
|
||||
m_macro(PACKED_VECTOR3_ARRAY); \
|
||||
m_macro(PACKED_COLOR_ARRAY); \
|
||||
m_macro(OBJECT)
|
||||
|
||||
case OPCODE_ITERATE_BEGIN: {
|
||||
text += "for-init ";
|
||||
text += DADDR(3);
|
||||
|
@ -686,6 +738,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||
|
||||
incr += 5;
|
||||
} break;
|
||||
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE_BEGIN);
|
||||
case OPCODE_ITERATE: {
|
||||
text += "for-loop ";
|
||||
text += DADDR(2);
|
||||
|
@ -698,6 +751,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||
|
||||
incr += 5;
|
||||
} break;
|
||||
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
|
||||
case OPCODE_LINE: {
|
||||
int line = _code_ptr[ip + 1] - 1;
|
||||
if (line >= 0 && line < p_code_lines.size()) {
|
||||
|
|
|
@ -238,7 +238,45 @@ public:
|
|||
OPCODE_JUMP_TO_DEF_ARGUMENT,
|
||||
OPCODE_RETURN,
|
||||
OPCODE_ITERATE_BEGIN,
|
||||
OPCODE_ITERATE_BEGIN_INT,
|
||||
OPCODE_ITERATE_BEGIN_FLOAT,
|
||||
OPCODE_ITERATE_BEGIN_VECTOR2,
|
||||
OPCODE_ITERATE_BEGIN_VECTOR2I,
|
||||
OPCODE_ITERATE_BEGIN_VECTOR3,
|
||||
OPCODE_ITERATE_BEGIN_VECTOR3I,
|
||||
OPCODE_ITERATE_BEGIN_STRING,
|
||||
OPCODE_ITERATE_BEGIN_DICTIONARY,
|
||||
OPCODE_ITERATE_BEGIN_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY,
|
||||
OPCODE_ITERATE_BEGIN_OBJECT,
|
||||
OPCODE_ITERATE,
|
||||
OPCODE_ITERATE_INT,
|
||||
OPCODE_ITERATE_FLOAT,
|
||||
OPCODE_ITERATE_VECTOR2,
|
||||
OPCODE_ITERATE_VECTOR2I,
|
||||
OPCODE_ITERATE_VECTOR3,
|
||||
OPCODE_ITERATE_VECTOR3I,
|
||||
OPCODE_ITERATE_STRING,
|
||||
OPCODE_ITERATE_DICTIONARY,
|
||||
OPCODE_ITERATE_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_BYTE_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_INT32_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_INT64_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_FLOAT32_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_FLOAT64_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_STRING_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_VECTOR2_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_COLOR_ARRAY,
|
||||
OPCODE_ITERATE_OBJECT,
|
||||
OPCODE_ASSERT,
|
||||
OPCODE_BREAKPOINT,
|
||||
OPCODE_LINE,
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "gdscript_function.h"
|
||||
|
||||
#include "core/core_string_names.h"
|
||||
#include "core/os/os.h"
|
||||
#include "gdscript.h"
|
||||
#include "gdscript_functions.h"
|
||||
|
@ -185,93 +186,131 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
|||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define OPCODES_TABLE \
|
||||
static const void *switch_table_ops[] = { \
|
||||
&&OPCODE_OPERATOR, \
|
||||
&&OPCODE_OPERATOR_VALIDATED, \
|
||||
&&OPCODE_EXTENDS_TEST, \
|
||||
&&OPCODE_IS_BUILTIN, \
|
||||
&&OPCODE_SET_KEYED, \
|
||||
&&OPCODE_SET_KEYED_VALIDATED, \
|
||||
&&OPCODE_SET_INDEXED_VALIDATED, \
|
||||
&&OPCODE_GET_KEYED, \
|
||||
&&OPCODE_GET_KEYED_VALIDATED, \
|
||||
&&OPCODE_GET_INDEXED_VALIDATED, \
|
||||
&&OPCODE_SET_NAMED, \
|
||||
&&OPCODE_SET_NAMED_VALIDATED, \
|
||||
&&OPCODE_GET_NAMED, \
|
||||
&&OPCODE_GET_NAMED_VALIDATED, \
|
||||
&&OPCODE_SET_MEMBER, \
|
||||
&&OPCODE_GET_MEMBER, \
|
||||
&&OPCODE_ASSIGN, \
|
||||
&&OPCODE_ASSIGN_TRUE, \
|
||||
&&OPCODE_ASSIGN_FALSE, \
|
||||
&&OPCODE_ASSIGN_TYPED_BUILTIN, \
|
||||
&&OPCODE_ASSIGN_TYPED_NATIVE, \
|
||||
&&OPCODE_ASSIGN_TYPED_SCRIPT, \
|
||||
&&OPCODE_CAST_TO_BUILTIN, \
|
||||
&&OPCODE_CAST_TO_NATIVE, \
|
||||
&&OPCODE_CAST_TO_SCRIPT, \
|
||||
&&OPCODE_CONSTRUCT, \
|
||||
&&OPCODE_CONSTRUCT_ARRAY, \
|
||||
&&OPCODE_CONSTRUCT_DICTIONARY, \
|
||||
&&OPCODE_CALL, \
|
||||
&&OPCODE_CALL_RETURN, \
|
||||
&&OPCODE_CALL_ASYNC, \
|
||||
&&OPCODE_CALL_BUILT_IN, \
|
||||
&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED, \
|
||||
&&OPCODE_CALL_SELF_BASE, \
|
||||
&&OPCODE_CALL_METHOD_BIND, \
|
||||
&&OPCODE_CALL_METHOD_BIND_RET, \
|
||||
&&OPCODE_CALL_PTRCALL_NO_RETURN, \
|
||||
&&OPCODE_CALL_PTRCALL_BOOL, \
|
||||
&&OPCODE_CALL_PTRCALL_INT, \
|
||||
&&OPCODE_CALL_PTRCALL_FLOAT, \
|
||||
&&OPCODE_CALL_PTRCALL_STRING, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR2, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR2I, \
|
||||
&&OPCODE_CALL_PTRCALL_RECT2, \
|
||||
&&OPCODE_CALL_PTRCALL_RECT2I, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR3, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR3I, \
|
||||
&&OPCODE_CALL_PTRCALL_TRANSFORM2D, \
|
||||
&&OPCODE_CALL_PTRCALL_PLANE, \
|
||||
&&OPCODE_CALL_PTRCALL_QUAT, \
|
||||
&&OPCODE_CALL_PTRCALL_AABB, \
|
||||
&&OPCODE_CALL_PTRCALL_BASIS, \
|
||||
&&OPCODE_CALL_PTRCALL_TRANSFORM, \
|
||||
&&OPCODE_CALL_PTRCALL_COLOR, \
|
||||
&&OPCODE_CALL_PTRCALL_STRING_NAME, \
|
||||
&&OPCODE_CALL_PTRCALL_NODE_PATH, \
|
||||
&&OPCODE_CALL_PTRCALL_RID, \
|
||||
&&OPCODE_CALL_PTRCALL_OBJECT, \
|
||||
&&OPCODE_CALL_PTRCALL_CALLABLE, \
|
||||
&&OPCODE_CALL_PTRCALL_SIGNAL, \
|
||||
&&OPCODE_CALL_PTRCALL_DICTIONARY, \
|
||||
&&OPCODE_CALL_PTRCALL_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_AWAIT, \
|
||||
&&OPCODE_AWAIT_RESUME, \
|
||||
&&OPCODE_JUMP, \
|
||||
&&OPCODE_JUMP_IF, \
|
||||
&&OPCODE_JUMP_IF_NOT, \
|
||||
&&OPCODE_JUMP_TO_DEF_ARGUMENT, \
|
||||
&&OPCODE_RETURN, \
|
||||
&&OPCODE_ITERATE_BEGIN, \
|
||||
&&OPCODE_ITERATE, \
|
||||
&&OPCODE_ASSERT, \
|
||||
&&OPCODE_BREAKPOINT, \
|
||||
&&OPCODE_LINE, \
|
||||
&&OPCODE_END \
|
||||
}; \
|
||||
#define OPCODES_TABLE \
|
||||
static const void *switch_table_ops[] = { \
|
||||
&&OPCODE_OPERATOR, \
|
||||
&&OPCODE_OPERATOR_VALIDATED, \
|
||||
&&OPCODE_EXTENDS_TEST, \
|
||||
&&OPCODE_IS_BUILTIN, \
|
||||
&&OPCODE_SET_KEYED, \
|
||||
&&OPCODE_SET_KEYED_VALIDATED, \
|
||||
&&OPCODE_SET_INDEXED_VALIDATED, \
|
||||
&&OPCODE_GET_KEYED, \
|
||||
&&OPCODE_GET_KEYED_VALIDATED, \
|
||||
&&OPCODE_GET_INDEXED_VALIDATED, \
|
||||
&&OPCODE_SET_NAMED, \
|
||||
&&OPCODE_SET_NAMED_VALIDATED, \
|
||||
&&OPCODE_GET_NAMED, \
|
||||
&&OPCODE_GET_NAMED_VALIDATED, \
|
||||
&&OPCODE_SET_MEMBER, \
|
||||
&&OPCODE_GET_MEMBER, \
|
||||
&&OPCODE_ASSIGN, \
|
||||
&&OPCODE_ASSIGN_TRUE, \
|
||||
&&OPCODE_ASSIGN_FALSE, \
|
||||
&&OPCODE_ASSIGN_TYPED_BUILTIN, \
|
||||
&&OPCODE_ASSIGN_TYPED_NATIVE, \
|
||||
&&OPCODE_ASSIGN_TYPED_SCRIPT, \
|
||||
&&OPCODE_CAST_TO_BUILTIN, \
|
||||
&&OPCODE_CAST_TO_NATIVE, \
|
||||
&&OPCODE_CAST_TO_SCRIPT, \
|
||||
&&OPCODE_CONSTRUCT, \
|
||||
&&OPCODE_CONSTRUCT_ARRAY, \
|
||||
&&OPCODE_CONSTRUCT_DICTIONARY, \
|
||||
&&OPCODE_CALL, \
|
||||
&&OPCODE_CALL_RETURN, \
|
||||
&&OPCODE_CALL_ASYNC, \
|
||||
&&OPCODE_CALL_BUILT_IN, \
|
||||
&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED, \
|
||||
&&OPCODE_CALL_SELF_BASE, \
|
||||
&&OPCODE_CALL_METHOD_BIND, \
|
||||
&&OPCODE_CALL_METHOD_BIND_RET, \
|
||||
&&OPCODE_CALL_PTRCALL_NO_RETURN, \
|
||||
&&OPCODE_CALL_PTRCALL_BOOL, \
|
||||
&&OPCODE_CALL_PTRCALL_INT, \
|
||||
&&OPCODE_CALL_PTRCALL_FLOAT, \
|
||||
&&OPCODE_CALL_PTRCALL_STRING, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR2, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR2I, \
|
||||
&&OPCODE_CALL_PTRCALL_RECT2, \
|
||||
&&OPCODE_CALL_PTRCALL_RECT2I, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR3, \
|
||||
&&OPCODE_CALL_PTRCALL_VECTOR3I, \
|
||||
&&OPCODE_CALL_PTRCALL_TRANSFORM2D, \
|
||||
&&OPCODE_CALL_PTRCALL_PLANE, \
|
||||
&&OPCODE_CALL_PTRCALL_QUAT, \
|
||||
&&OPCODE_CALL_PTRCALL_AABB, \
|
||||
&&OPCODE_CALL_PTRCALL_BASIS, \
|
||||
&&OPCODE_CALL_PTRCALL_TRANSFORM, \
|
||||
&&OPCODE_CALL_PTRCALL_COLOR, \
|
||||
&&OPCODE_CALL_PTRCALL_STRING_NAME, \
|
||||
&&OPCODE_CALL_PTRCALL_NODE_PATH, \
|
||||
&&OPCODE_CALL_PTRCALL_RID, \
|
||||
&&OPCODE_CALL_PTRCALL_OBJECT, \
|
||||
&&OPCODE_CALL_PTRCALL_CALLABLE, \
|
||||
&&OPCODE_CALL_PTRCALL_SIGNAL, \
|
||||
&&OPCODE_CALL_PTRCALL_DICTIONARY, \
|
||||
&&OPCODE_CALL_PTRCALL_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY, \
|
||||
&&OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_AWAIT, \
|
||||
&&OPCODE_AWAIT_RESUME, \
|
||||
&&OPCODE_JUMP, \
|
||||
&&OPCODE_JUMP_IF, \
|
||||
&&OPCODE_JUMP_IF_NOT, \
|
||||
&&OPCODE_JUMP_TO_DEF_ARGUMENT, \
|
||||
&&OPCODE_RETURN, \
|
||||
&&OPCODE_ITERATE_BEGIN, \
|
||||
&&OPCODE_ITERATE_BEGIN_INT, \
|
||||
&&OPCODE_ITERATE_BEGIN_FLOAT, \
|
||||
&&OPCODE_ITERATE_BEGIN_VECTOR2, \
|
||||
&&OPCODE_ITERATE_BEGIN_VECTOR2I, \
|
||||
&&OPCODE_ITERATE_BEGIN_VECTOR3, \
|
||||
&&OPCODE_ITERATE_BEGIN_VECTOR3I, \
|
||||
&&OPCODE_ITERATE_BEGIN_STRING, \
|
||||
&&OPCODE_ITERATE_BEGIN_DICTIONARY, \
|
||||
&&OPCODE_ITERATE_BEGIN_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_ITERATE_BEGIN_OBJECT, \
|
||||
&&OPCODE_ITERATE, \
|
||||
&&OPCODE_ITERATE_INT, \
|
||||
&&OPCODE_ITERATE_FLOAT, \
|
||||
&&OPCODE_ITERATE_VECTOR2, \
|
||||
&&OPCODE_ITERATE_VECTOR2I, \
|
||||
&&OPCODE_ITERATE_VECTOR3, \
|
||||
&&OPCODE_ITERATE_VECTOR3I, \
|
||||
&&OPCODE_ITERATE_STRING, \
|
||||
&&OPCODE_ITERATE_DICTIONARY, \
|
||||
&&OPCODE_ITERATE_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_BYTE_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_INT32_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_INT64_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_STRING_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \
|
||||
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_ITERATE_OBJECT, \
|
||||
&&OPCODE_ASSERT, \
|
||||
&&OPCODE_BREAKPOINT, \
|
||||
&&OPCODE_LINE, \
|
||||
&&OPCODE_END \
|
||||
}; \
|
||||
static_assert((sizeof(switch_table_ops) / sizeof(switch_table_ops[0]) == (OPCODE_END + 1)), "Opcodes in jump table aren't the same as opcodes in enum.");
|
||||
|
||||
#define OPCODE(m_op) \
|
||||
|
@ -1979,6 +2018,344 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_INT) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
int64_t size = *VariantInternal::get_int(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::INT);
|
||||
*VariantInternal::get_int(counter) = 0;
|
||||
|
||||
if (size > 0) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::INT);
|
||||
*VariantInternal::get_int(iterator) = 0;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_FLOAT) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
double size = *VariantInternal::get_float(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::FLOAT);
|
||||
*VariantInternal::get_float(counter) = 0.0;
|
||||
|
||||
if (size > 0) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::FLOAT);
|
||||
*VariantInternal::get_float(iterator) = 0;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Vector2 *bounds = VariantInternal::get_vector2(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::FLOAT);
|
||||
*VariantInternal::get_float(counter) = bounds->x;
|
||||
|
||||
if (bounds->x < bounds->y) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::FLOAT);
|
||||
*VariantInternal::get_float(iterator) = bounds->x;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR2I) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Vector2i *bounds = VariantInternal::get_vector2i(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::FLOAT);
|
||||
*VariantInternal::get_int(counter) = bounds->x;
|
||||
|
||||
if (bounds->x < bounds->y) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::INT);
|
||||
*VariantInternal::get_int(iterator) = bounds->x;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Vector3 *bounds = VariantInternal::get_vector3(container);
|
||||
double from = bounds->x;
|
||||
double to = bounds->y;
|
||||
double step = bounds->z;
|
||||
|
||||
VariantInternal::initialize(counter, Variant::FLOAT);
|
||||
*VariantInternal::get_float(counter) = from;
|
||||
|
||||
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
|
||||
|
||||
if (do_continue) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::FLOAT);
|
||||
*VariantInternal::get_float(iterator) = from;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_VECTOR3I) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Vector3i *bounds = VariantInternal::get_vector3i(container);
|
||||
int64_t from = bounds->x;
|
||||
int64_t to = bounds->y;
|
||||
int64_t step = bounds->z;
|
||||
|
||||
VariantInternal::initialize(counter, Variant::INT);
|
||||
*VariantInternal::get_int(counter) = from;
|
||||
|
||||
bool do_continue = from == to ? false : (from < to ? step > 0 : step < 0);
|
||||
|
||||
if (do_continue) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::INT);
|
||||
*VariantInternal::get_int(iterator) = from;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_STRING) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
String *str = VariantInternal::get_string(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::INT);
|
||||
*VariantInternal::get_int(counter) = 0;
|
||||
|
||||
if (!str->empty()) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
VariantInternal::initialize(iterator, Variant::STRING);
|
||||
*VariantInternal::get_string(iterator) = str->substr(0, 1);
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_DICTIONARY) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Dictionary *dict = VariantInternal::get_dictionary(container);
|
||||
const Variant *next = dict->next(nullptr);
|
||||
*counter = *next;
|
||||
|
||||
if (!dict->empty()) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*iterator = *next;
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_ARRAY) {
|
||||
CHECK_SPACE(8); // Check space for iterate instruction too.
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
Array *array = VariantInternal::get_array(container);
|
||||
|
||||
VariantInternal::initialize(counter, Variant::INT);
|
||||
*VariantInternal::get_int(counter) = 0;
|
||||
|
||||
if (!array->empty()) {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*iterator = array->get(0);
|
||||
|
||||
// Skip regular iterate.
|
||||
ip += 5;
|
||||
} else {
|
||||
// Jump to end of loop.
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
#define OPCODE_ITERATE_BEGIN_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_var_ret_type, m_ret_type, m_ret_get_func) \
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_PACKED_##m_var_type##_ARRAY) { \
|
||||
CHECK_SPACE(8); \
|
||||
GET_INSTRUCTION_ARG(counter, 0); \
|
||||
GET_INSTRUCTION_ARG(container, 1); \
|
||||
Vector<m_elem_type> *array = VariantInternal::m_get_func(container); \
|
||||
VariantInternal::initialize(counter, Variant::INT); \
|
||||
*VariantInternal::get_int(counter) = 0; \
|
||||
if (!array->empty()) { \
|
||||
GET_INSTRUCTION_ARG(iterator, 2); \
|
||||
VariantInternal::initialize(iterator, Variant::m_var_ret_type); \
|
||||
m_ret_type *it = VariantInternal::m_ret_get_func(iterator); \
|
||||
*it = array->get(0); \
|
||||
ip += 5; \
|
||||
} else { \
|
||||
int jumpto = _code_ptr[ip + 4]; \
|
||||
GD_ERR_BREAK(jumpto<0 || jumpto> _code_size); \
|
||||
ip = jumpto; \
|
||||
} \
|
||||
} \
|
||||
DISPATCH_OPCODE
|
||||
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, INT, int64_t, get_int);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT32, int32_t, get_int32_array, INT, int64_t, get_int);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(INT64, int64_t, get_int64_array, INT, int64_t, get_int);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT32, float, get_float32_array, FLOAT, double, get_float);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(FLOAT64, double, get_float64_array, FLOAT, double, get_float);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(STRING, String, get_string_array, STRING, String, get_string);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, VECTOR2, Vector2, get_vector2);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, VECTOR3, Vector3, get_vector3);
|
||||
OPCODE_ITERATE_BEGIN_PACKED_ARRAY(COLOR, Color, get_color_array, COLOR, Color, get_color);
|
||||
|
||||
OPCODE(OPCODE_ITERATE_BEGIN_OBJECT) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool freed = false;
|
||||
Object *obj = container->get_validated_object_with_check(freed);
|
||||
if (freed) {
|
||||
err_text = "Trying to iterate on a previously freed object.";
|
||||
OPCODE_BREAK;
|
||||
} else if (!obj) {
|
||||
err_text = "Trying to iterate on a null value.";
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#else
|
||||
Object *obj = *VariantInternal::get_object(container);
|
||||
#endif
|
||||
Array ref;
|
||||
ref.push_back(*counter);
|
||||
Variant vref;
|
||||
VariantInternal::initialize(&vref, Variant::ARRAY);
|
||||
*VariantInternal::get_array(&vref) = ref;
|
||||
|
||||
Variant **args = instruction_args; // Overriding an instruction argument, but we don't need access to that anymore.
|
||||
args[0] = &vref;
|
||||
|
||||
Callable::CallError ce;
|
||||
Variant has_next = obj->call(CoreStringNames::get_singleton()->_iter_init, (const Variant **)args, 1, ce);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#endif
|
||||
if (!has_next.booleanize()) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*iterator = obj->call(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#endif
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
|
@ -2011,6 +2388,305 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_INT) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
int64_t size = *VariantInternal::get_int(container);
|
||||
int64_t *count = VariantInternal::get_int(counter);
|
||||
|
||||
(*count)++;
|
||||
|
||||
if (*count >= size) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_int(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_FLOAT) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
double size = *VariantInternal::get_float(container);
|
||||
double *count = VariantInternal::get_float(counter);
|
||||
|
||||
(*count)++;
|
||||
|
||||
if (*count >= size) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_float(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_VECTOR2) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Vector2 *bounds = VariantInternal::get_vector2((const Variant *)container);
|
||||
double *count = VariantInternal::get_float(counter);
|
||||
|
||||
(*count)++;
|
||||
|
||||
if (*count >= bounds->y) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_float(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_VECTOR2I) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Vector2i *bounds = VariantInternal::get_vector2i((const Variant *)container);
|
||||
int64_t *count = VariantInternal::get_int(counter);
|
||||
|
||||
(*count)++;
|
||||
|
||||
if (*count >= bounds->y) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_int(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_VECTOR3) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Vector3 *bounds = VariantInternal::get_vector3((const Variant *)container);
|
||||
double *count = VariantInternal::get_float(counter);
|
||||
|
||||
*count += bounds->z;
|
||||
|
||||
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_float(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_VECTOR3I) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Vector3i *bounds = VariantInternal::get_vector3i((const Variant *)container);
|
||||
int64_t *count = VariantInternal::get_int(counter);
|
||||
|
||||
*count += bounds->z;
|
||||
|
||||
if ((bounds->z < 0 && *count <= bounds->y) || (bounds->z > 0 && *count >= bounds->y)) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_int(iterator) = *count;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_STRING) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const String *str = VariantInternal::get_string((const Variant *)container);
|
||||
int64_t *idx = VariantInternal::get_int(counter);
|
||||
(*idx)++;
|
||||
|
||||
if (*idx >= str->length()) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*VariantInternal::get_string(iterator) = str->substr(*idx, 1);
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_DICTIONARY) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Dictionary *dict = VariantInternal::get_dictionary((const Variant *)container);
|
||||
const Variant *next = dict->next(counter);
|
||||
|
||||
if (!next) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*counter = *next;
|
||||
*iterator = *next;
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ITERATE_ARRAY) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
const Array *array = VariantInternal::get_array((const Variant *)container);
|
||||
int64_t *idx = VariantInternal::get_int(counter);
|
||||
(*idx)++;
|
||||
|
||||
if (*idx >= array->size()) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*iterator = array->get(*idx);
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
#define OPCODE_ITERATE_PACKED_ARRAY(m_var_type, m_elem_type, m_get_func, m_ret_get_func) \
|
||||
OPCODE(OPCODE_ITERATE_PACKED_##m_var_type##_ARRAY) { \
|
||||
CHECK_SPACE(4); \
|
||||
GET_INSTRUCTION_ARG(counter, 0); \
|
||||
GET_INSTRUCTION_ARG(container, 1); \
|
||||
const Vector<m_elem_type> *array = VariantInternal::m_get_func((const Variant *)container); \
|
||||
int64_t *idx = VariantInternal::get_int(counter); \
|
||||
(*idx)++; \
|
||||
if (*idx >= array->size()) { \
|
||||
int jumpto = _code_ptr[ip + 4]; \
|
||||
GD_ERR_BREAK(jumpto<0 || jumpto> _code_size); \
|
||||
ip = jumpto; \
|
||||
} else { \
|
||||
GET_INSTRUCTION_ARG(iterator, 2); \
|
||||
*VariantInternal::m_ret_get_func(iterator) = array->get(*idx); \
|
||||
ip += 5; \
|
||||
} \
|
||||
} \
|
||||
DISPATCH_OPCODE
|
||||
|
||||
OPCODE_ITERATE_PACKED_ARRAY(BYTE, uint8_t, get_byte_array, get_int);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(INT32, int32_t, get_int32_array, get_int);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(INT64, int64_t, get_int64_array, get_int);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(FLOAT32, float, get_float32_array, get_float);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(FLOAT64, double, get_float64_array, get_float);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(STRING, String, get_string_array, get_string);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(VECTOR2, Vector2, get_vector2_array, get_vector2);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(VECTOR3, Vector3, get_vector3_array, get_vector3);
|
||||
OPCODE_ITERATE_PACKED_ARRAY(COLOR, Color, get_color_array, get_color);
|
||||
|
||||
OPCODE(OPCODE_ITERATE_OBJECT) {
|
||||
CHECK_SPACE(4);
|
||||
|
||||
GET_INSTRUCTION_ARG(counter, 0);
|
||||
GET_INSTRUCTION_ARG(container, 1);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
bool freed = false;
|
||||
Object *obj = container->get_validated_object_with_check(freed);
|
||||
if (freed) {
|
||||
err_text = "Trying to iterate on a previously freed object.";
|
||||
OPCODE_BREAK;
|
||||
} else if (!obj) {
|
||||
err_text = "Trying to iterate on a null value.";
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#else
|
||||
Object *obj = *VariantInternal::get_object(container);
|
||||
#endif
|
||||
Array ref;
|
||||
ref.push_back(*counter);
|
||||
Variant vref;
|
||||
VariantInternal::initialize(&vref, Variant::ARRAY);
|
||||
*VariantInternal::get_array(&vref) = ref;
|
||||
|
||||
Variant **args = instruction_args; // Overriding an instruction argument, but we don't need access to that anymore.
|
||||
args[0] = &vref;
|
||||
|
||||
Callable::CallError ce;
|
||||
Variant has_next = obj->call(CoreStringNames::get_singleton()->_iter_next, (const Variant **)args, 1, ce);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
err_text = vformat(R"(There was an error calling "_iter_next" on iterator object of type %s.)", *container);
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#endif
|
||||
if (!has_next.booleanize()) {
|
||||
int jumpto = _code_ptr[ip + 4];
|
||||
GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
|
||||
ip = jumpto;
|
||||
} else {
|
||||
GET_INSTRUCTION_ARG(iterator, 2);
|
||||
*iterator = obj->call(CoreStringNames::get_singleton()->_iter_get, (const Variant **)args, 1, ce);
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (ce.error != Callable::CallError::CALL_OK) {
|
||||
err_text = vformat(R"(There was an error calling "_iter_get" on iterator object of type %s.)", *container);
|
||||
OPCODE_BREAK;
|
||||
}
|
||||
#endif
|
||||
|
||||
ip += 5; // Loop again.
|
||||
}
|
||||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
OPCODE(OPCODE_ASSERT) {
|
||||
CHECK_SPACE(3);
|
||||
|
||||
|
|
Loading…
Reference in a new issue