| 1897 | } |
| 1898 | |
| 1899 | Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::SuiteNode *p_block, bool p_add_locals, bool p_clear_locals) { |
| 1900 | Error err = OK; |
| 1901 | GDScriptCodeGenerator *gen = codegen.generator; |
| 1902 | List<GDScriptCodeGenerator::Address> block_locals; |
| 1903 | |
| 1904 | gen->clear_temporaries(); |
| 1905 | codegen.start_block(); |
| 1906 | |
| 1907 | if (p_add_locals) { |
| 1908 | block_locals = _add_block_locals(codegen, p_block); |
| 1909 | } |
| 1910 | |
| 1911 | for (int i = 0; i < p_block->statements.size(); i++) { |
| 1912 | const GDScriptParser::Node *s = p_block->statements[i]; |
| 1913 | |
| 1914 | gen->write_newline(s->start_line); |
| 1915 | |
| 1916 | switch (s->type) { |
| 1917 | case GDScriptParser::Node::MATCH: { |
| 1918 | const GDScriptParser::MatchNode *match = static_cast<const GDScriptParser::MatchNode *>(s); |
| 1919 | |
| 1920 | codegen.start_block(); // Add an extra block, since @special locals belong to the match scope. |
| 1921 | |
| 1922 | // Evaluate the match expression. |
| 1923 | GDScriptCodeGenerator::Address value = codegen.add_local("@match_value", _gdtype_from_datatype(match->test->get_datatype(), codegen.script)); |
| 1924 | GDScriptCodeGenerator::Address value_expr = _parse_expression(codegen, err, match->test); |
| 1925 | if (err) { |
| 1926 | return err; |
| 1927 | } |
| 1928 | |
| 1929 | /// Assign to local. |
| 1930 | /// @todo This can be improved by passing the target to parse_expression(). |
| 1931 | gen->write_assign(value, value_expr); |
| 1932 | |
| 1933 | if (value_expr.mode == GDScriptCodeGenerator::Address::TEMPORARY) { |
| 1934 | codegen.generator->pop_temporary(); |
| 1935 | } |
| 1936 | |
| 1937 | // Then, let's save the type of the value in the stack too, so we can reuse for later comparisons. |
| 1938 | GDScriptDataType typeof_type; |
| 1939 | typeof_type.has_type = true; |
| 1940 | typeof_type.kind = GDScriptDataType::BUILTIN; |
| 1941 | typeof_type.builtin_type = Variant::INT; |
| 1942 | GDScriptCodeGenerator::Address type = codegen.add_local("@match_type", typeof_type); |
| 1943 | |
| 1944 | Vector<GDScriptCodeGenerator::Address> typeof_args; |
| 1945 | typeof_args.push_back(value); |
| 1946 | gen->write_call_utility(type, "typeof", typeof_args); |
| 1947 | |
| 1948 | // Now we can actually start testing. |
| 1949 | // For each branch. |
| 1950 | for (int j = 0; j < match->branches.size(); j++) { |
| 1951 | if (j > 0) { |
| 1952 | // Use `else` to not check the next branch after matching. |
| 1953 | gen->write_else(); |
| 1954 | } |
| 1955 | |
| 1956 | const GDScriptParser::MatchBranchNode *branch = match->branches[j]; |
nothing calls this directly
no test coverage detected