From 9379cbc774805fca0ea563617eaa55af048419a4 Mon Sep 17 00:00:00 2001 From: Chaosus Date: Mon, 15 Jul 2019 18:47:22 +0300 Subject: Added local array initializer --- drivers/gles2/shader_compiler_gles2.cpp | 16 +++ drivers/gles3/shader_compiler_gles3.cpp | 16 +++ servers/visual/shader_language.cpp | 197 +++++++++++++++++++++++++++++--- servers/visual/shader_language.h | 2 + 4 files changed, 216 insertions(+), 15 deletions(-) diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index af88d0172a..df7eee2301 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -531,6 +531,22 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener declaration += "["; declaration += itos(var_dec_node->declarations[i].size); declaration += "]"; + int sz = var_dec_node->declarations[i].initializer.size(); + if (sz > 0) { + declaration += "="; + declaration += _typestr(var_dec_node->datatype); + declaration += "["; + declaration += itos(sz); + declaration += "]"; + declaration += "("; + for (int j = 0; j < sz; j++) { + declaration += _dump_node_code(var_dec_node->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (j != sz - 1) { + declaration += ", "; + } + } + declaration += ")"; + } } code += declaration.as_string(); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index ae68f0a06d..f826bdf5a2 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -622,6 +622,22 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener declaration += "["; declaration += itos(vdnode->declarations[i].size); declaration += "]"; + int sz = vdnode->declarations[i].initializer.size(); + if (sz > 0) { + declaration += "="; + declaration += _typestr(vdnode->datatype); + declaration += "["; + declaration += itos(sz); + declaration += "]"; + declaration += "("; + for (int j = 0; j < sz; j++) { + declaration += _dump_node_code(vdnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (j != sz - 1) { + declaration += ", "; + } + } + declaration += ")"; + } } code += declaration; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 58028962b1..c39a0d4d02 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -785,6 +785,17 @@ ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_ty return PRECISION_MEDIUMP; } +String ShaderLanguage::get_precision_name(DataPrecision p_type) { + switch (p_type) { + case PRECISION_LOWP: return "lowp"; + case PRECISION_MEDIUMP: return "mediump"; + case PRECISION_HIGHP: return "highp"; + default: + break; + } + return ""; +} + String ShaderLanguage::get_datatype_name(DataType p_type) { switch (p_type) { @@ -3803,6 +3814,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map(); node->datatype = type; @@ -3815,22 +3827,181 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map 0"); - return ERR_PARSE_ERROR; - } + if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; + } else { - tk = _get_token(); + if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { + _set_error("Expected integer constant > 0 or ']'"); + return ERR_PARSE_ERROR; + } - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; + tk = _get_token(); + + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + + decl.size = ((uint32_t)tk.constant); + var.array_size = decl.size; } - decl.size = ((uint32_t)tk.constant); - var.array_size = decl.size; + bool full_def = false; tk = _get_token(); + if (tk.type == TK_OP_ASSIGN) { + tk = _get_token(); + + if (tk.type != TK_CURLY_BRACKET_OPEN) { + + if (unknown_size) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + + full_def = true; + + DataPrecision precision2 = PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision2 = get_token_precision(tk.type); + tk = _get_token(); + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precision"); + return ERR_PARSE_ERROR; + } + } + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return ERR_PARSE_ERROR; + } + DataType type2 = get_token_datatype(tk.type); + + int array_size2 = 0; + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size2 = cnode->values[0].sint; + if (array_size2 <= 0) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']"); + return ERR_PARSE_ERROR; + } else { + tk = _get_token(); + } + } else { + _set_error("Expected '["); + return ERR_PARSE_ERROR; + } + + if (precision != precision2 || type != type2 || var.array_size != array_size2) { + String error_str = "Cannot convert from '"; + if (precision2 != PRECISION_DEFAULT) { + error_str += get_precision_name(precision2); + error_str += " "; + } + error_str += get_datatype_name(type2); + error_str += "["; + error_str += itos(array_size2); + error_str += "]'"; + error_str += " to '"; + if (precision != PRECISION_DEFAULT) { + error_str += get_precision_name(precision); + error_str += " "; + } + error_str += get_datatype_name(type); + error_str += "["; + error_str += itos(var.array_size); + error_str += "]'"; + _set_error(error_str); + return ERR_PARSE_ERROR; + } + } + + bool curly = tk.type == TK_CURLY_BRACKET_OPEN; + + if (unknown_size) { + if (!curly) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + } else { + if (full_def) { + if (curly) { + _set_error("Expected '('"); + return ERR_PARSE_ERROR; + } + } + } + + if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization + while (true) { + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) { + return ERR_PARSE_ERROR; + } + if (n->type != Node::TYPE_CONSTANT) { + _set_error("Expected constant expression in the array declaration"); + return ERR_PARSE_ERROR; + } + + if (var.type != n->get_datatype()) { + _set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + decl.initializer.push_back(n); + continue; + } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) { + decl.initializer.push_back(n); + break; + } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) { + decl.initializer.push_back(n); + break; + } else { + if (curly) + _set_error("Expected '}' or ','"); + else + _set_error("Expected ')' or ','"); + return ERR_PARSE_ERROR; + } + } + if (unknown_size) { + decl.size = decl.initializer.size(); + var.array_size = decl.initializer.size(); + } else if (decl.initializer.size() != var.array_size) { + _set_error("Array size mismatch"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } + } else { + if (unknown_size) { + _set_error("Expected array initialization"); + return ERR_PARSE_ERROR; + } + } + node->declarations.push_back(decl); } else if (tk.type == TK_OP_ASSIGN) { @@ -3878,11 +4049,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map initializer; }; Vector declarations; @@ -588,6 +589,7 @@ public: static DataInterpolation get_token_interpolation(TokenType p_type); static bool is_token_precision(TokenType p_type); static DataPrecision get_token_precision(TokenType p_type); + static String get_precision_name(DataPrecision p_type); static String get_datatype_name(DataType p_type); static bool is_token_nonvoid_datatype(TokenType p_type); static bool is_token_operator(TokenType p_type); -- cgit v1.2.3