You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-13 13:31:48 +00:00
Merge pull request #71914 from vnen/gdscript-no-continue-match
GDScript: Remove function of `continue` for match statement
This commit is contained in:
@@ -1543,28 +1543,6 @@ void GDScriptByteCodeGenerator::write_endwhile() {
|
|||||||
current_breaks_to_patch.pop_back();
|
current_breaks_to_patch.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::start_match() {
|
|
||||||
match_continues_to_patch.push_back(List<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::start_match_branch() {
|
|
||||||
// Patch continue statements.
|
|
||||||
for (const int &E : match_continues_to_patch.back()->get()) {
|
|
||||||
patch_jump(E);
|
|
||||||
}
|
|
||||||
match_continues_to_patch.pop_back();
|
|
||||||
// Start a new list for next branch.
|
|
||||||
match_continues_to_patch.push_back(List<int>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::end_match() {
|
|
||||||
// Patch continue statements.
|
|
||||||
for (const int &E : match_continues_to_patch.back()->get()) {
|
|
||||||
patch_jump(E);
|
|
||||||
}
|
|
||||||
match_continues_to_patch.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::write_break() {
|
void GDScriptByteCodeGenerator::write_break() {
|
||||||
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
||||||
current_breaks_to_patch.back()->get().push_back(opcodes.size());
|
current_breaks_to_patch.back()->get().push_back(opcodes.size());
|
||||||
@@ -1576,12 +1554,6 @@ void GDScriptByteCodeGenerator::write_continue() {
|
|||||||
append(continue_addrs.back()->get());
|
append(continue_addrs.back()->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::write_continue_match() {
|
|
||||||
append_opcode(GDScriptFunction::OPCODE_JUMP);
|
|
||||||
match_continues_to_patch.back()->get().push_back(opcodes.size());
|
|
||||||
append(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GDScriptByteCodeGenerator::write_breakpoint() {
|
void GDScriptByteCodeGenerator::write_breakpoint() {
|
||||||
append_opcode(GDScriptFunction::OPCODE_BREAKPOINT);
|
append_opcode(GDScriptFunction::OPCODE_BREAKPOINT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||||||
List<int> ternary_jump_skip_pos;
|
List<int> ternary_jump_skip_pos;
|
||||||
|
|
||||||
List<List<int>> current_breaks_to_patch;
|
List<List<int>> current_breaks_to_patch;
|
||||||
List<List<int>> match_continues_to_patch;
|
|
||||||
|
|
||||||
void add_stack_identifier(const StringName &p_id, int p_stackpos) {
|
void add_stack_identifier(const StringName &p_id, int p_stackpos) {
|
||||||
if (locals.size() > max_locals) {
|
if (locals.size() > max_locals) {
|
||||||
@@ -496,12 +495,8 @@ public:
|
|||||||
virtual void start_while_condition() override;
|
virtual void start_while_condition() override;
|
||||||
virtual void write_while(const Address &p_condition) override;
|
virtual void write_while(const Address &p_condition) override;
|
||||||
virtual void write_endwhile() override;
|
virtual void write_endwhile() override;
|
||||||
virtual void start_match() override;
|
|
||||||
virtual void start_match_branch() override;
|
|
||||||
virtual void end_match() override;
|
|
||||||
virtual void write_break() override;
|
virtual void write_break() override;
|
||||||
virtual void write_continue() override;
|
virtual void write_continue() override;
|
||||||
virtual void write_continue_match() override;
|
|
||||||
virtual void write_breakpoint() override;
|
virtual void write_breakpoint() override;
|
||||||
virtual void write_newline(int p_line) override;
|
virtual void write_newline(int p_line) override;
|
||||||
virtual void write_return(const Address &p_return_value) override;
|
virtual void write_return(const Address &p_return_value) override;
|
||||||
|
|||||||
@@ -148,12 +148,8 @@ public:
|
|||||||
virtual void start_while_condition() = 0; // Used to allow a jump to the expression evaluation.
|
virtual void start_while_condition() = 0; // Used to allow a jump to the expression evaluation.
|
||||||
virtual void write_while(const Address &p_condition) = 0;
|
virtual void write_while(const Address &p_condition) = 0;
|
||||||
virtual void write_endwhile() = 0;
|
virtual void write_endwhile() = 0;
|
||||||
virtual void start_match() = 0;
|
|
||||||
virtual void start_match_branch() = 0;
|
|
||||||
virtual void end_match() = 0;
|
|
||||||
virtual void write_break() = 0;
|
virtual void write_break() = 0;
|
||||||
virtual void write_continue() = 0;
|
virtual void write_continue() = 0;
|
||||||
virtual void write_continue_match() = 0;
|
|
||||||
virtual void write_breakpoint() = 0;
|
virtual void write_breakpoint() = 0;
|
||||||
virtual void write_newline(int p_line) = 0;
|
virtual void write_newline(int p_line) = 0;
|
||||||
virtual void write_return(const Address &p_return_value) = 0;
|
virtual void write_return(const Address &p_return_value) = 0;
|
||||||
|
|||||||
@@ -1679,7 +1679,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||||||
case GDScriptParser::Node::MATCH: {
|
case GDScriptParser::Node::MATCH: {
|
||||||
const GDScriptParser::MatchNode *match = static_cast<const GDScriptParser::MatchNode *>(s);
|
const GDScriptParser::MatchNode *match = static_cast<const GDScriptParser::MatchNode *>(s);
|
||||||
|
|
||||||
gen->start_match();
|
|
||||||
codegen.start_block();
|
codegen.start_block();
|
||||||
|
|
||||||
// Evaluate the match expression.
|
// Evaluate the match expression.
|
||||||
@@ -1718,7 +1717,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||||||
|
|
||||||
const GDScriptParser::MatchBranchNode *branch = match->branches[j];
|
const GDScriptParser::MatchBranchNode *branch = match->branches[j];
|
||||||
|
|
||||||
gen->start_match_branch(); // Need so lower level code can patch 'continue' jumps.
|
|
||||||
codegen.start_block(); // Create an extra block around for binds.
|
codegen.start_block(); // Create an extra block around for binds.
|
||||||
|
|
||||||
// Add locals in block before patterns, so temporaries don't use the stack address for binds.
|
// Add locals in block before patterns, so temporaries don't use the stack address for binds.
|
||||||
@@ -1756,8 +1754,6 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||||||
for (int j = 0; j < match->branches.size(); j++) {
|
for (int j = 0; j < match->branches.size(); j++) {
|
||||||
gen->write_endif();
|
gen->write_endif();
|
||||||
}
|
}
|
||||||
|
|
||||||
gen->end_match();
|
|
||||||
} break;
|
} break;
|
||||||
case GDScriptParser::Node::IF: {
|
case GDScriptParser::Node::IF: {
|
||||||
const GDScriptParser::IfNode *if_n = static_cast<const GDScriptParser::IfNode *>(s);
|
const GDScriptParser::IfNode *if_n = static_cast<const GDScriptParser::IfNode *>(s);
|
||||||
@@ -1845,12 +1841,7 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Sui
|
|||||||
gen->write_break();
|
gen->write_break();
|
||||||
} break;
|
} break;
|
||||||
case GDScriptParser::Node::CONTINUE: {
|
case GDScriptParser::Node::CONTINUE: {
|
||||||
const GDScriptParser::ContinueNode *cont = static_cast<const GDScriptParser::ContinueNode *>(s);
|
gen->write_continue();
|
||||||
if (cont->is_for_match) {
|
|
||||||
gen->write_continue_match();
|
|
||||||
} else {
|
|
||||||
gen->write_continue();
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case GDScriptParser::Node::RETURN: {
|
case GDScriptParser::Node::RETURN: {
|
||||||
const GDScriptParser::ReturnNode *return_n = static_cast<const GDScriptParser::ReturnNode *>(s);
|
const GDScriptParser::ReturnNode *return_n = static_cast<const GDScriptParser::ReturnNode *>(s);
|
||||||
|
|||||||
@@ -1789,11 +1789,10 @@ GDScriptParser::BreakNode *GDScriptParser::parse_break() {
|
|||||||
|
|
||||||
GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
|
GDScriptParser::ContinueNode *GDScriptParser::parse_continue() {
|
||||||
if (!can_continue) {
|
if (!can_continue) {
|
||||||
push_error(R"(Cannot use "continue" outside of a loop or pattern matching block.)");
|
push_error(R"(Cannot use "continue" outside of a loop.)");
|
||||||
}
|
}
|
||||||
current_suite->has_continue = true;
|
current_suite->has_continue = true;
|
||||||
ContinueNode *cont = alloc_node<ContinueNode>();
|
ContinueNode *cont = alloc_node<ContinueNode>();
|
||||||
cont->is_for_match = is_continue_match;
|
|
||||||
complete_extents(cont);
|
complete_extents(cont);
|
||||||
end_statement(R"("continue")");
|
end_statement(R"("continue")");
|
||||||
return cont;
|
return cont;
|
||||||
@@ -1819,12 +1818,10 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
|
|||||||
// Save break/continue state.
|
// Save break/continue state.
|
||||||
bool could_break = can_break;
|
bool could_break = can_break;
|
||||||
bool could_continue = can_continue;
|
bool could_continue = can_continue;
|
||||||
bool was_continue_match = is_continue_match;
|
|
||||||
|
|
||||||
// Allow break/continue.
|
// Allow break/continue.
|
||||||
can_break = true;
|
can_break = true;
|
||||||
can_continue = true;
|
can_continue = true;
|
||||||
is_continue_match = false;
|
|
||||||
|
|
||||||
SuiteNode *suite = alloc_node<SuiteNode>();
|
SuiteNode *suite = alloc_node<SuiteNode>();
|
||||||
if (n_for->variable) {
|
if (n_for->variable) {
|
||||||
@@ -1842,7 +1839,6 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() {
|
|||||||
// Reset break/continue state.
|
// Reset break/continue state.
|
||||||
can_break = could_break;
|
can_break = could_break;
|
||||||
can_continue = could_continue;
|
can_continue = could_continue;
|
||||||
is_continue_match = was_continue_match;
|
|
||||||
|
|
||||||
return n_for;
|
return n_for;
|
||||||
}
|
}
|
||||||
@@ -1979,13 +1975,6 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save continue state.
|
|
||||||
bool could_continue = can_continue;
|
|
||||||
bool was_continue_match = is_continue_match;
|
|
||||||
// Allow continue for match.
|
|
||||||
can_continue = true;
|
|
||||||
is_continue_match = true;
|
|
||||||
|
|
||||||
SuiteNode *suite = alloc_node<SuiteNode>();
|
SuiteNode *suite = alloc_node<SuiteNode>();
|
||||||
if (branch->patterns.size() > 0) {
|
if (branch->patterns.size() > 0) {
|
||||||
for (const KeyValue<StringName, IdentifierNode *> &E : branch->patterns[0]->binds) {
|
for (const KeyValue<StringName, IdentifierNode *> &E : branch->patterns[0]->binds) {
|
||||||
@@ -1998,10 +1987,6 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() {
|
|||||||
branch->block = parse_suite("match pattern block", suite);
|
branch->block = parse_suite("match pattern block", suite);
|
||||||
complete_extents(branch);
|
complete_extents(branch);
|
||||||
|
|
||||||
// Restore continue state.
|
|
||||||
can_continue = could_continue;
|
|
||||||
is_continue_match = was_continue_match;
|
|
||||||
|
|
||||||
return branch;
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2160,12 +2145,10 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
|
|||||||
// Save break/continue state.
|
// Save break/continue state.
|
||||||
bool could_break = can_break;
|
bool could_break = can_break;
|
||||||
bool could_continue = can_continue;
|
bool could_continue = can_continue;
|
||||||
bool was_continue_match = is_continue_match;
|
|
||||||
|
|
||||||
// Allow break/continue.
|
// Allow break/continue.
|
||||||
can_break = true;
|
can_break = true;
|
||||||
can_continue = true;
|
can_continue = true;
|
||||||
is_continue_match = false;
|
|
||||||
|
|
||||||
n_while->loop = parse_suite(R"("while" block)");
|
n_while->loop = parse_suite(R"("while" block)");
|
||||||
n_while->loop->is_loop = true;
|
n_while->loop->is_loop = true;
|
||||||
@@ -2174,7 +2157,6 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() {
|
|||||||
// Reset break/continue state.
|
// Reset break/continue state.
|
||||||
can_break = could_break;
|
can_break = could_break;
|
||||||
can_continue = could_continue;
|
can_continue = could_continue;
|
||||||
is_continue_match = was_continue_match;
|
|
||||||
|
|
||||||
return n_while;
|
return n_while;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -758,7 +758,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ContinueNode : public Node {
|
struct ContinueNode : public Node {
|
||||||
bool is_for_match = false;
|
|
||||||
ContinueNode() {
|
ContinueNode() {
|
||||||
type = CONTINUE;
|
type = CONTINUE;
|
||||||
}
|
}
|
||||||
@@ -1254,7 +1253,6 @@ private:
|
|||||||
bool panic_mode = false;
|
bool panic_mode = false;
|
||||||
bool can_break = false;
|
bool can_break = false;
|
||||||
bool can_continue = false;
|
bool can_continue = false;
|
||||||
bool is_continue_match = false; // Whether a `continue` will act on a `match`.
|
|
||||||
List<bool> multiline_stack;
|
List<bool> multiline_stack;
|
||||||
|
|
||||||
ClassNode *head = nullptr;
|
ClassNode *head = nullptr;
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ func test():
|
|||||||
match i:
|
match i:
|
||||||
"Hello":
|
"Hello":
|
||||||
print("hello")
|
print("hello")
|
||||||
# This will fall through to the default case below.
|
|
||||||
continue
|
|
||||||
"Good bye":
|
"Good bye":
|
||||||
print("bye")
|
print("bye")
|
||||||
_:
|
_:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
GDTEST_OK
|
GDTEST_OK
|
||||||
hello
|
hello
|
||||||
default
|
|
||||||
This will match
|
This will match
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ func test():
|
|||||||
1234:
|
1234:
|
||||||
print("2")
|
print("2")
|
||||||
match number:
|
match number:
|
||||||
1234:
|
4321:
|
||||||
print("3")
|
print("Should not be printed")
|
||||||
continue
|
|
||||||
_:
|
_:
|
||||||
print("Should also be printed")
|
print("3")
|
||||||
match number:
|
match number:
|
||||||
1234:
|
1234:
|
||||||
print("4")
|
print("4")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ GDTEST_OK
|
|||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
Should also be printed
|
|
||||||
4
|
4
|
||||||
5
|
5
|
||||||
6
|
6
|
||||||
|
|||||||
Reference in New Issue
Block a user