This commit is contained in:
parent
54e81c7955
commit
7eb8760477
@ -438,26 +438,44 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
|||||||
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
|
SL::BlockNode *bnode = (SL::BlockNode *)p_node;
|
||||||
|
|
||||||
//variables
|
//variables
|
||||||
code += _mktab(p_level - 1) + "{\n";
|
if (!bnode->single_statement) {
|
||||||
for (Map<StringName, SL::BlockNode::Variable>::Element *E = bnode->variables.front(); E; E = E->next()) {
|
code += _mktab(p_level - 1) + "{\n";
|
||||||
|
|
||||||
code += _mktab(p_level) + _prestr(E->get().precision) + _typestr(E->get().type) + " " + _mkid(E->key()) + ";\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < bnode->statements.size(); i++) {
|
for (int i = 0; i < bnode->statements.size(); i++) {
|
||||||
|
|
||||||
String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions);
|
String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions);
|
||||||
|
|
||||||
if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW) {
|
if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement ) {
|
||||||
// FIXME: if (A || A) ? I am hesitant to delete one of them, could be copy-paste error.
|
|
||||||
code += scode; //use directly
|
code += scode; //use directly
|
||||||
} else {
|
} else {
|
||||||
code += _mktab(p_level) + scode + ";\n";
|
code += _mktab(p_level) + scode + ";\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code += _mktab(p_level - 1) + "}\n";
|
if (!bnode->single_statement) {
|
||||||
|
code += _mktab(p_level - 1) + "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
case SL::Node::TYPE_VARIABLE_DECLARATION: {
|
||||||
|
SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node;
|
||||||
|
|
||||||
|
String declaration = _prestr(vdnode->precision) + _typestr(vdnode->datatype);
|
||||||
|
for(int i=0;i<vdnode->declarations.size();i++) {
|
||||||
|
if (i>0) {
|
||||||
|
declaration+=",";
|
||||||
|
} else {
|
||||||
|
declaration+=" ";
|
||||||
|
}
|
||||||
|
declaration += _mkid(vdnode->declarations[i].name);
|
||||||
|
if (vdnode->declarations[i].initializer) {
|
||||||
|
declaration+="=";
|
||||||
|
declaration+=_dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code+=declaration;
|
||||||
|
} break;
|
||||||
case SL::Node::TYPE_VARIABLE: {
|
case SL::Node::TYPE_VARIABLE: {
|
||||||
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
|
SL::VariableNode *vnode = (SL::VariableNode *)p_node;
|
||||||
|
|
||||||
@ -600,6 +618,13 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
|||||||
|
|
||||||
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions) + ")\n";
|
code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions) + ")\n";
|
||||||
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions);
|
code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions);
|
||||||
|
} 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);
|
||||||
|
String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions);
|
||||||
|
String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions);
|
||||||
|
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);
|
||||||
|
|
||||||
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
|
} else if (cfnode->flow_op == SL::FLOW_OP_RETURN) {
|
||||||
|
|
||||||
@ -611,6 +636,12 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
|
|||||||
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
|
} else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) {
|
||||||
|
|
||||||
code = "discard;";
|
code = "discard;";
|
||||||
|
} else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) {
|
||||||
|
|
||||||
|
code = "continue;";
|
||||||
|
} else if (cfnode->flow_op == SL::FLOW_OP_BREAK) {
|
||||||
|
|
||||||
|
code = "break;";
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -79,7 +79,11 @@ String ShaderLanguage::get_operator_text(Operator p_op) {
|
|||||||
"|",
|
"|",
|
||||||
"^",
|
"^",
|
||||||
"~",
|
"~",
|
||||||
"++"
|
"++",
|
||||||
|
"--",
|
||||||
|
"?",
|
||||||
|
":",
|
||||||
|
"++",
|
||||||
"--",
|
"--",
|
||||||
"()",
|
"()",
|
||||||
"construct",
|
"construct",
|
||||||
@ -3116,6 +3120,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
|
VariableDeclarationNode *vardecl = alloc_node<VariableDeclarationNode>();
|
||||||
|
vardecl->datatype=type;
|
||||||
|
vardecl->precision=precision;
|
||||||
|
|
||||||
|
p_block->statements.push_back(vardecl);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
if (tk.type != TK_IDENTIFIER) {
|
if (tk.type != TK_IDENTIFIER) {
|
||||||
@ -3133,8 +3143,14 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
var.type = type;
|
var.type = type;
|
||||||
var.precision = precision;
|
var.precision = precision;
|
||||||
var.line = tk_line;
|
var.line = tk_line;
|
||||||
|
|
||||||
p_block->variables[name] = var;
|
p_block->variables[name] = var;
|
||||||
|
|
||||||
|
VariableDeclarationNode::Declaration decl;
|
||||||
|
|
||||||
|
decl.name=name;
|
||||||
|
decl.initializer=NULL;
|
||||||
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
if (tk.type == TK_OP_ASSIGN) {
|
if (tk.type == TK_OP_ASSIGN) {
|
||||||
@ -3143,22 +3159,19 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
if (!n)
|
if (!n)
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
|
|
||||||
OperatorNode *assign = alloc_node<OperatorNode>();
|
decl.initializer = n;
|
||||||
VariableNode *vnode = alloc_node<VariableNode>();
|
|
||||||
vnode->name = name;
|
if (var.type!=n->get_datatype()) {
|
||||||
vnode->datatype_cache = type;
|
_set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(var.type) + "'");
|
||||||
assign->arguments.push_back(vnode);
|
return ERR_PARSE_ERROR;
|
||||||
assign->arguments.push_back(n);
|
|
||||||
assign->op = OP_ASSIGN;
|
}
|
||||||
p_block->statements.push_back(assign);
|
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
|
|
||||||
if (!_validate_operator(assign)) {
|
|
||||||
_set_error("Invalid assignment of '" + get_datatype_name(n->get_datatype()) + "' to '" + get_datatype_name(type) + "'");
|
|
||||||
return ERR_PARSE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vardecl->declarations.push_back(decl);
|
||||||
|
|
||||||
if (tk.type == TK_COMMA) {
|
if (tk.type == TK_COMMA) {
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
//another variable
|
//another variable
|
||||||
@ -3221,7 +3234,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
//if () {}
|
//if () {}
|
||||||
tk = _get_token();
|
tk = _get_token();
|
||||||
if (tk.type != TK_PARENTHESIS_OPEN) {
|
if (tk.type != TK_PARENTHESIS_OPEN) {
|
||||||
_set_error("Expected '(' after if");
|
_set_error("Expected '(' after while");
|
||||||
return ERR_PARSE_ERROR;
|
return ERR_PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3243,7 +3256,64 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
cf->blocks.push_back(block);
|
cf->blocks.push_back(block);
|
||||||
p_block->statements.push_back(cf);
|
p_block->statements.push_back(cf);
|
||||||
|
|
||||||
Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue);
|
Error err = _parse_block(block, p_builtin_types, true, true, true);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
} else if (tk.type == TK_CF_FOR) {
|
||||||
|
//if () {}
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_PARENTHESIS_OPEN) {
|
||||||
|
_set_error("Expected '(' after for");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlowNode *cf = alloc_node<ControlFlowNode>();
|
||||||
|
cf->flow_op = FLOW_OP_FOR;
|
||||||
|
|
||||||
|
BlockNode *init_block = alloc_node<BlockNode>();
|
||||||
|
init_block->parent_block = p_block;
|
||||||
|
init_block->single_statement=true;
|
||||||
|
cf->blocks.push_back(init_block);
|
||||||
|
if (_parse_block(init_block,p_builtin_types,true,false,false)!=OK) {
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *n = _parse_and_reduce_expression(init_block, p_builtin_types);
|
||||||
|
if (!n)
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
|
||||||
|
if (n->get_datatype()!=TYPE_BOOL) {
|
||||||
|
_set_error("Middle expression is expected to be boolean.");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_SEMICOLON) {
|
||||||
|
_set_error("Expected ';' after middle expression");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cf->expressions.push_back(n);
|
||||||
|
|
||||||
|
n = _parse_and_reduce_expression(init_block, p_builtin_types);
|
||||||
|
if (!n)
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
|
||||||
|
cf->expressions.push_back(n);
|
||||||
|
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_PARENTHESIS_CLOSE) {
|
||||||
|
_set_error("Expected ')' after third expression");
|
||||||
|
return ERR_PARSE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockNode *block = alloc_node<BlockNode>();
|
||||||
|
block->parent_block = p_block;
|
||||||
|
cf->blocks.push_back(block);
|
||||||
|
p_block->statements.push_back(cf);
|
||||||
|
|
||||||
|
Error err = _parse_block(block, p_builtin_types, true, true, true);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -3319,6 +3389,44 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Dat
|
|||||||
_set_error("Expected ';' after discard");
|
_set_error("Expected ';' after discard");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p_block->statements.push_back(flow);
|
||||||
|
} else if (tk.type == TK_CF_BREAK) {
|
||||||
|
|
||||||
|
|
||||||
|
if (!p_can_break) {
|
||||||
|
//all is good
|
||||||
|
_set_error("Breaking is not allowed here");
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
|
||||||
|
flow->flow_op = FLOW_OP_BREAK;
|
||||||
|
|
||||||
|
pos = _get_tkpos();
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_SEMICOLON) {
|
||||||
|
//all is good
|
||||||
|
_set_error("Expected ';' after break");
|
||||||
|
}
|
||||||
|
|
||||||
|
p_block->statements.push_back(flow);
|
||||||
|
} else if (tk.type == TK_CF_CONTINUE) {
|
||||||
|
|
||||||
|
|
||||||
|
if (!p_can_break) {
|
||||||
|
//all is good
|
||||||
|
_set_error("Contiuning is not allowed here");
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlFlowNode *flow = alloc_node<ControlFlowNode>();
|
||||||
|
flow->flow_op = FLOW_OP_CONTINUE;
|
||||||
|
|
||||||
|
pos = _get_tkpos();
|
||||||
|
tk = _get_token();
|
||||||
|
if (tk.type != TK_SEMICOLON) {
|
||||||
|
//all is good
|
||||||
|
_set_error("Expected ';' after continue");
|
||||||
|
}
|
||||||
|
|
||||||
p_block->statements.push_back(flow);
|
p_block->statements.push_back(flow);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -266,6 +266,7 @@ public:
|
|||||||
TYPE_FUNCTION,
|
TYPE_FUNCTION,
|
||||||
TYPE_BLOCK,
|
TYPE_BLOCK,
|
||||||
TYPE_VARIABLE,
|
TYPE_VARIABLE,
|
||||||
|
TYPE_VARIABLE_DECLARATION,
|
||||||
TYPE_CONSTANT,
|
TYPE_CONSTANT,
|
||||||
TYPE_OPERATOR,
|
TYPE_OPERATOR,
|
||||||
TYPE_CONTROL_FLOW,
|
TYPE_CONTROL_FLOW,
|
||||||
@ -315,6 +316,25 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VariableDeclarationNode : public Node {
|
||||||
|
|
||||||
|
DataPrecision precision;
|
||||||
|
DataType datatype;
|
||||||
|
|
||||||
|
struct Declaration {
|
||||||
|
|
||||||
|
StringName name;
|
||||||
|
Node *initializer;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<Declaration> declarations;
|
||||||
|
virtual DataType get_datatype() const { return datatype; }
|
||||||
|
|
||||||
|
VariableDeclarationNode() {
|
||||||
|
type = TYPE_VARIABLE_DECLARATION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct ConstantNode : public Node {
|
struct ConstantNode : public Node {
|
||||||
|
|
||||||
DataType datatype;
|
DataType datatype;
|
||||||
@ -346,10 +366,12 @@ public:
|
|||||||
|
|
||||||
Map<StringName, Variable> variables;
|
Map<StringName, Variable> variables;
|
||||||
List<Node *> statements;
|
List<Node *> statements;
|
||||||
|
bool single_statement;
|
||||||
BlockNode() {
|
BlockNode() {
|
||||||
type = TYPE_BLOCK;
|
type = TYPE_BLOCK;
|
||||||
parent_block = NULL;
|
parent_block = NULL;
|
||||||
parent_function = NULL;
|
parent_function = NULL;
|
||||||
|
single_statement=false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user