diff options
Diffstat (limited to 'modules/gdscript/gd_compiler.cpp')
-rw-r--r-- | modules/gdscript/gd_compiler.cpp | 132 |
1 files changed, 102 insertions, 30 deletions
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index dd2834bf34..e6dd9d9ae1 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -60,7 +60,8 @@ bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::Operato codegen.opcodes.push_back(GDFunction::OPCODE_OPERATOR); // perform operator codegen.opcodes.push_back(op); //which operator codegen.opcodes.push_back(src_address_a); // argument 1 - codegen.opcodes.push_back(GDFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter) + codegen.opcodes.push_back(src_address_a); // argument 2 (repeated) + //codegen.opcodes.push_back(GDFunction::ADDR_TYPE_NIL); // argument 2 (unary only takes one parameter) return true; } @@ -185,51 +186,59 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre //TRY CLASS CONSTANTS - GDScript *scr = codegen.script; - GDNativeClass *nc=NULL; - while(scr) { + GDScript *owner = codegen.script; + while (owner) { - if (scr->constants.has(identifier)) { + GDScript *scr = owner; + GDNativeClass *nc=NULL; + while(scr) { - //int idx=scr->constants[identifier]; - int idx = codegen.get_name_map_pos(identifier); - return idx|(GDFunction::ADDR_TYPE_CLASS_CONSTANT<<GDFunction::ADDR_BITS); //argument (stack root) + if (scr->constants.has(identifier)) { + + //int idx=scr->constants[identifier]; + int idx = codegen.get_name_map_pos(identifier); + return idx|(GDFunction::ADDR_TYPE_CLASS_CONSTANT<<GDFunction::ADDR_BITS); //argument (stack root) + } + if (scr->native.is_valid()) + nc=scr->native.ptr(); + scr=scr->_base; } - if (scr->native.is_valid()) - nc=scr->native.ptr(); - scr=scr->_base; - } - // CLASS C++ Integer Constant + // CLASS C++ Integer Constant - if (nc) { + if (nc) { - bool success=false; - int constant = ObjectTypeDB::get_integer_constant(nc->get_name(),identifier,&success); - if (success) { - Variant key=constant; - int idx; + bool success=false; + int constant = ObjectTypeDB::get_integer_constant(nc->get_name(),identifier,&success); + if (success) { + Variant key=constant; + int idx; - if (!codegen.constant_map.has(key)) { + if (!codegen.constant_map.has(key)) { - idx=codegen.constant_map.size(); - codegen.constant_map[key]=idx; + idx=codegen.constant_map.size(); + codegen.constant_map[key]=idx; - } else { - idx=codegen.constant_map[key]; + } else { + idx=codegen.constant_map[key]; + } + + return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access) } - return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access) } + owner=owner->_owner; } - if (codegen.script->subclasses.has(identifier)) { + /* + handled in constants now + if (codegen.script->subclasses.has(identifier)) { //same with a subclass, make it a local constant. int idx = codegen.get_constant_pos(codegen.script->subclasses[identifier]); return idx|(GDFunction::ADDR_TYPE_LOCAL_CONSTANT<<GDFunction::ADDR_BITS); //make it a local constant (faster access) - } + }*/ if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) { @@ -452,6 +461,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre const GDParser::Node *instance = on->arguments[0]; + bool in_static=false; if (instance->type==GDParser::Node::TYPE_SELF) { //room for optimization @@ -465,7 +475,10 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre int ret; - if (i==1) { + if (i==0 && on->arguments[i]->type==GDParser::Node::TYPE_SELF && codegen.function_node && codegen.function_node->_static) { + //static call to self + ret=(GDFunction::ADDR_TYPE_CLASS<<GDFunction::ADDR_BITS); + } else if (i==1) { if (on->arguments[i]->type!=GDParser::Node::TYPE_IDENTIFIER) { _set_error("Attempt to call a non-identifier.",on); @@ -475,6 +488,7 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre ret=codegen.get_name_map_pos(id->name); } else { + ret = _parse_expression(codegen,on->arguments[i],slevel); if (ret<0) return ret; @@ -494,6 +508,34 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre codegen.opcodes.push_back(arguments[i]); } } break; + case GDParser::OperatorNode::OP_YIELD: { + + + ERR_FAIL_COND_V(on->arguments.size() && on->arguments.size()!=2,-1); + + Vector<int> arguments; + int slevel = p_stack_level; + for(int i=0;i<on->arguments.size();i++) { + + int ret = _parse_expression(codegen,on->arguments[i],slevel); + if (ret<0) + return ret; + if (ret&GDFunction::ADDR_TYPE_STACK<<GDFunction::ADDR_BITS) { + slevel++; + codegen.alloc_stack(slevel); + } + arguments.push_back(ret); + } + + //push call bytecode + codegen.opcodes.push_back(arguments.size()==0?GDFunction::OPCODE_YIELD:GDFunction::OPCODE_YIELD_SIGNAL); // basic type constructor + for(int i=0;i<arguments.size();i++) + codegen.opcodes.push_back(arguments[i]); //arguments + codegen.opcodes.push_back(GDFunction::OPCODE_YIELD_RESUME); + //next will be where to place the result :) + + } break; + //indexing operator case GDParser::OperatorNode::OP_INDEX: case GDParser::OperatorNode::OP_INDEX_NAMED: { @@ -631,8 +673,8 @@ int GDCompiler::_parse_expression(CodeGen& codegen,const GDParser::Node *p_expre case GDParser::OperatorNode::OP_BIT_OR: { if (!_create_binary_operator(codegen,on,Variant::OP_BIT_OR,p_stack_level)) return -1;} break; case GDParser::OperatorNode::OP_BIT_XOR: { if (!_create_binary_operator(codegen,on,Variant::OP_BIT_XOR,p_stack_level)) return -1;} break; //shift - case GDParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break; - case GDParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break; + case GDParser::OperatorNode::OP_SHIFT_LEFT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_LEFT,p_stack_level)) return -1;} break; + case GDParser::OperatorNode::OP_SHIFT_RIGHT: { if (!_create_binary_operator(codegen,on,Variant::OP_SHIFT_RIGHT,p_stack_level)) return -1;} break; //assignment operators case GDParser::OperatorNode::OP_ASSIGN_ADD: case GDParser::OperatorNode::OP_ASSIGN_SUB: @@ -1250,6 +1292,16 @@ Error GDCompiler::_parse_function(GDScript *p_script,const GDParser::ClassNode * gdfunc->name=func_name; gdfunc->_script=p_script; gdfunc->source=source; + +#ifdef DEBUG_ENABLED + + { + gdfunc->func_cname=(String(source)+" - "+String(func_name)).utf8(); + gdfunc->_func_cname=gdfunc->func_cname.get_data(); + + } + +#endif if (p_func) { gdfunc->_initial_line=p_func->line; } else { @@ -1298,11 +1350,26 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars if (path!="") { //path (and optionally subclasses) + if (path.is_rel_path()) { + + String base = p_script->get_path(); + if (base=="" || base.is_rel_path()) { + _set_error("Could not resolve relative path for parent class: "+path,p_class); + return ERR_FILE_NOT_FOUND; + } + path=base.get_base_dir().plus_file(path); + } script = ResourceLoader::load(path); if (script.is_null()) { _set_error("Could not load base class: "+path,p_class); return ERR_FILE_NOT_FOUND; } + if (!script->valid) { + + _set_error("Script not fully loaded (cyclic preload?): "+path,p_class); + return ERR_BUSY; + } + //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); if (p_class->extends_class.size()) { @@ -1405,6 +1472,9 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars } + //print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size())); + + for(int i=0;i<p_class->variables.size();i++) { StringName name = p_class->variables[i].identifier; @@ -1452,6 +1522,8 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars Error err = _parse_class(subclass.ptr(),p_script,p_class->subclasses[i]); if (err) return err; + + p_script->constants.insert(name,subclass); //once parsed, goes to the list of constants p_script->subclasses.insert(name,subclass); } |