|
@@ -1542,16 +1542,35 @@ void GDScriptByteCodeGenerator::write_end_jump_if_shared() {
|
|
if_jmp_addrs.pop_back();
|
|
if_jmp_addrs.pop_back();
|
|
}
|
|
}
|
|
|
|
|
|
-void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) {
|
|
|
|
|
|
+void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type, bool p_is_range) {
|
|
Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type);
|
|
Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type);
|
|
- Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type);
|
|
|
|
|
|
|
|
// Store state.
|
|
// Store state.
|
|
for_counter_variables.push_back(counter);
|
|
for_counter_variables.push_back(counter);
|
|
- for_container_variables.push_back(container);
|
|
|
|
|
|
+
|
|
|
|
+ if (p_is_range) {
|
|
|
|
+ GDScriptDataType int_type;
|
|
|
|
+ int_type.has_type = true;
|
|
|
|
+ int_type.kind = GDScriptDataType::BUILTIN;
|
|
|
|
+ int_type.builtin_type = Variant::INT;
|
|
|
|
+
|
|
|
|
+ Address range_from(Address::LOCAL_VARIABLE, add_local("@range_from", int_type), int_type);
|
|
|
|
+ Address range_to(Address::LOCAL_VARIABLE, add_local("@range_to", int_type), int_type);
|
|
|
|
+ Address range_step(Address::LOCAL_VARIABLE, add_local("@range_step", int_type), int_type);
|
|
|
|
+
|
|
|
|
+ // Store state.
|
|
|
|
+ for_range_from_variables.push_back(range_from);
|
|
|
|
+ for_range_to_variables.push_back(range_to);
|
|
|
|
+ for_range_step_variables.push_back(range_step);
|
|
|
|
+ } else {
|
|
|
|
+ Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type);
|
|
|
|
+
|
|
|
|
+ // Store state.
|
|
|
|
+ for_container_variables.push_back(container);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-void GDScriptByteCodeGenerator::write_for_assignment(const Address &p_list) {
|
|
|
|
|
|
+void GDScriptByteCodeGenerator::write_for_list_assignment(const Address &p_list) {
|
|
const Address &container = for_container_variables.back()->get();
|
|
const Address &container = for_container_variables.back()->get();
|
|
|
|
|
|
// Assign container.
|
|
// Assign container.
|
|
@@ -1560,16 +1579,33 @@ void GDScriptByteCodeGenerator::write_for_assignment(const Address &p_list) {
|
|
append(p_list);
|
|
append(p_list);
|
|
}
|
|
}
|
|
|
|
|
|
-void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_conversion) {
|
|
|
|
|
|
+void GDScriptByteCodeGenerator::write_for_range_assignment(const Address &p_from, const Address &p_to, const Address &p_step) {
|
|
|
|
+ const Address &range_from = for_range_from_variables.back()->get();
|
|
|
|
+ const Address &range_to = for_range_to_variables.back()->get();
|
|
|
|
+ const Address &range_step = for_range_step_variables.back()->get();
|
|
|
|
+
|
|
|
|
+ // Assign range args.
|
|
|
|
+ write_assign(range_from, p_from);
|
|
|
|
+ write_assign(range_to, p_to);
|
|
|
|
+ write_assign(range_step, p_step);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_conversion, bool p_is_range) {
|
|
const Address &counter = for_counter_variables.back()->get();
|
|
const Address &counter = for_counter_variables.back()->get();
|
|
- const Address &container = for_container_variables.back()->get();
|
|
|
|
|
|
+ const Address &container = p_is_range ? Address() : for_container_variables.back()->get();
|
|
|
|
+ const Address &range_from = p_is_range ? for_range_from_variables.back()->get() : Address();
|
|
|
|
+ const Address &range_to = p_is_range ? for_range_to_variables.back()->get() : Address();
|
|
|
|
+ const Address &range_step = p_is_range ? for_range_step_variables.back()->get() : Address();
|
|
|
|
|
|
current_breaks_to_patch.push_back(List<int>());
|
|
current_breaks_to_patch.push_back(List<int>());
|
|
|
|
|
|
GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
|
|
GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
|
|
GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
|
|
GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
|
|
|
|
|
|
- if (container.type.has_type) {
|
|
|
|
|
|
+ if (p_is_range) {
|
|
|
|
+ begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_RANGE;
|
|
|
|
+ iterate_opcode = GDScriptFunction::OPCODE_ITERATE_RANGE;
|
|
|
|
+ } else if (container.type.has_type) {
|
|
if (container.type.kind == GDScriptDataType::BUILTIN) {
|
|
if (container.type.kind == GDScriptDataType::BUILTIN) {
|
|
switch (container.type.builtin_type) {
|
|
switch (container.type.builtin_type) {
|
|
case Variant::INT:
|
|
case Variant::INT:
|
|
@@ -1665,19 +1701,30 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_
|
|
// Begin loop.
|
|
// Begin loop.
|
|
append_opcode(begin_opcode);
|
|
append_opcode(begin_opcode);
|
|
append(counter);
|
|
append(counter);
|
|
- append(container);
|
|
|
|
|
|
+ if (p_is_range) {
|
|
|
|
+ append(range_from);
|
|
|
|
+ append(range_to);
|
|
|
|
+ append(range_step);
|
|
|
|
+ } else {
|
|
|
|
+ append(container);
|
|
|
|
+ }
|
|
append(p_use_conversion ? temp : p_variable);
|
|
append(p_use_conversion ? temp : p_variable);
|
|
for_jmp_addrs.push_back(opcodes.size());
|
|
for_jmp_addrs.push_back(opcodes.size());
|
|
append(0); // End of loop address, will be patched.
|
|
append(0); // End of loop address, will be patched.
|
|
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
|
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
|
- append(opcodes.size() + 6); // Skip over 'continue' code.
|
|
|
|
|
|
+ append(opcodes.size() + (p_is_range ? 7 : 6)); // Skip over 'continue' code.
|
|
|
|
|
|
// Next iteration.
|
|
// Next iteration.
|
|
int continue_addr = opcodes.size();
|
|
int continue_addr = opcodes.size();
|
|
continue_addrs.push_back(continue_addr);
|
|
continue_addrs.push_back(continue_addr);
|
|
append_opcode(iterate_opcode);
|
|
append_opcode(iterate_opcode);
|
|
append(counter);
|
|
append(counter);
|
|
- append(container);
|
|
|
|
|
|
+ if (p_is_range) {
|
|
|
|
+ append(range_to);
|
|
|
|
+ append(range_step);
|
|
|
|
+ } else {
|
|
|
|
+ append(container);
|
|
|
|
+ }
|
|
append(p_use_conversion ? temp : p_variable);
|
|
append(p_use_conversion ? temp : p_variable);
|
|
for_jmp_addrs.push_back(opcodes.size());
|
|
for_jmp_addrs.push_back(opcodes.size());
|
|
append(0); // Jump destination, will be patched.
|
|
append(0); // Jump destination, will be patched.
|
|
@@ -1690,7 +1737,7 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void GDScriptByteCodeGenerator::write_endfor() {
|
|
|
|
|
|
+void GDScriptByteCodeGenerator::write_endfor(bool p_is_range) {
|
|
// Jump back to loop check.
|
|
// Jump back to loop check.
|
|
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
|
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
|
append(continue_addrs.back()->get());
|
|
append(continue_addrs.back()->get());
|
|
@@ -1710,7 +1757,13 @@ void GDScriptByteCodeGenerator::write_endfor() {
|
|
|
|
|
|
// Pop state.
|
|
// Pop state.
|
|
for_counter_variables.pop_back();
|
|
for_counter_variables.pop_back();
|
|
- for_container_variables.pop_back();
|
|
|
|
|
|
+ if (p_is_range) {
|
|
|
|
+ for_range_from_variables.pop_back();
|
|
|
|
+ for_range_to_variables.pop_back();
|
|
|
|
+ for_range_step_variables.pop_back();
|
|
|
|
+ } else {
|
|
|
|
+ for_container_variables.pop_back();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
void GDScriptByteCodeGenerator::start_while_condition() {
|
|
void GDScriptByteCodeGenerator::start_while_condition() {
|