Skip to content

Commit

Permalink
Allow multiple declarations in for loop in a shader
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaosus committed Feb 3, 2022
1 parent 6de5baf commit 58696fd
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 53 deletions.
9 changes: 6 additions & 3 deletions servers/rendering/shader_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene

if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) {
code += scode; //use directly
if (bnode->use_comma_between_statements && i + 1 < bnode->statements.size()) {
code += ",";
}
} else {
code += _mktab(p_level) + scode + ";\n";
}
Expand Down Expand Up @@ -1287,10 +1290,10 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
} else if (cfnode->flow_op == SL::FLOW_OP_FOR) {
String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String middle = _dump_node_code(cfnode->blocks[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
String right = _dump_node_code(cfnode->blocks[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning);
code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n";
code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);
code += _dump_node_code(cfnode->blocks[3], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning);

} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
if (cfnode->expressions.size()) {
Expand Down
134 changes: 85 additions & 49 deletions servers/rendering/shader_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5252,21 +5252,32 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
expression.push_back(e);
continue;
} else {
if (tk.type != TK_SEMICOLON) {
_set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk)));
return nullptr;
} else {
#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
_add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning."));
}
#endif // DEBUG_ENABLED
bool valid = false;
if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION && tk.type == TK_PARENTHESIS_CLOSE) {
valid = true;
_set_tkpos(prepos);

OperatorNode *func = alloc_node<OperatorNode>();
func->op = OP_EMPTY;
expr = func;
}
if (!valid) {
if (tk.type != TK_SEMICOLON) {
_set_error(vformat(RTR("Expected expression, found: '%s'."), get_token_text(tk)));
return nullptr;
} else {
#ifdef DEBUG_ENABLED
if (check_warnings && HAS_WARNING(ShaderWarning::FORMATTING_ERROR_FLAG)) {
_add_line_warning(ShaderWarning::FORMATTING_ERROR, RTR("Empty statement. Remove ';' to fix this warning."));
}
#endif // DEBUG_ENABLED
_set_tkpos(prepos);

OperatorNode *func = alloc_node<OperatorNode>();
func->op = OP_EMPTY;
expr = func;
}
}
}

ERR_FAIL_COND_V(!expr, nullptr);
Expand Down Expand Up @@ -6769,14 +6780,9 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
array_size = 0;
}

if (tk.type == TK_COMMA) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR) {
_set_error(vformat("Multiple declarations in '%s' loop are not supported.", "for"));
return ERR_PARSE_ERROR;
}
} else if (tk.type == TK_SEMICOLON) {
if (tk.type == TK_SEMICOLON) {
break;
} else {
} else if (tk.type != TK_COMMA) {
_set_expected_error(",", ";");
return ERR_PARSE_ERROR;
}
Expand Down Expand Up @@ -7138,52 +7144,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
cf->flow_op = FLOW_OP_FOR;

BlockNode *init_block = alloc_node<BlockNode>();
init_block->block_type = BlockNode::BLOCK_TYPE_FOR;
init_block->block_type = BlockNode::BLOCK_TYPE_FOR_INIT;
init_block->parent_block = p_block;
init_block->single_statement = true;
cf->blocks.push_back(init_block);
if (_parse_block(init_block, p_function_info, true, false, false) != OK) {
return ERR_PARSE_ERROR;
}

Node *n = _parse_and_reduce_expression(init_block, p_function_info);
if (!n) {
return ERR_PARSE_ERROR;
}

if (n->get_datatype() != TYPE_BOOL) {
_set_error(RTR("The middle expression is expected to be boolean."));
return ERR_PARSE_ERROR;
}

tk = _get_token();
if (tk.type != TK_SEMICOLON) {
_set_expected_error(";");
return ERR_PARSE_ERROR;
Error err = _parse_block(init_block, p_function_info, true, false, false);
if (err != OK) {
return err;
}

cf->expressions.push_back(n);

n = _parse_and_reduce_expression(init_block, p_function_info);
if (!n) {
return ERR_PARSE_ERROR;
BlockNode *condition_block = alloc_node<BlockNode>();
condition_block->block_type = BlockNode::BLOCK_TYPE_FOR_CONDITION;
condition_block->parent_block = init_block;
condition_block->single_statement = true;
condition_block->use_comma_between_statements = true;
cf->blocks.push_back(condition_block);
err = _parse_block(condition_block, p_function_info, true, false, false);
if (err != OK) {
return err;
}

cf->expressions.push_back(n);

tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
_set_expected_error(")");
return ERR_PARSE_ERROR;
BlockNode *expression_block = alloc_node<BlockNode>();
expression_block->block_type = BlockNode::BLOCK_TYPE_FOR_EXPRESSION;
expression_block->parent_block = init_block;
expression_block->single_statement = true;
expression_block->use_comma_between_statements = true;
cf->blocks.push_back(expression_block);
err = _parse_block(expression_block, p_function_info, true, false, false);
if (err != OK) {
return err;
}

BlockNode *block = alloc_node<BlockNode>();
block->parent_block = init_block;
cf->blocks.push_back(block);
p_block->statements.push_back(cf);

Error err = _parse_block(block, p_function_info, true, true, true);
if (err) {
err = _parse_block(block, p_function_info, true, true, true);
if (err != OK) {
return err;
}

Expand Down Expand Up @@ -7333,10 +7331,48 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!expr) {
return ERR_PARSE_ERROR;
}

bool empty = false;

if (expr->type == Node::TYPE_OPERATOR) {
OperatorNode *op = static_cast<OperatorNode *>(expr);
if (op->op == OP_EMPTY) {
empty = true;
}
}
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_INIT) {
if (!empty && expr->type != BlockNode::TYPE_VARIABLE_DECLARATION) {
_set_error(RTR("The left expression is expected to be a variable declaration."));
return ERR_PARSE_ERROR;
}
}
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION) {
if (!empty && expr->get_datatype() != TYPE_BOOL) {
_set_error(RTR("The middle expression is expected to be boolean."));
return ERR_PARSE_ERROR;
}
}

p_block->statements.push_back(expr);
tk = _get_token();

if (tk.type != TK_SEMICOLON) {
if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_CONDITION) {
if (tk.type == TK_COMMA) {
continue;
}
if (tk.type != TK_SEMICOLON) {
_set_expected_error(",", ";");
return ERR_PARSE_ERROR;
}
} else if (p_block->block_type == BlockNode::BLOCK_TYPE_FOR_EXPRESSION) {
if (tk.type == TK_COMMA) {
continue;
}
if (tk.type != TK_PARENTHESIS_CLOSE) {
_set_expected_error(",", ")");
return ERR_PARSE_ERROR;
}
} else if (tk.type != TK_SEMICOLON) {
_set_expected_error(";");
return ERR_PARSE_ERROR;
}
Expand Down
5 changes: 4 additions & 1 deletion servers/rendering/shader_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,9 @@ class ShaderLanguage {

enum BlockType {
BLOCK_TYPE_STANDART,
BLOCK_TYPE_FOR,
BLOCK_TYPE_FOR_INIT,
BLOCK_TYPE_FOR_CONDITION,
BLOCK_TYPE_FOR_EXPRESSION,
BLOCK_TYPE_SWITCH,
BLOCK_TYPE_CASE,
BLOCK_TYPE_DEFAULT,
Expand All @@ -526,6 +528,7 @@ class ShaderLanguage {
Map<StringName, Variable> variables;
List<Node *> statements;
bool single_statement = false;
bool use_comma_between_statements = false;

BlockNode() :
Node(TYPE_BLOCK) {}
Expand Down

0 comments on commit 58696fd

Please sign in to comment.